PageRenderTime 53ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/external/fieldtrip/trunk/fileio/private/ft_senstype.m

http://open-realtime-fmri.googlecode.com/
MATLAB | 366 lines | 242 code | 22 blank | 102 comment | 98 complexity | cdd4bb2dc7a1936ddcf97fbd81530073 MD5 | raw file
Possible License(s): GPL-2.0, GPL-3.0
  1. function [type] = ft_senstype(input, desired)
  2. % FT_SENSTYPE determines the type of sensors by looking at the channel names
  3. % and comparing them with predefined lists.
  4. %
  5. % Use as
  6. % [type] = ft_senstype(sens)
  7. % to get a string describing the type, or
  8. % [flag] = ft_senstype(sens, desired)
  9. % to get a boolean value.
  10. %
  11. % The output type can be any of the following
  12. % 'ctf151'
  13. % 'ctf151_planar'
  14. % 'ctf275'
  15. % 'ctf275_planar'
  16. % 'bti148'
  17. % 'bti148_planar'
  18. % 'bti248'
  19. % 'bti248_planar'
  20. % 'itab153'
  21. % 'itab153_planar'
  22. % 'yokogawa160'
  23. % 'yokogawa160_planar'
  24. % 'neuromag122'
  25. % 'neuromag306'
  26. % 'egi32'
  27. % 'egi64'
  28. % 'egi128'
  29. % 'egi256'
  30. % 'biosemi64'
  31. % 'biosemi128'
  32. % 'biosemi256'
  33. % 'ext1020'
  34. % 'plexon'
  35. % 'electrode'
  36. % 'magnetometer'
  37. %
  38. % The optional input argument for the desired type can be any of the above,
  39. % or any of the following
  40. % 'eeg'
  41. % 'meg'
  42. % 'meg_planar'
  43. % 'meg_axial'
  44. % 'ctf'
  45. % 'bti'
  46. % 'neuromag'
  47. % 'yokogawa'
  48. %
  49. % Besides specifiying a grad or elec structure as input, also allowed is
  50. % giving a data structure containing a grad or elec field, or giving a list
  51. % of channel names (as cell-arrray). I.e. assuming a FieldTrip data
  52. % structure, all of the following calls would be correct.
  53. % ft_senstype(data)
  54. % ft_senstype(data.label)
  55. % ft_senstype(data.grad)
  56. % ft_senstype(data.grad.label)
  57. %
  58. % See also FT_SENSLABEL, FT_CHANTYPE, FT_READ_SENS, FT_COMPUTE_LEADFIELD
  59. % Copyright (C) 2007-2009, Robert Oostenveld
  60. %
  61. % This file is part of FieldTrip, see http://www.ru.nl/neuroimaging/fieldtrip
  62. % for the documentation and details.
  63. %
  64. % FieldTrip is free software: you can redistribute it and/or modify
  65. % it under the terms of the GNU General Public License as published by
  66. % the Free Software Foundation, either version 3 of the License, or
  67. % (at your option) any later version.
  68. %
  69. % FieldTrip is distributed in the hope that it will be useful,
  70. % but WITHOUT ANY WARRANTY; without even the implied warranty of
  71. % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  72. % GNU General Public License for more details.
  73. %
  74. % You should have received a copy of the GNU General Public License
  75. % along with FieldTrip. If not, see <http://www.gnu.org/licenses/>.
  76. %
  77. % $Id: ft_senstype.m 2885 2011-02-16 09:41:58Z roboos $
  78. % these are for remembering the type on subsequent calls with the same input arguments
  79. persistent previous_argin previous_argout
  80. if iscell(input) && numel(input)<4 && ~all(cellfun(@ischar, input))
  81. % this might represent combined EEG, ECoG and/or MEG
  82. type = cell(size(input));
  83. if nargin<2
  84. desired = cell(size(input)); % empty elements
  85. end
  86. for i=1:numel(input)
  87. type{i} = ft_senstype(input{i}, desired{i});
  88. end
  89. return
  90. end
  91. if nargin<2
  92. % ensure that all input arguments are defined
  93. desired = [];
  94. end
  95. current_argin = {input, desired};
  96. if isequal(current_argin, previous_argin)
  97. % don't do the type detection again, but return the previous values from
  98. % cache
  99. type = previous_argout{1};
  100. return
  101. end
  102. % FIXME the detection of the type of input structure should perhaps be done using the datatype function
  103. isdata = isa(input, 'struct') && isfield(input, 'hdr');
  104. isheader = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'Fs');
  105. isgrad = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && isfield(input, 'ori');
  106. iselec = isa(input, 'struct') && isfield(input, 'label') && isfield(input, 'pnt') && ~isfield(input, 'ori');
  107. islabel = isa(input, 'cell') && ~isempty(input) && isa(input{1}, 'char');
  108. if ~isdata && ~isheader
  109. % timelock or freq structures don't have the header structure
  110. % the header is also removed from raw data after megrealign
  111. % the gradiometer definition is lost after megplanar+combineplanar
  112. isdata = isa(input, 'struct') && (isfield(input, 'grad') || isfield(input, 'elec') || isfield(input, 'label'));
  113. end
  114. % the input may be a data structure which then contains a grad/elec structure, a header or only the labels
  115. if isdata
  116. % preferably look at the data and not the header for the grad, because it might be re-balanced and/or planar
  117. if isfield(input, 'grad')
  118. sens = input.grad;
  119. isgrad = true;
  120. elseif issubfield(input, 'hdr.grad')
  121. sens = input.hdr.grad;
  122. isgrad = true;
  123. elseif issubfield(input, 'hdr.elec')
  124. sens = input.hdr.elec;
  125. iselec = true;
  126. elseif isfield(input, 'elec')
  127. sens = input.elec;
  128. iselec = true;
  129. elseif issubfield(input, 'hdr.label')
  130. sens.label = input.hdr.label;
  131. islabel = true;
  132. elseif isfield(input, 'label')
  133. sens.label = input.label;
  134. islabel = true;
  135. end
  136. elseif isheader
  137. if isfield(input, 'grad')
  138. sens = input.grad;
  139. isgrad = true;
  140. elseif isfield(input, 'elec')
  141. sens = input.elec;
  142. iselec = true;
  143. elseif isfield(input, 'label')
  144. sens.label = input.label;
  145. islabel = true;
  146. end
  147. elseif isgrad
  148. sens = input;
  149. elseif iselec
  150. sens = input;
  151. elseif islabel
  152. sens.label = input;
  153. else
  154. sens = [];
  155. end
  156. if isfield(input, 'type')
  157. % preferably the structure specifies its own type
  158. type = input.type;
  159. elseif issubfield(input, 'orig.FileHeader') && issubfield(input, 'orig.VarHeader')
  160. % this is a complete header that was read from a Plexon *.nex file using read_plexon_nex
  161. type = 'plexon';
  162. elseif issubfield(input, 'orig.stname')
  163. % this is a complete header that was read from an ITAB dataset
  164. type = 'itab';
  165. elseif issubfield(input, 'orig.sys_name')
  166. % this is a complete header that was read from a Yokogawa dataset
  167. type = 'yokogawa160';
  168. elseif issubfield(input, 'orig.FILE.Ext') && strcmp(input.orig.FILE.Ext, 'edf')
  169. % this is a complete header that was read from an EDF or EDF+ dataset
  170. type = 'electrode';
  171. else
  172. % start with unknown, then try to determine the proper type by looking at the labels
  173. type = 'unknown';
  174. if isgrad
  175. % probably this is MEG, determine the type of magnetometer/gradiometer system
  176. % 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
  177. if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8)
  178. type = 'ctf275';
  179. elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels
  180. type = 'ctf275';
  181. elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8)
  182. type = 'ctf151';
  183. elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8)
  184. type = 'ctf64';
  185. elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8)
  186. type = 'ctf275_planar';
  187. elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8)
  188. type = 'ctf151_planar';
  189. elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8)
  190. type = 'bti248';
  191. elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8)
  192. type = 'bti148';
  193. elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8)
  194. type = 'bti248_planar';
  195. elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8)
  196. type = 'bti148_planar';
  197. elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8)
  198. type = 'itab153';
  199. elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8)
  200. type = 'itab153_planar';
  201. elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4)
  202. type = 'yokogawa160';
  203. elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4)
  204. type = 'yokogawa160_planar';
  205. elseif (mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8)
  206. type = 'neuromag306';
  207. elseif (mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name
  208. type = 'neuromag306';
  209. elseif (mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8)
  210. type = 'neuromag122';
  211. elseif (mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name
  212. type = 'neuromag122';
  213. elseif any(ismember(ft_senslabel('btiref'), sens.label))
  214. type = 'bti'; % it might be 148 or 248 channels
  215. elseif any(ismember(ft_senslabel('ctfref'), sens.label))
  216. type = 'ctf'; % it might be 151 or 275 channels
  217. elseif isfield(sens, 'pnt') && isfield(sens, 'ori') && numel(sens.label)==size(sens.pnt,1)
  218. warning('could be Yokogawa system');
  219. type = 'magnetometer';
  220. else
  221. warning('could be Yokogawa system');
  222. type = 'meg';
  223. end
  224. elseif iselec
  225. % probably this is EEG
  226. if (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8)
  227. type = 'biosemi256';
  228. elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8)
  229. type = 'biosemi128';
  230. elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8)
  231. type = 'biosemi64';
  232. elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8)
  233. type = 'egi256';
  234. elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8)
  235. type = 'egi128';
  236. elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8)
  237. type = 'egi64';
  238. elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8)
  239. type = 'egi32';
  240. elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing
  241. type = 'ext1020';
  242. else
  243. type = 'electrode';
  244. end
  245. elseif islabel
  246. % look only at the channel labels
  247. if (mean(ismember(ft_senslabel('ctf275'), sens.label)) > 0.8)
  248. type = 'ctf275';
  249. elseif (mean(ismember(ft_senslabel('ctfheadloc'), sens.label)) > 0.8) % look at the head localization channels
  250. type = 'ctf275';
  251. elseif (mean(ismember(ft_senslabel('ctf151'), sens.label)) > 0.8)
  252. type = 'ctf151';
  253. elseif (mean(ismember(ft_senslabel('ctf64'), sens.label)) > 0.8)
  254. type = 'ctf64';
  255. elseif (mean(ismember(ft_senslabel('ctf275_planar'), sens.label)) > 0.8)
  256. type = 'ctf275_planar';
  257. elseif (mean(ismember(ft_senslabel('ctf151_planar'), sens.label)) > 0.8)
  258. type = 'ctf151_planar';
  259. elseif (mean(ismember(ft_senslabel('bti248'), sens.label)) > 0.8)
  260. type = 'bti248';
  261. elseif (mean(ismember(ft_senslabel('bti148'), sens.label)) > 0.8)
  262. type = 'bti148';
  263. elseif (mean(ismember(ft_senslabel('bti248_planar'), sens.label)) > 0.8)
  264. type = 'bti248_planar';
  265. elseif (mean(ismember(ft_senslabel('bti148_planar'), sens.label)) > 0.8)
  266. type = 'bti148_planar';
  267. elseif (mean(ismember(ft_senslabel('itab153'), sens.label)) > 0.8)
  268. type = 'itab153';
  269. elseif (mean(ismember(ft_senslabel('itab153_planar'), sens.label)) > 0.8)
  270. type = 'itab153_planar';
  271. elseif (mean(ismember(ft_senslabel('yokogawa160'), sens.label)) > 0.4)
  272. type = 'yokogawa160';
  273. elseif (mean(ismember(ft_senslabel('yokogawa160_planar'), sens.label)) > 0.4)
  274. type = 'yokogawa160_planar';
  275. elseif any(mean(ismember(ft_senslabel('neuromag306'), sens.label)) > 0.8)
  276. type = 'neuromag306';
  277. elseif any(mean(ismember(ft_senslabel('neuromag306alt'),sens.label)) > 0.8) % an alternative set without spaces in the name
  278. type = 'neuromag306';
  279. elseif any(mean(ismember(ft_senslabel('neuromag122'), sens.label)) > 0.8)
  280. type = 'neuromag122';
  281. elseif any(mean(ismember(ft_senslabel('neuromag122alt'),sens.label)) > 0.8) % an alternative set without spaces in the name
  282. type = 'neuromag122';
  283. elseif (mean(ismember(ft_senslabel('biosemi256'), sens.label)) > 0.8)
  284. type = 'biosemi256';
  285. elseif (mean(ismember(ft_senslabel('biosemi128'), sens.label)) > 0.8)
  286. type = 'biosemi128';
  287. elseif (mean(ismember(ft_senslabel('biosemi64'), sens.label)) > 0.8)
  288. type = 'biosemi64';
  289. elseif (mean(ismember(ft_senslabel('egi256'), sens.label)) > 0.8)
  290. type = 'egi256';
  291. elseif (mean(ismember(ft_senslabel('egi128'), sens.label)) > 0.8)
  292. type = 'egi128';
  293. elseif (mean(ismember(ft_senslabel('egi64'), sens.label)) > 0.8)
  294. type = 'egi64';
  295. elseif (mean(ismember(ft_senslabel('egi32'), sens.label)) > 0.8)
  296. type = 'egi32';
  297. elseif (sum(ismember(sens.label, ft_senslabel('eeg1005'))) > 10) % Otherwise it's not even worth recognizing
  298. type = 'ext1020';
  299. elseif any(ismember(ft_senslabel('btiref'), sens.label))
  300. type = 'bti'; % it might be 148 or 248 channels
  301. elseif any(ismember(ft_senslabel('ctfref'), sens.label))
  302. type = 'ctf'; % it might be 151 or 275 channels
  303. end
  304. end % look at label, ori and/or pnt
  305. end % if isfield(sens, 'type')
  306. if ~isempty(desired)
  307. % return a boolean flag
  308. switch desired
  309. case 'eeg'
  310. type = any(strcmp(type, {'eeg' 'electrode' 'biosemi64' 'biosemi128' 'biosemi256' 'egi32' 'egi64' 'egi128' 'egi256' 'ext1020'}));
  311. case 'biosemi'
  312. type = any(strcmp(type, {'biosemi64' 'biosemi128' 'biosemi256'}));
  313. case 'egi'
  314. type = any(strcmp(type, {'egi64' 'egi128' 'egi256'}));
  315. case 'meg'
  316. 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'}));
  317. case 'ctf'
  318. type = any(strcmp(type, {'ctf' 'ctf151' 'ctf275' 'ctf151_planar' 'ctf275_planar'}));
  319. case 'bti'
  320. type = any(strcmp(type, {'bti' 'bti148' 'bti148_planar' 'bti248' 'bti248_planar'}));
  321. case 'neuromag'
  322. type = any(strcmp(type, {'neuromag122' 'neuromag306'}));
  323. case 'yokogawa'
  324. type = any(strcmp(type, {'yokogawa160' 'yokogawa160_planar'}));
  325. case 'itab'
  326. type = any(strcmp(type, {'itab' 'itab153' 'itab153_planar'}));
  327. case 'meg_axial'
  328. % note that neuromag306 is mixed planar and axial
  329. type = any(strcmp(type, {'magnetometer' 'neuromag306' 'ctf151' 'ctf275' 'bti148' 'bti248' 'yokogawa160'}));
  330. case 'meg_planar'
  331. % note that neuromag306 is mixed planar and axial
  332. type = any(strcmp(type, {'neuromag122' 'neuromag306' 'ctf151_planar' 'ctf275_planar' 'bti148_planar' 'bti248_planar' 'yokogawa160_planar'}));
  333. otherwise
  334. type = any(strcmp(type, desired));
  335. end % switch desired
  336. end % detemine the correspondence to the desired type
  337. % remember the current input and output arguments, so that they can be
  338. % reused on a subsequent call in case the same input argument is given
  339. current_argout = {type};
  340. if isempty(previous_argin)
  341. previous_argin = current_argin;
  342. previous_argout = current_argout;
  343. end
  344. return % ft_senstype main()