function test_suite = test_meeg_layout_collection
% tests for cosmo_meeg_layout_collection
%
% # For CoSMoMVPA's copyright information and license terms, #
% # see the COPYING file distributed with CoSMoMVPA. #
try % assignment of 'localfunctions' is necessary in Matlab >= 2016
test_functions = localfunctions();
catch % no problem; early Matlab versions can use initTestSuite fine
end
initTestSuite;
function test_fieldtrip_correspondence
if cosmo_skip_test_if_no_external('fieldtrip')
return
end
lc = cosmo_meeg_layout_collection();
rp_lay = randperm(numel(lc));
ntest_layout = 2;
ntest_chan_max = 10;
% may or may not be present
ignore_labels = {'COMNT', 'SCALE'};
% temporarily switch off warnings (emitted by fieldtrip)
warning_state = warning('query', 'all');
cleaner = onCleanup(@()warning(warning_state));
warning('off', 'all');
% shorter form
tolerance = 1e-4;
aeae = @(x, y)max(abs(x(:) - y(:))) < tolerance && isequal(size(x), size(y));
for ii = 1:ntest_layout
layout = lc{rp_lay(ii)};
cfg = struct();
cfg.layout = layout.name;
layout_ft = ft_prepare_layout(cfg);
% test outlnie
for j = 1:max(numel(layout_ft.outline), numel(layout.outline))
aeae(layout_ft.outline{j}, layout.outline{j});
end
% test mask
for j = 1:max(numel(layout_ft.mask), numel(layout.mask))
aeae(layout_ft.outline{j}, layout.outline{j});
end
% test labels
keep_idxs = find(~cosmo_match(layout.label, ignore_labels));
keep_ft_idxs = find(~cosmo_match(layout_ft.label, ignore_labels));
assertEqual(sort(layout.label(keep_idxs)), ...
sort(layout_ft.label(keep_ft_idxs)));
% test positions
ntest_chan = min(numel(keep_idxs), ntest_chan_max);
rp_chan = randperm(numel(keep_idxs));
for jj = 1:ntest_chan
test_label_idx = keep_idxs(rp_chan(jj));
label = layout.label{test_label_idx};
if strcmp(layout_ft.label{test_label_idx}, label)
% little optimization
pos = test_label_idx;
else
pos = find(cosmo_match(layout_ft.label, {label}));
assert(numel(pos) == 1);
end
aeae(layout_ft.width(pos, :), layout.width(test_label_idx, :));
aeae(layout_ft.height(pos, :), layout.height(test_label_idx, :));
aeae(layout_ft.pos(pos, :), layout.pos(test_label_idx, :));
end
end
function test_meeg_layout_collection_
if cosmo_skip_test_if_no_external('fieldtrip')
return
end
% get layout properties
% order is:
% - layout name
% - number of channels
% - some channel positions
% - labels of channel positions
lay_props = get_layout_properties();
% test each one
n = numel(lay_props);
clear('cosmo_meeg_layout_collection');
lc = cosmo_meeg_layout_collection();
lc_cached = cosmo_meeg_layout_collection();
assertEqual(lc, lc_cached);
lc_names = cellfun(@(x) x.name, lc, 'UniformOutput', false);
for k = 1:n
lay_prop = lay_props{k};
name = lay_prop{1};
nchan = lay_prop{2};
pos = lay_prop{3};
label = lay_prop{4};
i = find(cosmo_match(lc_names, name));
assertEqual(numel(i), 1);
lay = lc{i};
keep = find(~cosmo_match(lay.label, {'COMNT', 'SCALE'}));
assertEqual(numel(keep), nchan);
for j = 1:numel(label)
lab_i = find(cosmo_match(lay.label, label{j}));
assert(numel(lab_i) == 1);
assertElementsAlmostEqual(lay.pos(lab_i, :), pos(j, :), ...
'absolute', 1e-4);
end
end
function lay_props = get_layout_properties()
% the layout properties below were generated with the following code:
% names={'yokogawa440.lay', 'neuromag306planar.lay',...
% 'neuromag306mag.lay', 'neuromag306cmb.lay',...
% 'neuromag306all.lay', 'elec1020.lay',...
% 'elec1010.lay', 'elec1005.lay', 'biosemi32.lay',...
% 'biosemi128.lay', 'biosemi256.lay', 'EEG1020.lay',...
% 'EEG1010.lay', 'EEG1005.lay', 'CTF151.lay',...
% 'CTF275.lay', '4D148.lay', '4D248.lay'};
% lc=cosmo_meeg_layout_collection();
% lcn=cellfun(@(x) x.name,lc,'UniformOutput',false);
% for k=1:numel(names)
% fn=[names{k}];
% m=find(cosmo_match(lcn,fn));
% lay=lc{m};
% keep=find(~cosmo_match(lay.label,{'COMNT','SCALE'}));
% nch=numel(keep);
% desc=sprintf(['{''%s'',%d,...\n\t\t\t[%.4f %.4f;%.4f %.4f],'...
% '...\n\t\t\t{''%s'',''%s''}},...'],...
% lay.name,nch,lay.pos(keep([1 end]),:)',...
% lay.label{keep(1)},lay.label{keep(end)});
% fprintf('%s\n',desc);
% end
lay_props = { {'4D248.lay', 248, ...
[0.0038 0.0232; 0.3897 0.3453], ...
{'A1', 'A248'}}, ...
{'yokogawa440.lay', 440, ...
[-0.3337 0.3729; -0.0108 0.0726], ...
{'AG001', 'AG440'}}, ...
{'neuromag306planar.lay', 204, ...
[-0.4084 0.2532; 0.3733 -0.0820], ...
{'MEG0113', 'MEG2643'}}, ...
{'neuromag306mag.lay', 102, ...
[-0.4084 0.2732; 0.3733 -0.1036], ...
{'MEG0111', 'MEG2641'}}, ...
{'neuromag306cmb.lay', 102, ...
[-0.4084 0.2732; 0.3733 -0.1036], ...
{'MEG0112+0113', 'MEG2642+2643'}}, ...
{'neuromag306all.lay', 306, ...
[-0.4099 0.2532; 0.3761 -0.0976], ...
{'MEG0113', 'MEG2641'}}, ...
{'elec1020.lay', 21, ...
[-0.1710 0.4010; 0.1710 -0.4010], ...
{'Fp1', 'O2'}}, ...
{'elec1010.lay', 86, ...
[-0.1112 0.4261; 0.1391 -0.4257], ...
{'Fp1', 'I2'}}, ...
{'elec1005.lay', 335, ...
[-0.1112 0.3881; 0.1252 -0.3814], ...
{'Fp1', 'OI2'}}, ...
{'biosemi32.lay', 32, ...
[-0.1391 0.4500; 0.0000 0.0113], ...
{'Fp1', 'Cz'}}, ...
{'biosemi128.lay', 128, ...
[0.0000 0.0500; -0.4096 -0.2145], ...
{'A1', 'D32'}}, ...
{'biosemi256.lay', 256, ...
[0.0000 0.0587; -0.2290 -0.4060], ...
{'A1', 'H32'}}, ...
{'EEG1020.lay', 21, ...
[-0.1390 0.4280; 0.1390 -0.4280], ...
{'Fp1', 'O2'}}, ...
{'EEG1010.lay', 86, ...
[-0.1112 0.4260; 0.1390 -0.4256], ...
{'Fp1', 'I2'}}, ...
{'EEG1005.lay', 335, ...
[-0.1112 0.3880; 0.1252 -0.3814], ...
{'Fp1', 'OI2'}}, ...
{'CTF151.lay', 151, ...
[-0.0344 0.1732; 0.0008 -0.2668], ...
{'MLC11', 'MZP02'}}, ...
{'CTF275.lay', 275, ...
[-0.0171 0.1815; 0.0002 -0.2056], ...
{'MLC11', 'MZP01'}}, ...
{'4D148.lay', 148, ...
[-0.0109 0.0939; 0.3709 0.3364], ...
{'A1', 'A148'}}, ...
{'4D248.lay', 248, ...
[0.0038 0.0232; 0.3897 0.3453], ...
{'A1', 'A248'}}};