function test_suite=test_meeg_chan_neighbors()
% tests for cosmo_meeg_chan_neighbors
%
% # 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_meeg_neighbors()
if cosmo_skip_test_if_no_external('fieldtrip')
return;
end
% switch off warnings by fieldtrip
warning_state=warning('query','all');
cleaner=onCleanup(@()warning(warning_state));
warning('off','all');
props=get_props();
n=numel(props);
% test a subset
ntest=round(n*.5);
% test a subset for fieldtrip
% (fieldtrip is very slow, so testing all would take too long)
ntest_fieldtrip=1;
% visit in random order
rp=randperm(n);
prev_sens='';
for k=1:ntest
prop=props{rp(k)};
sens=prop{1};
layout_name=prop{2};
args=prop{3};
nchan=prop{4};
chan_stats=prop{5};
chan_labels=prop{6};
if ~isequal(sens,prev_sens)
ds=cosmo_synthetic_dataset('type','meeg',...
'sens',sens,...
'size','big');
end
nbrs=cosmo_meeg_chan_neighbors(ds,args{:});
assertEqual(numel(nbrs),nchan);
chan_count=cellfun(@numel,{nbrs.neighblabel});
stats=[min(chan_count), max(chan_count), mean(chan_count)];
assertElementsAlmostEqual(stats, chan_stats,'relative',1e-3);
% test neighbor labels
for j=1:numel(chan_labels)
chan_label=chan_labels{j};
center=chan_label{1};
around=chan_label{2};
% little optimization for finding first and last channel
if j==1
pos=1;
else
pos=nchan;
end
if ~strcmp(center,nbrs(pos).label)
pos=find(cosmo_match({nbrs.label},center));
assert(numel(pos)==1);
end
assertEqual(sort(around(:)),sort(nbrs(pos).neighblabel));
end
can_test_fieldtrip=~isempty(layout_name) && ...
isequal(args{4},'layout') && ...
~strcmp(args{1},'count');
if can_test_fieldtrip && ntest_fieldtrip>0
cfg=struct();
cfg.layout=layout_name;
switch args{1}
case 'delaunay'
cfg.method='triangulation';
case 'radius'
cfg.method='distance';
cfg.neighbourdist=args{2};
otherwise
assert(false);
end
y=ft_prepare_neighbours(cfg);
% reorder the labels if necessary
nbrs_cell=cellfun(@(x){x},{nbrs.label},'UniformOutput',false);
y_cell=cellfun(@(x){x},{y.label},'UniformOutput',false);
p=cosmo_overlap(nbrs_cell,y_cell);
[i,j]=find(p==1);
y=y(i);
assertEqual({nbrs.label},{y.label});
[p,q]=cosmo_overlap({nbrs.neighblabel},{y.neighblabel});
dp=diag(p);
dq=diag(q);
assert(mean(dp(isfinite(dp)))>.9);
assert(mean(dq(isfinite(dq)))>.8);
ntest_fieldtrip=ntest_fieldtrip-1;
end
end
function props=get_props()
% properties to test; each cell has these elements:
% - dataset type
% - arguments for neighbors
% - number of neighbors
% - min, max, mean number of channels
% - a few channel labels and their neighbors
props={{'neuromag306_all',...
'neuromag306mag.lay',...
{'delaunay',true,'label','layout','chantype',...
'meg_axial'},...
102,[5 11 7.9412],...
{{'MEG0111',...
{'MEG0111','MEG0121','MEG0131',...
'MEG0141','MEG0341','MEG0511'}},...
{'MEG2641',...
{'MEG1331','MEG2421','MEG2431',...
'MEG2441','MEG2521','MEG2611',...
'MEG2621','MEG2631','MEG2641'}}}},...
{'neuromag306_all',...
'neuromag306planar.lay',...
{'delaunay',true,'label','layout','chantype',...
'meg_planar'},...
204,[4 12 8.0392],...
{{'MEG0113',...
{'MEG0113','MEG0112','MEG0122',...
'MEG0132','MEG0133','MEG0142',...
'MEG0343'}},...
{'MEG2643',...
{'MEG1333','MEG2423','MEG2422',...
'MEG2612','MEG2623','MEG2622',...
'MEG2642','MEG2643'}}}},...
{'neuromag306_planar',...
'neuromag306planar.lay',...
{'radius',0.1,'label','dataset','chantype',...
'meg_planar'},...
204,[4 14 8.9118],...
{{'MEG0113',...
{'MEG0113','MEG0112','MEG0122',...
'MEG0132','MEG0133'}},...
{'MEG2643',...
{'MEG2423','MEG2422','MEG2623',...
'MEG2622','MEG2632','MEG2642',...
'MEG2643'}}}},...
{'neuromag306_planar',...
'neuromag306planar.lay',...
{'radius',0.1,'label','dataset','chantype',...
'meg_combined_from_planar'},...
102,[4 16 8.9804],...
{{'MEG0112+0113',...
{'MEG0112','MEG0113','MEG0122',...
'MEG0123','MEG0132','MEG0133'}},...
{'MEG2642+2643',...
{'MEG2422','MEG2423','MEG2622',...
'MEG2623','MEG2632','MEG2633',...
'MEG2642','MEG2643'}}}},...
{'neuromag306_planar_combined',...
'neuromag306cmb.lay',...
{'count',5,'label','layout','chantype',...
'meg_planar_combined'},...
102,[5 5 5],...
{{'MEG0112+0113',...
{'MEG0112+0113','MEG0122+0123',...
'MEG0132+0133','MEG0212+0213',...
'MEG0342+0343'}},...
{'MEG2642+2643',...
{'MEG2422+2423','MEG2432+2433',...
'MEG2622+2623','MEG2632+2633',...
'MEG2642+2643'}}}},...
{'ctf151',...
'CTF151.lay',...
{'delaunay',true,'label','dataset','chantype',...
'meg_axial'},...
151,[5 11 8.404],...
{{'MLC11',...
{'MLC11','MLC12','MLC21','MLF41',...
'MLF51','MLF52','MRC11','MZC01',...
'MZF03'}},...
{'MZP02',...
{'MLO11','MLP21','MLP31','MRO11',...
'MRP21','MRP31','MZO01','MZP01',...
'MZP02'}}}},...
{'ctf151',...
'CTF151.lay',...
{'delaunay',true,'label','dataset','chantype',...
'meg_planar_combined'},...
151,[5 11 8.404],...
{{'MLC11',...
{'MLC11','MLC12','MLC21','MLF41',...
'MLF51','MLF52','MRC11','MZC01',...
'MZF03'}},...
{'MZP02',...
{'MLO11','MLP21','MLP31','MRO11',...
'MRP21','MRP31','MZO01','MZP01',...
'MZP02'}}}},...
{'ctf151_planar',...
[],...
{'radius',0.1,'label',...
{'MLC11_dH','MLC12_dH','MLC13_dH',...
'MLC14_dH','MLC15_dH','MLC21_dH',...
'MRT41_dV','MRT42_dV','MRT43_dV',...
'MRT44_dV','MZC01_dV','MZC02_dV'},...
'chantype','meg_planar'},...
12,[1 4 2.3333],...
{{'MLC11_dH',...
{'MLC11_dH','MLC12_dH','MLC21_dH',...
'MZC01_dV'}},...
{'MZC02_dV',{'MZC02_dV'}}}},...
{'ctf151_planar',...
[],...
{'radius',0.1,'label',...
{'MLC11_dH','MLC12_dH','MLC13_dH',...
'MLC14_dH','MLC15_dH','MLC21_dH',...
'MRT41_dV','MRT42_dV','MRT43_dV',...
'MRT44_dV','MZC01_dV','MZC02_dV'},...
'chantype','meg_combined_from_planar'},...
12,[1 4 2.3333],...
{{'MLC11',...
{'MLC11_dH','MLC12_dH','MLC21_dH',...
'MZC01_dV'}},...
{'MZC02',{ 'MZC02_dV' }}}},...
{'ctf151_planar_combined',...
'CTF151.lay',...
{'count',5,'label','dataset','chantype',...
'meg_axial'},...
151,[5 5 5],...
{{'MLC11',...
{'MLC11','MLC12','MLF51','MRC11',...
'MZF03'}},...
{'MZP02',...
{'MLO11','MLP21','MRO11','MRP21',...
'MZP02'}}}},...
{'ctf151_planar_combined',...
'CTF151.lay',...
{'count',5,'label','dataset','chantype',...
'meg_planar_combined'},...
151,[5 5 5],...
{{'MLC11',...
{'MLC11','MLC12','MLF51','MRC11',...
'MZF03'}},...
{'MZP02',...
{'MLO11','MLP21','MRO11','MRP21',...
'MZP02'}}}},...
{'4d148',...
'4D148.lay',...
{'delaunay',true,'label',...
{'A148','A147','A146','A145','A144',...
'A143','A13','A12','A11','A10','A9',...
'A8'},...
'chantype','meg_axial'},...
12,[4 9 6.8333],...
{{'A8',{'A8','A9','A10','A11','A13','A143'}},...
{'A148',...
{'A10','A11','A12','A13','A143',...
'A147','A148'}}}},...
{'4d148',...
'4D148.lay',...
{'delaunay',true,'label',...
{'A148','A147','A146','A145','A144',...
'A143','A13','A12','A11','A10','A9',...
'A8'},...
'chantype','meg_planar_combined'},...
12,[4 9 6.8333],...
{{'A8',{'A8','A9','A10','A11','A13','A143'}},...
{'A148',...
{'A10','A11','A12','A13','A143',...
'A147','A148'}}}},...
{'4d148_planar',...
[],...
{'radius',0.1,'label','layout','chantype',...
'meg_planar'},...
296,[4 20 13.1351],...
{{'A1_dH',...
{'A1_dH','A1_dV','A2_dH','A2_dV',...
'A3_dH','A3_dV','A5_dH','A5_dV',...
'A6_dH','A6_dV','A7_dH','A7_dV',...
'A10_dH','A10_dV','A11_dH','A11_dV',...
'A12_dH','A12_dV'}},...
{'A148_dV',...
{'A129_dH','A129_dV','A130_dH',...
'A130_dV','A148_dH','A148_dV'}}}},...
{'4d148_planar',...
[],...
{'radius',0.1,'label','layout','chantype',...
'meg_combined_from_planar'},...
148,[4 20 13.1351],...
{{'A1',...
{'A10_dH','A10_dV','A11_dH','A11_dV',...
'A12_dH','A12_dV','A1_dH','A1_dV',...
'A2_dH','A2_dV','A3_dH','A3_dV',...
'A5_dH','A5_dV','A6_dH','A6_dV',...
'A7_dH','A7_dV'}},...
{'A148',...
{'A129_dH','A129_dV','A130_dH',...
'A130_dV','A148_dH','A148_dV'}}}},...
{'4d148_planar_combined',...
'4D148.lay',...
{'count',5,'label',...
{'A148','A147','A146','A145','A144',...
'A143','A13','A12','A11','A10','A9',...
'A8'},...
'chantype','meg_axial'},...
12,[5 5 5],...
{{'A8',{'A8','A9','A10','A11','A12'}},...
{'A148',{'A12','A145','A146','A147','A148'}}}},...
{'4d148_planar_combined',...
'4D148.lay',...
{'count',5,'label',...
{'A148','A147','A146','A145','A144',...
'A143','A13','A12','A11','A10','A9',...
'A8'},...
'chantype','meg_planar_combined'},...
12,[5 5 5],...
{{'A8',{'A8','A9','A10','A11','A12'}},...
{'A148',{'A12','A145','A146','A147','A148'}}}},...
{'4d248',...
'4D248.lay',...
{'delaunay',true,'label','layout','chantype',...
'meg_axial'},...
248,[5 12 8.2903],...
{{'A1',...
{'A1','A2','A9','A10','A11','A12',...
'A13','A14'}},...
{'A248',...
{'A151','A152','A194','A195','A227',...
'A228','A246','A247','A248'}}}},...
{'4d248',...
'4D248.lay',...
{'delaunay',true,'label','layout','chantype',...
'meg_planar_combined'},...
248,[5 12 8.2903],...
{{'A1',...
{'A1','A2','A9','A10','A11','A12',...
'A13','A14'}},...
{'A248',...
{'A151','A152','A194','A195','A227',...
'A228','A246','A247','A248'}}}},...
{'4d248_planar',...
[],...
{'radius',0.1,'label','dataset','chantype',...
'meg_planar'},...
496,[8 32 22.1452],...
{{'A1_dH',...
{'A1_dH','A1_dV','A2_dH','A2_dV',...
'A9_dH','A9_dV','A10_dH','A10_dV',...
'A11_dH','A11_dV','A12_dH','A12_dV',...
'A13_dH','A13_dV','A14_dH','A14_dV',...
'A15_dH','A15_dV','A25_dH','A25_dV',...
'A28_dH','A28_dV','A30_dH','A30_dV',...
'A31_dH','A31_dV'}},...
{'A248_dV',...
{'A194_dH','A194_dV','A227_dH',...
'A227_dV','A228_dH','A228_dV',...
'A247_dH','A247_dV','A248_dH',...
'A248_dV'}}}},...
{'4d248_planar',...
[],...
{'radius',0.1,'label','dataset','chantype',...
'meg_combined_from_planar'},...
248,[8 32 22.1452],...
{{'A1',...
{'A10_dH','A10_dV','A11_dH','A11_dV',...
'A12_dH','A12_dV','A13_dH','A13_dV',...
'A14_dH','A14_dV','A15_dH','A15_dV',...
'A1_dH','A1_dV','A25_dH','A25_dV',...
'A28_dH','A28_dV','A2_dH','A2_dV',...
'A30_dH','A30_dV','A31_dH','A31_dV',...
'A9_dH','A9_dV'}},...
{'A248',...
{'A194_dH','A194_dV','A227_dH',...
'A227_dV','A228_dH','A228_dV',...
'A247_dH','A247_dV','A248_dH',...
'A248_dV'}}}},...
{'4d248_planar_combined',...
'4D248.lay',...
{'count',5,'label','layout','chantype',...
'meg_axial'},...
248,[5 5 5],...
{{'A1',{'A1','A2','A10','A12','A14'}},...
{'A248',{'A194','A227','A228','A247','A248'}}}},...
{'4d248_planar_combined',...
'4D248.lay',...
{'count',5,'label','layout','chantype',...
'meg_planar_combined'},...
248,[5 5 5],...
{{'A1',{'A1','A2','A10','A12','A14'}},...
{'A248',{'A194','A227','A228','A247','A248'}}}},...
{'eeg1005',...
'EEG1005.lay',...
{'delaunay',true,'label','dataset','chantype',...
'eeg'},...
335,[5 11 8.3851],...
{{'Fp1',...
{'Fp1','AFp9h','AFp7h','AFp5h','Fp1h',...
'AFp9','AFp7','AFp5','AFp3'}},...
{'OI2',...
{'O2','I2','POO8h','POO10h','OI2h',...
'O2h','I2h','POO6','POO8','POO10',...
'OI2'}}}},...
{'eeg1010',...
'EEG1010.lay',...
{'radius',0.1,'label',...
{'TP10','TP7','TP8','TP9','CP1','CP2',...
'PO8','PO9','POz','O1','O2','Oz'},...
'chantype','eeg'},...
12,[1 2 1.5],{{'TP9',{'TP9','TP7'}},{'O2',{'O2'}}}},...
{'eeg1020',...
'EEG1020.lay',...
{'count',5,'label','layout','chantype',...
'eeg'},...
21,[5 6 5.0952],...
{{'Fp1',{'Fp1','Fpz','F7','F3','Fz'}},...
{'O2',{'Pz','P4','O1','Oz','O2'}}}}
};