PageRenderTime 33ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/external/fieldtrip/trunk/utilities/ft_checkdata.m

http://open-realtime-fmri.googlecode.com/
MATLAB | 1688 lines | 1385 code | 107 blank | 196 comment | 240 complexity | bc50b48bacae739c80c0c901763def8e MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. function [data] = ft_checkdata(data, varargin)
  2. % FT_CHECKDATA checks the input data of the main FieldTrip functions, e.g. whether
  3. % the type of data strucure corresponds with the required data. If neccessary
  4. % and possible, this function will adjust the data structure to the input
  5. % requirements (e.g. change dimord, average over trials, convert inside from
  6. % index into logical).
  7. %
  8. % If the input data does NOT correspond to the requirements, this function
  9. % is supposed to give a elaborate warning message and if applicable point
  10. % the user to external documentation (link to website).
  11. %
  12. % Use as
  13. % [data] = ft_checkdata(data, ...)
  14. %
  15. % Optional input arguments should be specified as key-value pairs and can include
  16. % feedback = yes, no
  17. % datatype = raw, freq, timelock, comp, spike, source, volume, dip
  18. % dimord = any combination of time, freq, chan, refchan, rpt, subj, chancmb, rpttap, pos
  19. % senstype = ctf151, ctf275, ctf151_planar, ctf275_planar, neuromag122, neuromag306, bti148, bti248, bti248_planar, magnetometer, electrode
  20. % inside = logical, index
  21. % ismeg = yes, no
  22. % hastrials = yes, no
  23. % hasunits = yes, no
  24. % hastrialdef = yes, no
  25. % hasoffset = yes, no (only applies to raw data)
  26. % hascumtapcnt = yes, no (only applies to freq data)
  27. % hasdof = yes, no
  28. % cmbrepresentation = sparse, full (applies to covariance and cross-spectral density)
  29. %
  30. % For some options you can specify multiple values, e.g.
  31. % [data] = ft_checkdata(data, 'senstype', {'ctf151', 'ctf275'}), e.g. in megrealign
  32. % [data] = ft_checkdata(data, 'datatype', {'timelock', 'freq'}), e.g. in sourceanalysis
  33. % Copyright (C) 2007-2009, Robert Oostenveld
  34. %
  35. % This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
  36. % for the documentation and details.
  37. %
  38. % FieldTrip is free software: you can redistribute it and/or modify
  39. % it under the terms of the GNU General Public License as published by
  40. % the Free Software Foundation, either version 3 of the License, or
  41. % (at your option) any later version.
  42. %
  43. % FieldTrip is distributed in the hope that it will be useful,
  44. % but WITHOUT ANY WARRANTY; without even the implied warranty of
  45. % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  46. % GNU General Public License for more details.
  47. %
  48. % You should have received a copy of the GNU General Publhasoffsetic License
  49. % along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
  50. %
  51. % $Id: ft_checkdata.m 3093 2011-03-12 19:44:25Z jansch $
  52. % in case of an error this function could use dbstack for more detailled
  53. % user feedback
  54. %
  55. % this function should replace/encapsulate
  56. % fixdimord
  57. % fixinside
  58. % fixprecision
  59. % fixvolume
  60. % data2raw
  61. % raw2data
  62. % grid2transform
  63. % transform2grid
  64. % fourier2crsspctrm
  65. % freq2cumtapcnt
  66. % sensortype
  67. % time2offset
  68. % offset2time
  69. %
  70. % other potential uses for this function:
  71. % time -> offset in freqanalysis
  72. % average over trials
  73. % csd as matrix
  74. % get the optional input arguments
  75. feedback = keyval('feedback', varargin); if isempty(feedback), feedback = 'no'; end
  76. dtype = keyval('datatype', varargin); % should not conflict with the ft_datatype function
  77. dimord = keyval('dimord', varargin);
  78. stype = keyval('senstype', varargin); % senstype is a function name which should not be masked
  79. ismeg = keyval('ismeg', varargin);
  80. inside = keyval('inside', varargin); % can be logical or index
  81. hastrials = keyval('hastrials', varargin);
  82. hasunits = keyval('hasunits', varargin);
  83. hastrialdef = keyval('hastrialdef', varargin); if isempty(hastrialdef), hastrialdef = 'no'; end
  84. hasoffset = keyval('hasoffset', varargin); if isempty(hasoffset), hasoffset = 'no'; end
  85. hasdimord = keyval('hasdimord', varargin); if isempty(hasdimord), hasdimord = 'no'; end
  86. hascumtapcnt = keyval('hascumtapcnt', varargin);
  87. hasdof = keyval('hasdof', varargin); if isempty(hasdof), hasdof = 'no'; end
  88. haspow = keyval('haspow', varargin); if isempty(haspow), haspow = 'no'; end
  89. cmbrepresentation = keyval('cmbrepresentation', varargin);
  90. channelcmb = keyval('channelcmb', varargin);
  91. sourcedimord = keyval('sourcedimord', varargin);
  92. sourcerepresentation = keyval('sourcerepresentation', varargin);
  93. % determine the type of input data
  94. % this can be raw, freq, timelock, comp, spike, source, volume, dip
  95. israw = ft_datatype(data, 'raw');
  96. isfreq = ft_datatype(data, 'freq');
  97. istimelock = ft_datatype(data, 'timelock');
  98. iscomp = ft_datatype(data, 'comp');
  99. isspike = ft_datatype(data, 'spike');
  100. isvolume = ft_datatype(data, 'volume');
  101. issource = ft_datatype(data, 'source');
  102. isdip = ft_datatype(data, 'dip');
  103. ismvar = ft_datatype(data, 'mvar');
  104. isfreqmvar = ft_datatype(data, 'freqmvar');
  105. % FIXME use the istrue function on ismeg and hasxxx options
  106. if ~isequal(feedback, 'no')
  107. if israw
  108. nchan = length(data.label);
  109. ntrial = length(data.trial);
  110. fprintf('the input is raw data with %d channels and %d trials\n', nchan, ntrial);
  111. elseif isfreq
  112. nchan = length(data.label);
  113. nfreq = length(data.freq);
  114. if isfield(data, 'time'), ntime = num2str(length(data.time)); else ntime = 'no'; end
  115. fprintf('the input is freq data with %d channels, %d frequencybins and %s timebins\n', nchan, nfreq, ntime);
  116. elseif istimelock
  117. nchan = length(data.label);
  118. ntime = length(data.time);
  119. fprintf('the input is timelock data with %d channels and %d timebins\n', nchan, ntime);
  120. elseif iscomp
  121. ncomp = length(data.label);
  122. nchan = length(data.topolabel);
  123. fprintf('the input is component data with %d components and %d original channels\n', ncomp, nchan);
  124. elseif isspike
  125. nchan = length(data.label);
  126. fprintf('the input is spike data\n');
  127. elseif isvolume
  128. fprintf('the input is volume data with dimensions [%d %d %d]\n', data.dim(1), data.dim(2), data.dim(3));
  129. elseif issource
  130. nsource = size(data.pos, 1);
  131. fprintf('the input is source data with %d positions\n', nsource);
  132. elseif isdip
  133. fprintf('the input is dipole data\n');
  134. elseif ismvar
  135. fprintf('the input is mvar data\n');
  136. elseif isfreqmvar
  137. fprintf('the input is freqmvar data\n');
  138. end
  139. end % give feedback
  140. if issource && isvolume
  141. % it should be either one or the other: the choice here is to
  142. % represent it as volume description since that is simpler to handle
  143. % the conversion is done by remove the grid positions
  144. data = rmfield(data, 'pos');
  145. issource = false;
  146. end
  147. % the ft_datatype_XXX functions ensures the consistency of the XXX datatype
  148. % and provides a detailled description of the dataformat and its history
  149. if israw
  150. data = ft_datatype_raw(data);
  151. elseif isfreq
  152. data = ft_datatype_freq(data);
  153. elseif istimelock
  154. data = ft_datatype_timelock(data);
  155. elseif iscomp
  156. data = ft_datatype_comp(data);
  157. elseif isspike
  158. data = ft_datatype_spike(data);
  159. elseif isvolume
  160. data = ft_datatype_vol(data);
  161. elseif issource
  162. data = ft_datatype_source(data);
  163. elseif isdip
  164. data = ft_datatype_dip(data);
  165. elseif ismvar || isfreqmvar
  166. data = ft_datatype_mvar(data);
  167. end
  168. if ~isempty(dtype)
  169. if ~isa(dtype, 'cell')
  170. dtype = {dtype};
  171. end
  172. okflag = 0;
  173. for i=1:length(dtype)
  174. % check that the data matches with one or more of the required ft_datatypes
  175. switch dtype{i}
  176. case 'raw'
  177. okflag = okflag + israw;
  178. case 'freq'
  179. okflag = okflag + isfreq;
  180. case 'timelock'
  181. okflag = okflag + istimelock;
  182. case 'comp'
  183. okflag = okflag + iscomp;
  184. case 'spike'
  185. okflag = okflag + isspike;
  186. case 'volume'
  187. okflag = okflag + isvolume;
  188. case 'source'
  189. okflag = okflag + issource;
  190. case 'dip'
  191. okflag = okflag + isdip;
  192. case 'mvar'
  193. okflag = okflag + ismvar;
  194. case 'freqmvar'
  195. okflag = okflag + isfreqmvar;
  196. end % switch dtype
  197. end % for dtype
  198. if ~okflag
  199. % try to convert the data
  200. for iCell = 1:length(dtype)
  201. if isequal(dtype(iCell), {'source'}) && isvolume
  202. data = volume2source(data);
  203. isvolume = 0;
  204. issource = 1;
  205. okflag = 1;
  206. elseif isequal(dtype(iCell), {'volume'}) && issource
  207. data = source2volume(data);
  208. isvolume = 1;
  209. issource = 0;
  210. okflag = 1;
  211. elseif isequal(dtype(iCell), {'raw'}) && issource
  212. data = data2raw(data);
  213. issource = 0;
  214. israw = 1;
  215. okflag = 1;
  216. elseif isequal(dtype(iCell), {'raw'}) && istimelock
  217. data = timelock2raw(data);
  218. istimelock = 0;
  219. israw = 1;
  220. okflag = 1;
  221. elseif isequal(dtype(iCell), {'timelock'}) && israw
  222. data = raw2timelock(data);
  223. israw = 0;
  224. istimelock = 1;
  225. okflag = 1;
  226. elseif isequal(dtype(iCell), {'raw'}) && isfreq
  227. data = freq2raw(data);
  228. isfreq = 0;
  229. israw = 1;
  230. okflag = 1;
  231. elseif isequal(dtype(iCell), {'raw'}) && iscomp
  232. data = comp2raw(data);
  233. iscomp = 0;
  234. israw = 1;
  235. okflag = 1;
  236. end
  237. end % for iCell
  238. end % if okflag
  239. if ~okflag
  240. % construct an error message
  241. if length(dtype)>1
  242. str = sprintf('%s, ', dtype{1:(end-2)});
  243. str = sprintf('%s%s or %s', str, dtype{end-1}, dtype{end});
  244. else
  245. str = dtype{1};
  246. end
  247. str = sprintf('This function requires %s data as input.', str);
  248. error(str);
  249. end % if okflag
  250. end
  251. if ~isempty(dimord)
  252. if ~isa(dimord, 'cell')
  253. dimord = {dimord};
  254. end
  255. if isfield(data, 'dimord')
  256. okflag = any(strcmp(data.dimord, dimord));
  257. else
  258. okflag = 0;
  259. end
  260. if ~okflag
  261. % construct an error message
  262. if length(dimord)>1
  263. str = sprintf('%s, ', dimord{1:(end-2)});
  264. str = sprintf('%s%s or %s', str, dimord{end-1}, dimord{end});
  265. else
  266. str = dimord{1};
  267. end
  268. str = sprintf('This function requires data with a dimord of %s.', str);
  269. error(str);
  270. end % if okflag
  271. end
  272. if ~isempty(stype)
  273. if ~isa(stype, 'cell')
  274. stype = {stype};
  275. end
  276. if isfield(data, 'grad') || isfield(data, 'elec')
  277. if any(strcmp(ft_senstype(data), stype));
  278. okflag = 1;
  279. else
  280. okflag = 0;
  281. end
  282. else
  283. okflag = 0;
  284. end
  285. if ~okflag
  286. % construct an error message
  287. if length(stype)>1
  288. str = sprintf('%s, ', stype{1:(end-2)});
  289. str = sprintf('%s%s or %s', str, stype{end-1}, stype{end});
  290. else
  291. str = stype{1};
  292. end
  293. str = sprintf('This function requires %s data as input, but you are giving %s data.', str, ft_senstype(data));
  294. error(str);
  295. end % if okflag
  296. end
  297. if ~isempty(ismeg)
  298. if isequal(ismeg, 'yes')
  299. okflag = isfield(data, 'grad');
  300. elseif isequal(ismeg, 'no')
  301. okflag = ~isfield(data, 'grad');
  302. end
  303. if ~okflag && isequal(ismeg, 'yes')
  304. error('This function requires MEG data with a ''grad'' field');
  305. elseif ~okflag && isequal(ismeg, 'no')
  306. error('This function should not be given MEG data with a ''grad'' field');
  307. end % if okflag
  308. end
  309. if ~isempty(inside)
  310. % TODO absorb the fixinside function into this code
  311. data = fixinside(data, inside);
  312. okflag = isfield(data, 'inside');
  313. if ~okflag
  314. % construct an error message
  315. error('This function requires data with an ''inside'' field.');
  316. end % if okflag
  317. end
  318. %if isvolume
  319. % % ensure consistent dimensions of the volumetric data
  320. % % reshape each of the volumes that is found into a 3D array
  321. % param = parameterselection('all', data);
  322. % dim = data.dim;
  323. % for i=1:length(param)
  324. % tmp = getsubfield(data, param{i});
  325. % tmp = reshape(tmp, dim);
  326. % data = setsubfield(data, param{i}, tmp);
  327. % end
  328. %end
  329. if isequal(hasunits, 'yes') && ~isfield(data, 'units')
  330. % calling convert_units with only the input data adds the units without converting
  331. data = ft_convert_units(data);
  332. end
  333. if issource || isvolume,
  334. % the following section is to make a dimord-consistent representation of
  335. % volume and source data, taking trials, time and frequency into account
  336. if isequal(hasdimord, 'yes') && (~isfield(data, 'dimord') || ~strcmp(data.dimord,sourcedimord))
  337. % determine the size of the data
  338. if isfield(data, 'dimord'),
  339. dimtok = tokenize(data.dimord, '_');
  340. if ~isempty(strmatch('time', dimtok)), Ntime = length(data.time); else Ntime = 1; end
  341. if ~isempty(strmatch('freq', dimtok)), Nfreq = length(data.freq); else Nfreq = 1; end
  342. else
  343. Nfreq = 1;
  344. Ntime = 1;
  345. end
  346. %convert old style source representation into new style
  347. if isfield(data, 'avg') && isfield(data.avg, 'mom') && (isfield(data, 'freq') || isfield(data, 'frequency')) && strcmp(sourcedimord, 'rpt_pos'),
  348. %frequency domain source representation convert to single trial power
  349. Npos = size(data.pos,1);
  350. Nrpt = length(data.cumtapcnt);
  351. tmpmom = zeros(Npos, size(data.avg.mom{data.inside(1)},2));
  352. tmpmom(data.inside,:) = cat(1,data.avg.mom{data.inside});
  353. tmppow = zeros(Npos, Nrpt);
  354. tapcnt = [0;cumsum(data.cumtapcnt)];
  355. for k = 1:Nrpt
  356. Ntap = tapcnt(k+1)-tapcnt(k);
  357. tmppow(data.inside,k) = sum(abs(tmpmom(data.inside,(tapcnt(k)+1):tapcnt(k+1))).^2,2)./Ntap;
  358. end
  359. data.pow = tmppow';
  360. data = rmfield(data, 'avg');
  361. if strcmp(inside, 'logical'),
  362. data = fixinside(data, 'logical');
  363. data.inside = repmat(data.inside(:)',[Nrpt 1]);
  364. end
  365. elseif isfield(data, 'avg') && isfield(data.avg, 'mom') && (isfield(data, 'freq') || isfield(data, 'frequency')) && strcmp(sourcedimord, 'rpttap_pos'),
  366. %frequency domain source representation convert to single taper fourier coefficients
  367. Npos = size(data.pos,1);
  368. Nrpt = sum(data.cumtapcnt);
  369. data.fourierspctrm = complex(zeros(Nrpt, Npos), zeros(Nrpt, Npos));
  370. data.fourierspctrm(:, data.inside) = transpose(cat(1, data.avg.mom{data.inside}));
  371. data = rmfield(data, 'avg');
  372. elseif isfield(data, 'avg') && isfield(data.avg, 'mom') && isfield(data, 'time') && strcmp(sourcedimord, 'pos_time'),
  373. Npos = size(data.pos,1);
  374. Nrpt = 1;
  375. tmpmom = zeros(Npos, size(data.avg.mom{data.inside(1)},2));
  376. tmpmom(data.inside,:) = cat(1,data.avg.mom{data.inside});
  377. data.mom = tmpmom;
  378. if isfield(data.avg, 'noise'),
  379. tmpnoise = data.avg.noise(:);
  380. data.noise = tmpnoise(:,ones(1,size(tmpmom,2)));
  381. end
  382. data = rmfield(data, 'avg');
  383. Ntime = length(data.time);
  384. elseif isfield(data, 'trial') && isfield(data.trial(1), 'mom') && isfield(data, 'time') && strcmp(sourcedimord, 'rpt_pos_time'),
  385. Npos = size(data.pos,1);
  386. Nrpt = length(data.trial);
  387. Ntime = length(data.time);
  388. tmpmom = zeros(Nrpt, Npos, Ntime);
  389. for k = 1:Nrpt
  390. tmpmom(k,data.inside,:) = cat(1,data.trial(k).mom{data.inside});
  391. end
  392. data = rmfield(data, 'trial');
  393. data.mom = tmpmom;
  394. elseif isfield(data, 'trial') && isstruct(data.trial)
  395. Nrpt = length(data.trial);
  396. else
  397. Nrpt = 1;
  398. end
  399. % start with an initial specification of the dimord and dim
  400. if (~isfield(data, 'dim') || ~isfield(data, 'dimord'))
  401. if issource
  402. % at least it should have a Nx3 pos
  403. data.dim = size(data.pos, 1);
  404. data.dimord = 'pos';
  405. elseif isvolume
  406. % at least it should have a 1x3 dim
  407. data.dim = data.dim;
  408. data.dimord = 'dim1_dim2_dim3';
  409. end
  410. end
  411. % add the additional dimensions
  412. if Nfreq>1
  413. data.dimord = [data.dimord '_freq'];
  414. data.dim = [data.dim Nfreq];
  415. end
  416. if Ntime>1
  417. data.dimord = [data.dimord '_time'];
  418. data.dim = [data.dim Ntime];
  419. end
  420. if Nrpt>1 && strcmp(sourcedimord, 'rpt_pos'),
  421. data.dimord = ['rpt_' data.dimord];
  422. data.dim = [Nrpt data.dim ];
  423. elseif Nrpt>1 && strcmp(sourcedimord, 'rpttap_pos'),
  424. data.dimord = ['rpttap_' data.dimord];
  425. data.dim = [Nrpt data.dim ];
  426. end
  427. % the nested trial structure is not compatible with dimord
  428. if isfield(data, 'trial') && isstruct(data.trial)
  429. param = fieldnames(data.trial);
  430. for i=1:length(param)
  431. if isa(data.trial(1).(param{i}), 'cell')
  432. concat = cell(data.dim(1), prod(data.dim(2:end)));
  433. else
  434. concat = zeros(data.dim(1), prod(data.dim(2:end)));
  435. end
  436. for j=1:length(data.trial)
  437. tmp = data.trial(j).(param{i});
  438. concat(j,:) = tmp(:);
  439. end % for each trial
  440. data.trial = rmfield(data.trial, param{i});
  441. data.(param{i}) = reshape(concat, data.dim);
  442. end % for each param
  443. data = rmfield(data, 'trial');
  444. end
  445. end
  446. % ensure consistent dimensions of the source reconstructed data
  447. % reshape each of the source reconstructed parameters
  448. if issource && prod(data.dim)==size(data.pos,1)
  449. dim = [prod(data.dim) 1];
  450. elseif issource && any(~cellfun('isempty',strfind(fieldnames(data), 'dimord')))
  451. dim = [size(data.pos,1) 1]; %sparsely represented source structure new style
  452. elseif isfield(data, 'dim'),
  453. dim = [data.dim 1];
  454. elseif isfield(data, 'dimord'),
  455. %HACK
  456. dimtok = tokenize(data.dimord, '_');
  457. for i=1:length(dimtok)
  458. if strcmp(dimtok(i), 'pos')
  459. dim(1,i) = size(getsubfield(data,dimtok{i}),1);
  460. elseif strcmp(dimtok(i), 'rpt')
  461. dim(1,i) = nan;
  462. else
  463. dim(1,i) = length(getsubfield(data,dimtok{i}));
  464. end
  465. end
  466. i = find(isnan(dim));
  467. if ~isempty(i)
  468. n = fieldnames(data);
  469. for ii=1:length(n)
  470. numels(1,ii) = numel(getfield(data,n{ii}));
  471. end
  472. nrpt = numels./prod(dim(setdiff(1:length(dim),i)));
  473. nrpt = nrpt(nrpt==round(nrpt));
  474. dim(i) = max(nrpt);
  475. end
  476. if numel(dim)==1, dim(1,2) = 1; end;
  477. end
  478. % these fields should not be reshaped
  479. exclude = {'cfg' 'fwhm' 'leadfield' 'q' 'rough'};
  480. if ~strcmp(inside, 'logical')
  481. % also exclude the inside/outside from being reshaped
  482. exclude = cat(2, exclude, {'inside' 'outside'});
  483. end
  484. param = setdiff(parameterselection('all', data), exclude);
  485. for i=1:length(param)
  486. if any(param{i}=='.')
  487. % the parameter is nested in a substructure, which can have multiple elements (e.g. source.trial(1).pow, source.trial(2).pow, ...)
  488. % loop over the substructure array and reshape for every element
  489. tok = tokenize(param{i}, '.');
  490. sub1 = tok{1}; % i.e. this would be 'trial'
  491. sub2 = tok{2}; % i.e. this would be 'pow'
  492. tmp1 = getfield(data, sub1);
  493. for j=1:numel(tmp1)
  494. tmp2 = getfield(tmp1(j), sub2);
  495. tmp2 = reshape(tmp2, dim);
  496. tmp1(j) = setfield(tmp1(j), sub2, tmp2);
  497. end
  498. data = setfield(data, sub1, tmp1);
  499. else
  500. tmp = getfield(data, param{i});
  501. tmp = reshape(tmp, dim);
  502. data = setfield(data, param{i}, tmp);
  503. end
  504. end
  505. end
  506. if isequal(hastrials, 'yes')
  507. okflag = isfield(data, 'trial');
  508. if ~okflag
  509. error('This function requires data with a ''trial'' field');
  510. end % if okflag
  511. end
  512. if isequal(hastrialdef, 'yes')
  513. data = fixtrialdef(data);
  514. end
  515. if isequal(hasoffset, 'yes')
  516. okflag = isfield(data, 'offset');
  517. if ~okflag && isfield(data, 'time') && isa(data.time, 'cell')
  518. if ~isfield(data, 'fsample')
  519. data.fsample = 1/(data.time{1}(2)-data.time{1}(1));
  520. end
  521. for i=1:length(data.time);
  522. data.offset(i) = time2offset(data.time{i}, data.fsample);
  523. end
  524. data.offset = data.offset(:); % ensure that it is a column vector
  525. okflag = 1;
  526. elseif ~okflag && ft_datatype(data, 'mvar')
  527. data.offset = 0;
  528. okflag = 1;
  529. end
  530. if ~okflag
  531. error('This function requires data with an ''offset'' field');
  532. end % if okflag
  533. elseif isequal(hasoffset, 'no') && isfield(data, 'offset')
  534. data = rmfield(data, 'offset');
  535. end % if hasoffset
  536. if isequal(hascumtapcnt, 'yes') && ~isfield(data, 'cumtapcnt')
  537. error('This function requires data with a ''cumtapcnt'' field');
  538. elseif isequal(hascumtapcnt, 'no') && isfield(data, 'cumtapcnt')
  539. data = rmfield(data, 'cumtapcnt');
  540. end % if hascumtapcnt
  541. if isequal(hasdof, 'yes') && ~isfield(data, 'hasdof')
  542. error('This function requires data with a ''dof'' field');
  543. elseif isequal(hasdof, 'no') && isfield(data, 'hasdof')
  544. data = rmfield(data, 'cumtapcnt');
  545. end % if hasdof
  546. if ~isempty(cmbrepresentation)
  547. if istimelock
  548. data = fixcov(data, cmbrepresentation);
  549. elseif isfreq
  550. data = fixcsd(data, cmbrepresentation, channelcmb);
  551. elseif isfreqmvar
  552. data = fixcsd(data, cmbrepresentation, channelcmb);
  553. else
  554. error('This function requires data with a covariance, coherence or cross-spectrum');
  555. end
  556. end % cmbrepresentation
  557. if issource && ~isempty(sourcerepresentation)
  558. data = fixsource(data, 'type', sourcerepresentation);
  559. end
  560. if issource && ~strcmp(haspow, 'no')
  561. data = fixsource(data, 'type', sourcerepresentation, 'haspow', haspow);
  562. end
  563. if isfield(data, 'grad')
  564. % ensure that the gradiometer balancing is specified
  565. if ~isfield(data.grad, 'balance') || ~isfield(data.grad.balance, 'current')
  566. data.grad.balance.current = 'none';
  567. end
  568. end
  569. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  570. % represent the covariance matrix in a particular manner
  571. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  572. function data = fixcov(data, desired)
  573. if isfield(data, 'cov') && ~isfield(data, 'labelcmb')
  574. current = 'full';
  575. elseif isfield(data, 'cov') && isfield(data, 'labelcmb')
  576. current = 'sparse';
  577. else
  578. error('Could not determine the current representation of the covariance matrix');
  579. end
  580. if isequal(current, desired)
  581. % nothing to do
  582. elseif strcmp(current, 'full') && strcmp(desired, 'sparse')
  583. % FIXME should be implemented
  584. error('not yet implemented');
  585. elseif strcmp(current, 'sparse') && strcmp(desired, 'full')
  586. % FIXME should be implemented
  587. error('not yet implemented');
  588. end
  589. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  590. % represent the cross-spectral density matrix in a particular manner
  591. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  592. function [data] = fixcsd(data, desired, channelcmb)
  593. % FIXCSD converts univariate frequency domain data (fourierspctrm) into a bivariate
  594. % representation (crsspctrm), or changes the representation of bivariate frequency
  595. % domain data (sparse/full/sparsewithpow, sparsewithpow only works for crsspctrm or
  596. % fourierspctrm)
  597. % Copyright (C) 2010, Jan-Mathijs Schoffelen, Robert Oostenveld
  598. if isfield(data, 'crsspctrm') && isfield(data, 'powspctrm')
  599. current = 'sparsewithpow';
  600. elseif isfield(data, 'powspctrm')
  601. current = 'sparsewithpow';
  602. elseif isfield(data, 'fourierspctrm') && ~isfield(data, 'labelcmb')
  603. current = 'fourier';
  604. elseif ~isfield(data, 'labelcmb')
  605. current = 'full';
  606. elseif isfield(data, 'labelcmb')
  607. current = 'sparse';
  608. else
  609. error('Could not determine the current representation of the %s matrix', param);
  610. end
  611. % first go from univariate fourier to the required bivariate representation
  612. if strcmp(current, 'fourier') && strcmp(desired, 'fourier')
  613. % nothing to do
  614. elseif strcmp(current, 'fourier') && strcmp(desired, 'sparsewithpow')
  615. dimtok = tokenize(data.dimord, '_');
  616. if ~isempty(strmatch('rpttap', dimtok)),
  617. nrpt = length(data.cumtapcnt);
  618. flag = 0;
  619. else
  620. nrpt = 1;
  621. flag = 1;
  622. end
  623. if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end
  624. if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end
  625. fastflag = all(data.cumtapcnt(:)==data.cumtapcnt(1));
  626. %create auto-spectra
  627. nchan = length(data.label);
  628. if fastflag
  629. % all trials have the same amount of tapers
  630. powspctrm = zeros(nrpt,nchan,nfrq,ntim);
  631. ntap = data.cumtapcnt(1);
  632. for p = 1:ntap
  633. powspctrm = powspctrm + abs(data.fourierspctrm(p:ntap:end,:,:,:,:)).^2;
  634. end
  635. powspctrm = powspctrm./ntap;
  636. else
  637. % different amount of tapers
  638. powspctrm = zeros(nrpt,nchan,nfrq,ntim)+i.*zeros(nrpt,nchan,nfrq,ntim);
  639. sumtapcnt = [0;cumsum(data.cumtapcnt(:))];
  640. for p = 1:nrpt
  641. indx = (sumtapcnt(p)+1):sumtapcnt(p+1);
  642. tmpdat = data.fourierspctrm(indx,:,:,:);
  643. powspctrm(p,:,:,:) = (sum(tmpdat.*conj(tmpdat),1))./data.cumtapcnt(p);
  644. end
  645. end
  646. %create cross-spectra
  647. if ~isempty(channelcmb),
  648. ncmb = size(channelcmb,1);
  649. cmbindx = zeros(ncmb,2);
  650. labelcmb = cell(ncmb,2);
  651. for k = 1:ncmb
  652. ch1 = find(strcmp(data.label, channelcmb(k,1)));
  653. ch2 = find(strcmp(data.label, channelcmb(k,2)));
  654. if ~isempty(ch1) && ~isempty(ch2),
  655. cmbindx(k,:) = [ch1 ch2];
  656. labelcmb(k,:) = data.label([ch1 ch2])';
  657. end
  658. end
  659. crsspctrm = zeros(nrpt,ncmb,nfrq,ntim)+i.*zeros(nrpt,ncmb,nfrq,ntim);
  660. if fastflag
  661. for p = 1:ntap
  662. tmpdat1 = data.fourierspctrm(p:ntap:end,cmbindx(:,1),:,:,:);
  663. tmpdat2 = data.fourierspctrm(p:ntap:end,cmbindx(:,2),:,:,:);
  664. crsspctrm = crsspctrm + tmpdat1.*conj(tmpdat2);
  665. end
  666. crsspctrm = crsspctrm./ntap;
  667. else
  668. for p = 1:nrpt
  669. indx = (sumtapcnt(p)+1):sumtapcnt(p+1);
  670. tmpdat1 = data.fourierspctrm(indx,cmbindx(:,1),:,:);
  671. tmpdat2 = data.fourierspctrm(indx,cmbindx(:,2),:,:);
  672. crsspctrm(p,:,:,:) = (sum(tmpdat1.*conj(tmpdat2),1))./data.cumtapcnt(p);
  673. end
  674. end
  675. data.crsspctrm = crsspctrm;
  676. data.labelcmb = labelcmb;
  677. end
  678. data.powspctrm = powspctrm;
  679. data = rmfield(data, 'fourierspctrm');
  680. if ntim>1,
  681. data.dimord = 'chan_freq_time';
  682. else
  683. data.dimord = 'chan_freq';
  684. end
  685. if nrpt>1,
  686. data.dimord = ['rpt_',data.dimord];
  687. end
  688. if flag, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end
  689. elseif strcmp(current, 'fourier') && strcmp(desired, 'sparse')
  690. if isempty(channelcmb), error('no channel combinations are specified'); end
  691. dimtok = tokenize(data.dimord, '_');
  692. if ~isempty(strmatch('rpttap', dimtok)),
  693. nrpt = length(data.cumtapcnt);
  694. flag = 0;
  695. else
  696. nrpt = 1;
  697. flag = 1;
  698. end
  699. if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end
  700. if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end
  701. ncmb = size(channelcmb,1);
  702. cmbindx = zeros(ncmb,2);
  703. labelcmb = cell(ncmb,2);
  704. for k = 1:ncmb
  705. ch1 = find(strcmp(data.label, channelcmb(k,1)));
  706. ch2 = find(strcmp(data.label, channelcmb(k,2)));
  707. if ~isempty(ch1) && ~isempty(ch2),
  708. cmbindx(k,:) = [ch1 ch2];
  709. labelcmb(k,:) = data.label([ch1 ch2])';
  710. end
  711. end
  712. sumtapcnt = [0;cumsum(data.cumtapcnt(:))];
  713. fastflag = all(data.cumtapcnt(:)==data.cumtapcnt(1));
  714. if fastflag && nrpt>1
  715. ntap = data.cumtapcnt(1);
  716. % compute running sum across tapers
  717. siz = [size(data.fourierspctrm) 1];
  718. for p = 1:ntap
  719. indx = p:ntap:nrpt*ntap;
  720. if p==1.
  721. tmpc = zeros(numel(indx), size(cmbindx,1), siz(3), siz(4)) + ...
  722. 1i.*zeros(numel(indx), size(cmbindx,1), siz(3), siz(4));
  723. end
  724. for k = 1:size(cmbindx,1)
  725. tmpc(:,k,:,:) = data.fourierspctrm(indx,cmbindx(k,1),:,:).* ...
  726. conj(data.fourierspctrm(indx,cmbindx(k,2),:,:));
  727. end
  728. if p==1
  729. crsspctrm = tmpc;
  730. else
  731. crsspctrm = tmpc + crsspctrm;
  732. end
  733. end
  734. crsspctrm = crsspctrm./ntap;
  735. else
  736. crsspctrm = zeros(nrpt, ncmb, nfrq, ntim);
  737. for p = 1:nrpt
  738. indx = (sumtapcnt(p)+1):sumtapcnt(p+1);
  739. tmpdat1 = data.fourierspctrm(indx,cmbindx(:,1),:,:);
  740. tmpdat2 = data.fourierspctrm(indx,cmbindx(:,2),:,:);
  741. crsspctrm(p,:,:,:) = (sum(tmpdat1.*conj(tmpdat2),1))./data.cumtapcnt(p);
  742. end
  743. end
  744. data.crsspctrm = crsspctrm;
  745. data.labelcmb = labelcmb;
  746. data = rmfield(data, 'fourierspctrm');
  747. data = rmfield(data, 'label');
  748. if ntim>1,
  749. data.dimord = 'chan_freq_time';
  750. else
  751. data.dimord = 'chan_freq';
  752. end
  753. if nrpt>1,
  754. data.dimord = ['rpt_',data.dimord];
  755. end
  756. if flag, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end
  757. elseif strcmp(current, 'fourier') && strcmp(desired, 'full')
  758. % this is how it is currently and the desired functionality of prepare_freq_matrices
  759. dimtok = tokenize(data.dimord, '_');
  760. if ~isempty(strmatch('rpttap', dimtok)),
  761. nrpt = length(data.cumtapcnt);
  762. flag = 0;
  763. else
  764. nrpt = 1;
  765. flag = 1;
  766. end
  767. if ~isempty(strmatch('rpttap',dimtok)), nrpt=length(data.cumtapcnt); else nrpt = 1; end
  768. if ~isempty(strmatch('freq', dimtok)), nfrq=length(data.freq); else nfrq = 1; end
  769. if ~isempty(strmatch('time', dimtok)), ntim=length(data.time); else ntim = 1; end
  770. nchan = length(data.label);
  771. crsspctrm = zeros(nrpt,nchan,nchan,nfrq,ntim);
  772. sumtapcnt = [0;cumsum(data.cumtapcnt(:))];
  773. for k = 1:ntim
  774. for m = 1:nfrq
  775. for p = 1:nrpt
  776. %FIXME speed this up in the case that all trials have equal number of tapers
  777. indx = (sumtapcnt(p)+1):sumtapcnt(p+1);
  778. tmpdat = transpose(data.fourierspctrm(indx,:,m,k));
  779. crsspctrm(p,:,:,m,k) = (tmpdat*tmpdat')./data.cumtapcnt(p);
  780. clear tmpdat;
  781. end
  782. end
  783. end
  784. data.crsspctrm = crsspctrm;
  785. data = rmfield(data, 'fourierspctrm');
  786. if ntim>1,
  787. data.dimord = 'chan_chan_freq_time';
  788. else
  789. data.dimord = 'chan_chan_freq';
  790. end
  791. if nrpt>1,
  792. data.dimord = ['rpt_',data.dimord];
  793. end
  794. % remove first singleton dimension
  795. if flag || nrpt==1, siz = size(data.crsspctrm); data.crsspctrm = reshape(data.crsspctrm, siz(2:end)); end
  796. elseif strcmp(current, 'fourier') && strcmp(desired, 'fullfast'),
  797. dimtok = tokenize(data.dimord, '_');
  798. nrpt = size(data.fourierspctrm, 1);
  799. nchn = numel(data.label);
  800. nfrq = numel(data.freq);
  801. if ~isempty(strmatch('time', dimtok)), ntim=numel(data.time); else ntim = 1; end
  802. data.fourierspctrm = reshape(data.fourierspctrm, [nrpt nchn nfrq*ntim]);
  803. data.fourierspctrm(~isfinite(data.fourierspctrm)) = 0;
  804. crsspctrm = complex(zeros(nchn,nchn,nfrq*ntim));
  805. for k = 1:nfrq*ntim
  806. tmp = transpose(data.fourierspctrm(:,:,k));
  807. n = sum(tmp~=0,2);
  808. crsspctrm(:,:,k) = tmp*tmp'./n(1);
  809. end
  810. data = rmfield(data, 'fourierspctrm');
  811. data.crsspctrm = reshape(crsspctrm, [nchn nchn nfrq ntim]);
  812. if isfield(data, 'time'),
  813. data.dimord = 'chan_chan_freq_time';
  814. else
  815. data.dimord = 'chan_chan_freq';
  816. end
  817. end % convert to the requested bivariate representation
  818. % from one bivariate representation to another
  819. if isequal(current, desired)
  820. % nothing to do
  821. elseif (strcmp(current, 'full') && strcmp(desired, 'fourier')) || ...
  822. (strcmp(current, 'sparse') && strcmp(desired, 'fourier')) || ...
  823. (strcmp(current, 'sparsewithpow') && strcmp(desired, 'fourier'))
  824. % this is not possible
  825. error('converting the cross-spectrum into a Fourier representation is not possible');
  826. elseif strcmp(current, 'full') && strcmp(desired, 'sparsewithpow')
  827. error('not yet implemented');
  828. elseif strcmp(current, 'sparse') && strcmp(desired, 'sparsewithpow')
  829. % convert back to crsspctrm/powspctrm representation: useful for plotting functions etc
  830. indx = labelcmb2indx(data.labelcmb);
  831. autoindx = indx(indx(:,1)==indx(:,2), 1);
  832. cmbindx = setdiff([1:size(indx,1)]', autoindx);
  833. if strcmp(data.dimord(1:3), 'rpt')
  834. data.powspctrm = data.crsspctrm(:, autoindx, :, :);
  835. data.crsspctrm = data.crsspctrm(:, cmbindx, :, :);
  836. else
  837. data.powspctrm = data.crsspctrm(autoindx, :, :);
  838. data.crsspctrm = data.crsspctrm(cmbindx, :, :);
  839. end
  840. data.label = data.labelcmb(autoindx,1);
  841. data.labelcmb = data.labelcmb(cmbindx, :);
  842. if isempty(cmbindx)
  843. data = rmfield(data, 'crsspctrm');
  844. data = rmfield(data, 'labelcmb');
  845. end
  846. elseif strcmp(current, 'full') && strcmp(desired, 'sparse')
  847. dimtok = tokenize(data.dimord, '_');
  848. if ~isempty(strmatch('rpt', dimtok)), nrpt=numel(data.cumtapcnt); else nrpt = 1; end
  849. if ~isempty(strmatch('freq', dimtok)), nfrq=numel(data.freq); else nfrq = 1; end
  850. if ~isempty(strmatch('time', dimtok)), ntim=numel(data.time); else ntim = 1; end
  851. nchan = length(data.label);
  852. ncmb = nchan*nchan;
  853. labelcmb = cell(ncmb, 2);
  854. cmbindx = zeros(nchan, nchan);
  855. k = 1;
  856. for j=1:nchan
  857. for m=1:nchan
  858. labelcmb{k, 1} = data.label{m};
  859. labelcmb{k, 2} = data.label{j};
  860. cmbindx(m,j) = k;
  861. k = k+1;
  862. end
  863. end
  864. % reshape all possible fields
  865. fn = fieldnames(data);
  866. for ii=1:numel(fn)
  867. if numel(data.(fn{ii})) == nrpt*ncmb*nfrq*ntim;
  868. if nrpt>1,
  869. data.(fn{ii}) = reshape(data.(fn{ii}), nrpt, ncmb, nfrq, ntim);
  870. else
  871. data.(fn{ii}) = reshape(data.(fn{ii}), ncmb, nfrq, ntim);
  872. end
  873. end
  874. end
  875. % remove obsolete fields
  876. data = rmfield(data, 'label');
  877. try, data = rmfield(data, 'dof'); end
  878. % replace updated fields
  879. data.labelcmb = labelcmb;
  880. if ntim>1,
  881. data.dimord = 'chancmb_freq_time';
  882. else
  883. data.dimord = 'chancmb_freq';
  884. end
  885. if nrpt>1,
  886. data.dimord = ['rpt_',data.dimord];
  887. end
  888. elseif strcmp(current, 'sparsewithpow') && strcmp(desired, 'sparse')
  889. % this representation for sparse data contains autospectra
  890. % as e.g. {'A' 'A'} in labelcmb
  891. if isfield(data, 'crsspctrm'),
  892. dimtok = tokenize(data.dimord, '_');
  893. catdim = match_str(dimtok, {'chan' 'chancmb'});
  894. data.crsspctrm = cat(catdim, data.powspctrm, data.crsspctrm);
  895. data.labelcmb = [data.label(:) data.label(:); data.labelcmb];
  896. data = rmfield(data, 'powspctrm');
  897. else
  898. data.crsspctrm = data.powspctrm;
  899. data.labelcmb = [data.label(:) data.label(:)];
  900. data = rmfield(data, 'powspctrm');
  901. end
  902. data = rmfield(data, 'label');
  903. elseif strcmp(current, 'sparse') && strcmp(desired, 'full')
  904. dimtok = tokenize(data.dimord, '_');
  905. if ~isempty(strmatch('rpt', dimtok)), nrpt=numel(data.cumtapcnt); else nrpt = 1; end
  906. if ~isempty(strmatch('freq', dimtok)), nfrq=numel(data.freq); else nfrq = 1; end
  907. if ~isempty(strmatch('time', dimtok)), ntim=numel(data.time); else ntim = 1; end
  908. if ~isfield(data, 'label')
  909. data.label = unique(data.labelcmb(:));
  910. end
  911. nchan = length(data.label);
  912. ncmb = size(data.labelcmb,1);
  913. cmbindx = zeros(nchan,nchan);
  914. for k = 1:size(data.labelcmb,1)
  915. ch1 = find(strcmp(data.label, data.labelcmb(k,1)));
  916. ch2 = find(strcmp(data.label, data.labelcmb(k,2)));
  917. if ~isempty(ch1) && ~isempty(ch2),
  918. cmbindx(ch1,ch2) = k;
  919. end
  920. end
  921. complete = all(cmbindx(:)~=0);
  922. fn = fieldnames(data);
  923. for ii=1:numel(fn)
  924. if numel(data.(fn{ii})) == nrpt*ncmb*nfrq*ntim;
  925. if nrpt==1,
  926. data.(fn{ii}) = reshape(data.(fn{ii}), [nrpt ncmb nfrq ntim]);
  927. end
  928. tmpall = nan(nrpt,nchan,nchan,nfrq,ntim);
  929. for j = 1:nrpt
  930. for k = 1:ntim
  931. for m = 1:nfrq
  932. tmpdat = nan(nchan,nchan);
  933. indx = find(cmbindx);
  934. if ~complete
  935. % this realizes the missing combinations to be represented as the
  936. % conjugate of the corresponding combination across the diagonal
  937. tmpdat(indx) = reshape(data.(fn{ii})(j,cmbindx(indx),m,k),[numel(indx) 1]);
  938. tmpdat = ctranspose(tmpdat);
  939. end
  940. tmpdat(indx) = reshape(data.(fn{ii})(j,cmbindx(indx),m,k),[numel(indx) 1]);
  941. tmpall(j,:,:,m,k) = tmpdat;
  942. end % for m
  943. end % for k
  944. end % for j
  945. % replace the data in the old representation with the new representation
  946. if nrpt>1,
  947. data.(fn{ii}) = tmpall;
  948. else
  949. data.(fn{ii}) = reshape(tmpall, [nchan nchan nfrq ntim]);
  950. end
  951. end % if numel
  952. end % for ii
  953. % remove obsolete fields
  954. try, data = rmfield(data, 'powspctrm'); end
  955. try, data = rmfield(data, 'labelcmb'); end
  956. try, data = rmfield(data, 'dof'); end
  957. if ntim>1,
  958. data.dimord = 'chan_chan_freq_time';
  959. else
  960. data.dimord = 'chan_chan_freq';
  961. end
  962. if nrpt>1,
  963. data.dimord = ['rpt_',data.dimord];
  964. end
  965. elseif strcmp(current, 'sparse') && strcmp(desired, 'fullfast')
  966. dimtok = tokenize(data.dimord, '_');
  967. if ~isempty(strmatch('rpt', dimtok)), nrpt=numel(data.cumtapcnt); else nrpt = 1; end
  968. if ~isempty(strmatch('freq', dimtok)), nfrq=numel(data.freq); else nfrq = 1; end
  969. if ~isempty(strmatch('time', dimtok)), ntim=numel(data.time); else ntim = 1; end
  970. if ~isfield(data, 'label')
  971. data.label = unique(data.labelcmb(:));
  972. end
  973. nchan = length(data.label);
  974. ncmb = size(data.labelcmb,1);
  975. cmbindx = zeros(nchan,nchan);
  976. for k = 1:size(data.labelcmb,1)
  977. ch1 = find(strcmp(data.label, data.labelcmb(k,1)));
  978. ch2 = find(strcmp(data.label, data.labelcmb(k,2)));
  979. if ~isempty(ch1) && ~isempty(ch2),
  980. cmbindx(ch1,ch2) = k;
  981. end
  982. end
  983. complete = all(cmbindx(:)~=0);
  984. fn = fieldnames(data);
  985. for ii=1:numel(fn)
  986. if numel(data.(fn{ii})) == nrpt*ncmb*nfrq*ntim;
  987. if nrpt==1,
  988. data.(fn{ii}) = reshape(data.(fn{ii}), [nrpt ncmb nfrq ntim]);
  989. end
  990. tmpall = nan(nchan,nchan,nfrq,ntim);
  991. for k = 1:ntim
  992. for m = 1:nfrq
  993. tmpdat = nan(nchan,nchan);
  994. indx = find(cmbindx);
  995. if ~complete
  996. % this realizes the missing combinations to be represented as the
  997. % conjugate of the corresponding combination across the diagonal
  998. tmpdat(indx) = reshape(nanmean(data.(fn{ii})(:,cmbindx(indx),m,k)),[numel(indx) 1]);
  999. tmpdat = ctranspose(tmpdat);
  1000. end
  1001. tmpdat(indx) = reshape(nanmean(data.(fn{ii})(:,cmbindx(indx),m,k)),[numel(indx) 1]);
  1002. tmpall(:,:,m,k) = tmpdat;
  1003. end % for m
  1004. end % for k
  1005. % replace the data in the old representation with the new representation
  1006. if nrpt>1,
  1007. data.(fn{ii}) = tmpall;
  1008. else
  1009. data.(fn{ii}) = reshape(tmpall, [nchan nchan nfrq ntim]);
  1010. end
  1011. end % if numel
  1012. end % for ii
  1013. % remove obsolete fields
  1014. try, data = rmfield(data, 'powspctrm'); end
  1015. try, data = rmfield(data, 'labelcmb'); end
  1016. try, data = rmfield(data, 'dof'); end
  1017. if ntim>1,
  1018. data.dimord = 'chan_chan_freq_time';
  1019. else
  1020. data.dimord = 'chan_chan_freq';
  1021. end
  1022. elseif strcmp(current, 'sparsewithpow') && strcmp(desired, 'full')
  1023. % this is how is currently done in prepare_freq_matrices
  1024. data = ft_checkdata(data, 'cmbrepresentation', 'sparse');
  1025. data = ft_checkdata(data, 'cmbrepresentation', 'full');
  1026. end
  1027. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1028. % convert to new source representation
  1029. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1030. function [output] = fixsource(input, varargin)
  1031. % FIXSOURCE converts old style source structures into new style source structures and the
  1032. % other way around
  1033. %
  1034. % Use as:
  1035. % fixsource(input, type)
  1036. % where input is a source structure,
  1037. %
  1038. % Typically, old style source structures contain
  1039. % avg.XXX or trial.XXX fields
  1040. %
  1041. % The new style source structure contains:
  1042. % source.pos
  1043. % source.dim (optional, if the list of positions describes a 3D volume
  1044. % source.XXX the old style subfields in avg/trial
  1045. % source.XXXdimord string how to interpret the respective XXX field:
  1046. % e.g. source.leadfield = cell(1,Npos), source.leadfielddimord = '{pos}_chan_ori'
  1047. % source.mom = cell(1,Npos), source.momdimord = '{pos}_ori_rpttap'
  1048. type = keyval('type', varargin{:});
  1049. haspow = keyval('haspow', varargin{:});
  1050. if isempty(type), type = 'old'; end
  1051. if isempty(haspow), haspow = 'no'; end
  1052. fnames = fieldnames(input);
  1053. tmp = cell2mat(strfind(fnames, 'dimord')); %get dimord like fields
  1054. if any(tmp>1),
  1055. current = 'new';
  1056. elseif any(tmp==1),
  1057. %don't know what to do yet data is JM's own invention
  1058. current = 'old';
  1059. else
  1060. current = 'old';
  1061. end
  1062. if strcmp(current, type),
  1063. %do nothing
  1064. output = input;
  1065. %return
  1066. elseif strcmp(current, 'old') && strcmp(type, 'new'),
  1067. %go from old to new
  1068. if isfield(input, 'avg'),
  1069. stuff = getfield(input, 'avg');
  1070. output = rmfield(input, 'avg');
  1071. elseif isfield(input, 'trial'),
  1072. stuff = getfield(input, 'trial');
  1073. output = rmfield(input, 'trial');
  1074. else
  1075. %this could occur later in the pipeline, e.g. when doing group statistics using individual subject
  1076. %descriptive statistics
  1077. error('the input does not contain an avg or trial field');
  1078. end
  1079. %-------------------------------------------------
  1080. %remove and rename the specified fields if present
  1081. removefields = {'xgrid';'ygrid';'zgrid';'method'};
  1082. renamefields = {'frequency' 'freq'; 'csdlabel' 'orilabel'};
  1083. fnames = fieldnames(output);
  1084. for k = 1:numel(fnames)
  1085. ix = strmatch(fnames{k}, removefields);
  1086. if ~isempty(ix),
  1087. output = rmfield(output, fnames{k});
  1088. end
  1089. ix = strmatch(fnames{k}, renamefields(:,1), 'exact');
  1090. if ~isempty(ix),
  1091. output = setfield(output, renamefields{ix,2}, ...
  1092. getfield(output, renamefields{ix,1}));
  1093. output = rmfield(output, fnames{k});
  1094. end
  1095. end
  1096. %----------------------------------------------------------------------
  1097. %put the stuff originally in avg or trial one level up in the structure
  1098. fnames = fieldnames(stuff(1));
  1099. npos = size(input.pos,1);
  1100. nrpt = numel(stuff);
  1101. for k = 1:numel(fnames)
  1102. if nrpt>1,
  1103. %multiple trials
  1104. %(or subjects FIXME not yet implemented, nor tested)
  1105. tmp = getfield(stuff(1), fnames{k});
  1106. siz = size(tmp);
  1107. if isfield(input, 'cumtapcnt') && strcmp(fnames{k}, 'mom')
  1108. %pcc based mom is orixrpttap
  1109. %tranpose to keep manageable
  1110. for kk = 1:numel(input.inside)
  1111. indx = input.inside(kk);
  1112. tmp{indx} = permute(tmp{indx}, [2 1 3]);
  1113. end
  1114. nrpttap = sum(input.cumtapcnt);
  1115. sizvox = [size(tmp{input.inside(1)}) 1];
  1116. sizvox = [nrpttap sizvox(2:end)];
  1117. elseif strcmp(fnames{k}, 'mom'),
  1118. %this is then probably not a frequency based mom
  1119. nrpttap = numel(stuff);
  1120. sizvox = [size(tmp{input.inside(1)}) 1];
  1121. sizvox = [nrpttap sizvox];
  1122. elseif iscell(tmp)
  1123. nrpttap = numel(stuff);
  1124. sizvox = [size(tmp{input.inside(1)}) 1];
  1125. sizvox = [nrpttap sizvox];
  1126. end
  1127. if siz(1) ~= npos && siz(2) ==npos,
  1128. tmp = transpose(tmp);
  1129. end
  1130. if iscell(tmp)
  1131. %allocate memory for cell-array
  1132. tmpall = cell(npos,1);
  1133. for n = 1:numel(input.inside)
  1134. tmpall{input.inside(n)} = zeros(sizvox);
  1135. end
  1136. else
  1137. %allocate memory for matrix
  1138. tmpall = zeros([npos nrpt siz(2:end)]);
  1139. end
  1140. cnt = 0;
  1141. for m = 1:nrpt
  1142. tmp = getfield(stuff(m), fnames{k});
  1143. siz = size(tmp);
  1144. if siz(1) ~= npos && siz(2) ==npos,
  1145. tmp = transpose(tmp);
  1146. end
  1147. if ~iscell(tmp),
  1148. tmpall(:,m,:,:,:) = tmp;
  1149. else
  1150. for n = 1:numel(input.inside)
  1151. indx = input.inside(n);
  1152. tmpdat = tmp{indx};
  1153. if isfield(input, 'cumtapcnt') && strcmp(fnames{k}, 'mom'),
  1154. if n==1, siz1 = size(tmpdat,2); end
  1155. else
  1156. if n==1, siz1 = 1; end
  1157. end
  1158. tmpall{indx}(cnt+[1:siz1],:,:,:,:) = tmpdat;
  1159. if n==numel(input.inside), cnt = cnt + siz1; end
  1160. end
  1161. end
  1162. end
  1163. output = setfield(output, fnames{k}, tmpall);
  1164. newdimord = createdimord(output, fnames{k}, 1);
  1165. if ~isempty(newdimord)
  1166. output = setfield(output, [fnames{k},'dimord'], newdimord);
  1167. end
  1168. else
  1169. tmp = getfield(stuff, fnames{k});
  1170. siz = size(tmp);
  1171. if isfield(input, 'cumtapcnt') && strcmp(fnames{k}, 'mom')
  1172. %pcc based mom is orixrpttap
  1173. %tranpose to keep manageable
  1174. for kk = 1:numel(input.inside)
  1175. indx = input.inside(kk);
  1176. tmp{indx} = permute(tmp{indx}, [2 1 3]);
  1177. end
  1178. end
  1179. if siz(1) ~= npos && siz(2) ==npos,
  1180. tmp = transpose(tmp);
  1181. end
  1182. output = setfield(output, fnames{k}, tmp);
  1183. newdimord = createdimord(output, fnames{k});
  1184. if ~isempty(newdimord)
  1185. output = setfield(output, [fnames{k},'dimord'], newdimord);
  1186. end
  1187. end
  1188. end
  1189. if isfield(output, 'csdlabel')
  1190. output = setfield(output, 'orilabel', getfield(output, 'csdlabel'));
  1191. output = rmfield(output, 'csdlabel');
  1192. end
  1193. if isfield(output, 'leadfield')
  1194. % add dimord to leadfield as well. since the leadfield is not in
  1195. % the original .avg or .trial field it has not yet been taken care of
  1196. output.leadfielddimord = createdimord(output, 'leadfield');
  1197. end
  1198. if isfield(output, 'ori')
  1199. % convert cell-array ori into matrix
  1200. ori = zeros(3,npos) + nan;
  1201. try,
  1202. ori(:,output.inside) = cat(2, output.ori{output.inside});
  1203. catch
  1204. %when oris are in wrong orientation (row rather than column)
  1205. for k = 1:numel(output.inside)
  1206. ori(:,output.inside(k)) = output.ori{output.inside(k)}';
  1207. end
  1208. end
  1209. output.ori = ori;
  1210. end
  1211. current = 'new';
  1212. elseif strcmp(current, 'new') && strcmp(type, 'old')
  1213. %go from new to old
  1214. error('not implemented yet');
  1215. end
  1216. if strcmp(current, 'new') && strcmp(haspow, 'yes'),
  1217. %----------------------------------------------
  1218. %convert mom into pow if requested and possible
  1219. convert = 0;
  1220. if isfield(output, 'mom') && size(output.mom{output.inside(1)},2)==1,
  1221. convert = 1;
  1222. else
  1223. 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');
  1224. end
  1225. if isfield(output, 'cumtapcnt')
  1226. convert = 1 & convert;
  1227. else
  1228. warning('conversion from mom to pow will not be done, because cumtapcnt is missing');
  1229. end
  1230. if convert,
  1231. npos = size(output.pos,1);
  1232. nrpt = numel(output.cumtapcnt);
  1233. tmpmom = cat(2,output.mom{output.inside});
  1234. tmppow = zeros(npos, nrpt);
  1235. tapcnt = [0;cumsum(output.cumtapcnt(:))];
  1236. for k = 1:nrpt
  1237. ntap = tapcnt(k+1)-tapcnt(k);
  1238. tmppow(output.inside,k) = sum(abs(tmpmom((tapcnt(k)+1):tapcnt(k+1),:)).^2,1)./ntap;
  1239. end
  1240. output.pow = tmppow;
  1241. output.powdimord = ['pos_rpt_freq'];
  1242. end
  1243. elseif strcmp(current, 'old') && strcmp(haspow, 'yes')
  1244. warning('construction of single trial power estimates is not implemented here using old style source representation');
  1245. end
  1246. %--------------------------------------------------------
  1247. function [dimord] = createdimord(output, fname, rptflag);
  1248. if nargin==2, rptflag = 0; end
  1249. tmp = getfield(output, fname);
  1250. dimord = '';
  1251. dimnum = 1;
  1252. hasori = isfield(output, 'ori'); %if not, this is probably singleton and not relevant at the end
  1253. if iscell(tmp) && (size(output.pos,1)==size(tmp,dimnum) || size(output.pos,1)==size(tmp,2))
  1254. dimord = [dimord,'{pos}'];
  1255. dimnum = dimnum + 1;
  1256. elseif ~iscell(tmp) && size(output.pos,1)==size(tmp,dimnum)
  1257. dimord = [dimord,'pos'];
  1258. dimnum = dimnum + 1;
  1259. end
  1260. switch fname
  1261. case 'cov'
  1262. if hasori, dimord = [dimord,'_ori_ori']; end;
  1263. case 'csd'
  1264. if hasori, dimord = [dimord,'_ori_ori']; end;
  1265. case 'csdlabel'
  1266. dimord = dimord;
  1267. case 'filter'
  1268. dimord = [dimord,'_ori_chan'];
  1269. case 'leadfield'
  1270. %if hasori,
  1271. dimord = [dimord,'_chan_ori'];
  1272. %else
  1273. % dimord = [dimord,'_chan'];
  1274. %end
  1275. case 'mom'
  1276. if isfield(output, 'cumtapcnt') && sum(output.cumtapcnt)==size(tmp{output.inside(1)},1)
  1277. if hasori,
  1278. dimord = [dimord,'_rpttap_ori'];
  1279. else
  1280. dimord = [dimord,'_rpttap'];
  1281. end
  1282. elseif isfield(output, 'time')
  1283. if rptflag,
  1284. dimord = [dimord,'_rpt'];
  1285. dimnum = dimnum + 1;
  1286. end
  1287. if numel(output.time)==size(tmp{output.inside(1)},dimnum)
  1288. dimord = [dimord,'_ori_time'];
  1289. end
  1290. end
  1291. if isfield(output, 'freq') && numel(output.freq)>1,
  1292. dimord = [dimord,'_freq'];
  1293. end
  1294. case 'nai'
  1295. if isfield(output, 'freq') && numel(output.freq)==size(tmp,dimnum)
  1296. dimord = [dimord,'_freq'];
  1297. end
  1298. case 'noise'
  1299. if isfield(output, 'freq') && numel(output.freq)==size(tmp,dimnum)
  1300. dimord = [dimord,'_freq'];
  1301. end
  1302. case 'noisecsd'
  1303. if hasori, dimord = [dimord,'_ori_ori']; end
  1304. case 'ori'
  1305. dimord = '';
  1306. case 'pow'
  1307. if isfield(output, 'cumtapcnt') && numel(output.cumtapcnt)==size(tmp,dimnum)
  1308. dimord = [dimord,'_rpt'];
  1309. dimnum = dimnum + 1;
  1310. end
  1311. if isfield(output, 'freq') && numel(output.freq)>1 && numel(output.freq)==size(tmp,dimnum)
  1312. dimord = [dimord,'_freq'];
  1313. dimnum = dimnum+1;
  1314. end
  1315. if isfield(output, 'time') && numel(output.time)>1 && numel(output.time)==size(tmp,dimnum)
  1316. dimord = [dimord,'_time'];
  1317. dimnum = dimnum+1;
  1318. end
  1319. otherwise
  1320. warning('skipping unknown fieldname %s', fname);
  1321. %error(sprintf('unknown fieldname %s', fname));
  1322. end
  1323. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1324. % convert between datatypes
  1325. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1326. function data = comp2raw(data)
  1327. % just remove the component topographies
  1328. data = rmfield(data, 'topo');
  1329. data = rmfield(data, 'topolabel');
  1330. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1331. % convert between datatypes
  1332. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1333. function data = volume2source(data)
  1334. if isfield(data, 'dimord')
  1335. % it is a modern source description
  1336. else
  1337. % it is an old-fashioned source description

Large files files are truncated, but you can click here to view the full file