def test_auto_topomap_coords(): """Test mapping of coordinates in 3D space to 2D""" info = Raw(fif_fname).info.copy() picks = pick_types(info, meg=False, eeg=True, eog=False, stim=False) # Remove extra digitization point, so EEG digitization points match up # with the EEG channels del info['dig'][85] # Remove head origin from channel locations, so mapping with digitization # points yields the same result dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EEG, FIFF.FIFFV_POINT_EXTRA) _, origin_head, _ = fit_sphere_to_headshape(info, dig_kinds) origin_head /= 1000. # to meters for ch in info['chs']: ch['loc'][:3] -= origin_head # Use channel locations l0 = _auto_topomap_coords(info, picks) # Remove electrode position information, use digitization points from now # on. for ch in info['chs']: ch['loc'] = np.zeros(12) l1 = _auto_topomap_coords(info, picks) assert_allclose(l1, l0) # Test plotting mag topomap without channel locations: it should fail mag_picks = pick_types(info, meg='mag') assert_raises(ValueError, _auto_topomap_coords, info, mag_picks) # Test function with too many EEG digitization points: it should fail info['dig'].append({'r': [1, 2, 3], 'kind': FIFF.FIFFV_POINT_EEG}) assert_raises(ValueError, _auto_topomap_coords, info, picks) # Test function with too little EEG digitization points: it should fail info['dig'] = info['dig'][:-2] assert_raises(ValueError, _auto_topomap_coords, info, picks) # Electrode positions must be unique info['dig'].append(info['dig'][-1]) assert_raises(ValueError, _auto_topomap_coords, info, picks) # Test function without EEG digitization points: it should fail info['dig'] = [d for d in info['dig'] if d['kind'] != FIFF.FIFFV_POINT_EEG] assert_raises(RuntimeError, _auto_topomap_coords, info, picks) # Test function without any digitization points, it should fail info['dig'] = None assert_raises(RuntimeError, _auto_topomap_coords, info, picks) info['dig'] = [] assert_raises(RuntimeError, _auto_topomap_coords, info, picks)
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points.""" # Create points of various kinds rad = 0.09 big_rad = 0.12 center = np.array([0.0005, -0.01, 0.04]) dev_trans = np.array([0., -0.005, -0.01]) dev_center = center - dev_trans dig = [ # Left auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0])}, # Nasion {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0])}, # Right auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0])}, # Top of the head (extra point) {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EXTRA, 'r': np.array([0.0, 0.0, 1.0])}, # EEG points # Fz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, .72, .69])}, # F3 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([-.55, .67, .50])}, # F4 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([.55, .67, .50])}, # Cz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0.0, 0.0, 1.0])}, # Pz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, -.72, .69])}, ] for d in dig: d['r'] *= rad d['r'] += center # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = Transform('meg', 'head', translation(*(dev_trans))) info = Info(dig=dig, dev_head_t=dev_head_t) # Degenerate conditions pytest.raises(ValueError, fit_sphere_to_headshape, info, dig_kinds=(FIFF.FIFFV_POINT_HPI,)) pytest.raises(ValueError, fit_sphere_to_headshape, info, dig_kinds='foo', units='m') info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_DEVICE pytest.raises(RuntimeError, fit_sphere_to_headshape, info, units='m') info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_HEAD # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') kwargs = dict(rtol=1e-3, atol=1e-5) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with all points dig_kinds = ('cardinal', FIFF.FIFFV_POINT_EXTRA, 'eeg') kwargs = dict(rtol=1e-3, atol=1e-3) with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with some noisy EEG points only. dig_kinds = 'eeg' with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') kwargs = dict(rtol=1e-3, atol=1e-2) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, center, **kwargs) # Test big size dig_kinds = ('cardinal', 'extra') info_big = deepcopy(info) for d in info_big['dig']: d['r'] -= center d['r'] *= big_rad / rad d['r'] += center with pytest.warns(RuntimeWarning, match='Estimated head size'): r, oh, od = fit_sphere_to_headshape(info_big, dig_kinds=dig_kinds, units='mm') assert_allclose(oh, center * 1000, atol=1e-3) assert_allclose(r, big_rad * 1000, atol=1e-3) del info_big # Test offcenter dig_kinds = ('cardinal', 'extra') info_shift = deepcopy(info) shift_center = np.array([0., -0.03, 0.]) for d in info_shift['dig']: d['r'] -= center d['r'] += shift_center with pytest.warns(RuntimeWarning, match='from head frame origin'): r, oh, od = fit_sphere_to_headshape( info_shift, dig_kinds=dig_kinds, units='m') assert_allclose(oh, shift_center, atol=1e-6) assert_allclose(r, rad, atol=1e-6) # Test "auto" mode (default) # Should try "extra", fail, and go on to EEG with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, units='m') kwargs = dict(rtol=1e-3, atol=1e-3) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r2, oh2, od2 = fit_sphere_to_headshape(info, units='m') assert_allclose(r, r2, atol=1e-7) assert_allclose(oh, oh2, atol=1e-7) assert_allclose(od, od2, atol=1e-7) # this one should pass, 1 EXTRA point and 3 EEG (but the fit is terrible) info = Info(dig=dig[:7], dev_head_t=dev_head_t) with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, units='m') # this one should fail, 1 EXTRA point and 3 EEG (but the fit is terrible) info = Info(dig=dig[:6], dev_head_t=dev_head_t) pytest.raises(ValueError, fit_sphere_to_headshape, info, units='m') pytest.raises(TypeError, fit_sphere_to_headshape, 1, units='m')
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points.""" # Create points of various kinds rad = 0.09 big_rad = 0.12 center = np.array([0.0005, -0.01, 0.04]) dev_trans = np.array([0., -0.005, -0.01]) dev_center = center - dev_trans dig = [ # Left auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0])}, # Nasion {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0])}, # Right auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0])}, # Top of the head (extra point) {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EXTRA, 'ident': 0, 'r': np.array([0.0, 0.0, 1.0])}, # EEG points # Fz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'ident': 0, 'r': np.array([0, .72, .69])}, # F3 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'ident': 1, 'r': np.array([-.55, .67, .50])}, # F4 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'ident': 2, 'r': np.array([.55, .67, .50])}, # Cz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'ident': 3, 'r': np.array([0.0, 0.0, 1.0])}, # Pz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'ident': 4, 'r': np.array([0, -.72, .69])}, ] for d in dig: d['r'] *= rad d['r'] += center # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = Transform('meg', 'head', translation(*(dev_trans))) info = Info(dig=dig, dev_head_t=dev_head_t) # Degenerate conditions pytest.raises(ValueError, fit_sphere_to_headshape, info, dig_kinds=(FIFF.FIFFV_POINT_HPI,)) pytest.raises(ValueError, fit_sphere_to_headshape, info, dig_kinds='foo', units='m') info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_DEVICE pytest.raises(RuntimeError, fit_sphere_to_headshape, info, units='m') info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_HEAD # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') kwargs = dict(rtol=1e-3, atol=1e-5) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with all points dig_kinds = ('cardinal', FIFF.FIFFV_POINT_EXTRA, 'eeg') kwargs = dict(rtol=1e-3, atol=1e-3) with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with some noisy EEG points only. dig_kinds = 'eeg' with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') kwargs = dict(rtol=1e-3, atol=1e-2) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, center, **kwargs) # Test big size dig_kinds = ('cardinal', 'extra') info_big = deepcopy(info) for d in info_big['dig']: d['r'] -= center d['r'] *= big_rad / rad d['r'] += center with pytest.warns(RuntimeWarning, match='Estimated head size'): r, oh, od = fit_sphere_to_headshape(info_big, dig_kinds=dig_kinds, units='mm') assert_allclose(oh, center * 1000, atol=1e-3) assert_allclose(r, big_rad * 1000, atol=1e-3) del info_big # Test offcenter dig_kinds = ('cardinal', 'extra') info_shift = deepcopy(info) shift_center = np.array([0., -0.03, 0.]) for d in info_shift['dig']: d['r'] -= center d['r'] += shift_center with pytest.warns(RuntimeWarning, match='from head frame origin'): r, oh, od = fit_sphere_to_headshape( info_shift, dig_kinds=dig_kinds, units='m') assert_allclose(oh, shift_center, atol=1e-6) assert_allclose(r, rad, atol=1e-6) # Test "auto" mode (default) # Should try "extra", fail, and go on to EEG with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, units='m') kwargs = dict(rtol=1e-3, atol=1e-3) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r2, oh2, od2 = fit_sphere_to_headshape(info, units='m') assert_allclose(r, r2, atol=1e-7) assert_allclose(oh, oh2, atol=1e-7) assert_allclose(od, od2, atol=1e-7) # this one should pass, 1 EXTRA point and 3 EEG (but the fit is terrible) info = Info(dig=dig[:7], dev_head_t=dev_head_t) with pytest.warns(RuntimeWarning, match='Only .* head digitization'): r, oh, od = fit_sphere_to_headshape(info, units='m') # this one should fail, 1 EXTRA point and 3 EEG (but the fit is terrible) info = Info(dig=dig[:6], dev_head_t=dev_head_t) pytest.raises(ValueError, fit_sphere_to_headshape, info, units='m') pytest.raises(TypeError, fit_sphere_to_headshape, 1, units='m')
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points""" # Create points of various kinds rad = 90. # mm center = np.array([0.5, -10., 40.]) # mm dev_trans = np.array([0., -0.005, -10.]) dev_center = center - dev_trans dig = [ # Left auricular { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0]) }, # Nasion { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0]) }, # Right auricular { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0]) }, # Top of the head (extra point) { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EXTRA, 'r': np.array([0.0, 0.0, 1.0]) }, # EEG points # Fz { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, .72, .69]) }, # F3 { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([-.55, .67, .50]) }, # F4 { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([.55, .67, .50]) }, # Cz { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0.0, 0.0, 1.0]) }, # Pz { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, -.72, .69]) }, ] for d in dig: d['r'] *= rad / 1000. d['r'] += center / 1000. # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = Transform('meg', 'head', translation(*(dev_trans / 1000.))) info = {'dig': dig, 'dev_head_t': dev_head_t} # Degenerate conditions assert_raises(ValueError, fit_sphere_to_headshape, info, dig_kinds=(FIFF.FIFFV_POINT_HPI, )) info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_DEVICE assert_raises(RuntimeError, fit_sphere_to_headshape, info) info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_HEAD # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=1e-2) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with all points dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with some noisy EEG points only. dig_kinds = (FIFF.FIFFV_POINT_EEG, ) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=10.) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, center, **kwargs) dig = [dict(coord_frame=FIFF.FIFFV_COORD_DEVICE, )]
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points""" # Create points of various kinds rad = 0.09 big_rad = 0.12 center = np.array([0.0005, -0.01, 0.04]) dev_trans = np.array([0., -0.005, -0.01]) dev_center = center - dev_trans dig = [ # Left auricular { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0]) }, # Nasion { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0]) }, # Right auricular { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0]) }, # Top of the head (extra point) { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EXTRA, 'r': np.array([0.0, 0.0, 1.0]) }, # EEG points # Fz { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, .72, .69]) }, # F3 { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([-.55, .67, .50]) }, # F4 { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([.55, .67, .50]) }, # Cz { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0.0, 0.0, 1.0]) }, # Pz { 'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, -.72, .69]) }, ] for d in dig: d['r'] *= rad d['r'] += center # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = Transform('meg', 'head', translation(*(dev_trans))) info = {'dig': dig, 'dev_head_t': dev_head_t} # Degenerate conditions with warnings.catch_warnings(record=True) as w: assert_raises(ValueError, fit_sphere_to_headshape, info, dig_kinds=(FIFF.FIFFV_POINT_HPI, )) assert_equal(len(w), 1) assert_true(w[0].category == DeprecationWarning) assert_raises(ValueError, fit_sphere_to_headshape, info, dig_kinds='foo', units='m') info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_DEVICE assert_raises(RuntimeError, fit_sphere_to_headshape, info, units='m') info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_HEAD # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) with warnings.catch_warnings(record=True): # not enough points r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') kwargs = dict(rtol=1e-3, atol=1e-5) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with all points dig_kinds = ('cardinal', FIFF.FIFFV_POINT_EXTRA, 'eeg') kwargs = dict(rtol=1e-3, atol=1e-3) with warnings.catch_warnings(record=True): # not enough points r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with some noisy EEG points only. dig_kinds = 'eeg' with warnings.catch_warnings(record=True): # not enough points r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') kwargs = dict(rtol=1e-3, atol=1e-2) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, center, **kwargs) # Test big size dig_kinds = ('cardinal', 'extra') info_big = deepcopy(info) for d in info_big['dig']: d['r'] -= center d['r'] *= big_rad / rad d['r'] += center with warnings.catch_warnings(record=True): # fit with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape(info_big, dig_kinds=dig_kinds, verbose='warning', units='mm') log_file = log_file.getvalue().strip() assert_equal(len(log_file.split('\n')), 2) assert_true('Estimated head size' in log_file) assert_allclose(oh, center * 1000, atol=1e-3) assert_allclose(r, big_rad * 1000, atol=1e-3) del info_big # Test offcenter dig_kinds = ('cardinal', 'extra') info_shift = deepcopy(info) shift_center = np.array([0., -0.03, 0.]) for d in info_shift['dig']: d['r'] -= center d['r'] += shift_center with warnings.catch_warnings(record=True): with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape(info_shift, dig_kinds=dig_kinds, verbose='warning', units='m') log_file = log_file.getvalue().strip() assert_equal(len(log_file.split('\n')), 2) assert_true('from head frame origin' in log_file) assert_allclose(oh, shift_center, atol=1e-6) assert_allclose(r, rad, atol=1e-6) # Test "auto" mode (default) # Should try "extra", fail, and go on to EEG with warnings.catch_warnings(record=True): # not enough points r, oh, od = fit_sphere_to_headshape(info, units='m') kwargs = dict(rtol=1e-3, atol=1e-3) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) with warnings.catch_warnings(record=True): # not enough points r2, oh2, od2 = fit_sphere_to_headshape(info, units='m') assert_allclose(r, r2, atol=1e-7) assert_allclose(oh, oh2, atol=1e-7) assert_allclose(od, od2, atol=1e-7) # this one should pass, 1 EXTRA point and 3 EEG (but the fit is terrible) info = {'dig': dig[:7], 'dev_head_t': dev_head_t} with warnings.catch_warnings(record=True): # bad fit r, oh, od = fit_sphere_to_headshape(info, units='m') # this one should fail, 1 EXTRA point and 3 EEG (but the fit is terrible) info = {'dig': dig[:6], 'dev_head_t': dev_head_t} assert_raises(ValueError, fit_sphere_to_headshape, info, units='m')
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points""" # Create points of various kinds dig = [ # Left auricular { 'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0]) }, # Nasion { 'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0]) }, # Right auricular { 'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0]) }, # Top of the head (extra point) { 'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EXTRA, 'r': np.array([0.0, 0.0, 1.0]) }, # EEG points # Fz { 'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, .72, .69]) }, # F3 { 'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([-.55, .67, .50]) }, # F4 { 'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([.55, .67, .50]) }, # Cz { 'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0.0, 0.0, 1.0]) }, # Pz { 'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, -.72, .69]) }, ] # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = { 'from': FIFF.FIFFV_COORD_DEVICE, 'to': FIFF.FIFFV_COORD_HEAD, 'trans': rotation(x=0.2), } info = {'dig': dig, 'dev_head_t': dev_head_t} # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) assert_almost_equal(r / 1000, 1.0, decimal=10) assert_almost_equal(oh / 1000, [0.0, 0.0, 0.0], decimal=10) assert_almost_equal(od / 1000, [0.0, 0.0, 0.0], decimal=10) # Test with all points. Digitization points are no longer perfect, so # allow for a wider margin of error. dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) assert_almost_equal(r / 1000, 1.0, decimal=3) assert_almost_equal(oh / 1000, [0.0, 0.0, 0.0], decimal=3) assert_almost_equal(od / 1000, [0.0, 0.0, 0.0], decimal=3) # Test with some noisy EEG points only. dig_kinds = (FIFF.FIFFV_POINT_EEG, ) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) assert_almost_equal(r / 1000, 1.0, decimal=2) assert_almost_equal(oh / 1000, [0.0, 0.0, 0.0], decimal=2) assert_almost_equal(od / 1000, [0.0, 0.0, 0.0], decimal=2)
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points""" # Create points of various kinds rad = 90. # mm big_rad = 120. center = np.array([0.5, -10., 40.]) # mm dev_trans = np.array([0., -0.005, -10.]) dev_center = center - dev_trans dig = [ # Left auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0])}, # Nasion {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0])}, # Right auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0])}, # Top of the head (extra point) {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EXTRA, 'r': np.array([0.0, 0.0, 1.0])}, # EEG points # Fz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, .72, .69])}, # F3 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([-.55, .67, .50])}, # F4 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([.55, .67, .50])}, # Cz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0.0, 0.0, 1.0])}, # Pz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, -.72, .69])}, ] for d in dig: d['r'] *= rad / 1000. d['r'] += center / 1000. # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = Transform('meg', 'head', translation(*(dev_trans / 1000.))) info = {'dig': dig, 'dev_head_t': dev_head_t} # Degenerate conditions assert_raises(ValueError, fit_sphere_to_headshape, info, dig_kinds=(FIFF.FIFFV_POINT_HPI,)) info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_DEVICE assert_raises(RuntimeError, fit_sphere_to_headshape, info) info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_HEAD # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=1e-2) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with all points dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA, FIFF.FIFFV_POINT_EEG) kwargs = dict(rtol=1e-3, atol=1.) # in mm r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with some noisy EEG points only. dig_kinds = (FIFF.FIFFV_POINT_EEG,) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=10.) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, center, **kwargs) # Test big size dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) info_big = deepcopy(info) for d in info_big['dig']: d['r'] -= center / 1000. d['r'] *= big_rad / rad d['r'] += center / 1000. with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape(info_big, dig_kinds=dig_kinds, verbose='warning') log_file = log_file.getvalue().strip() assert_equal(len(log_file.split('\n')), 1) assert_true(log_file.startswith('Estimated head size')) assert_allclose(oh, center, atol=1e-3) assert_allclose(r, big_rad, atol=1e-3) del info_big # Test offcenter dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) info_shift = deepcopy(info) shift_center = np.array([0., -30, 0.]) for d in info_shift['dig']: d['r'] -= center / 1000. d['r'] += shift_center / 1000. with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape(info_shift, dig_kinds=dig_kinds, verbose='warning') log_file = log_file.getvalue().strip() assert_equal(len(log_file.split('\n')), 1) assert_true('from head frame origin' in log_file) assert_allclose(oh, shift_center, atol=1e-3) assert_allclose(r, rad, atol=1e-3)
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points""" # Create points of various kinds rad = 90. # mm big_rad = 120. center = np.array([0.5, -10., 40.]) # mm dev_trans = np.array([0., -0.005, -10.]) dev_center = center - dev_trans dig = [ # Left auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0])}, # Nasion {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0])}, # Right auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0])}, # Top of the head (extra point) {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EXTRA, 'r': np.array([0.0, 0.0, 1.0])}, # EEG points # Fz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, .72, .69])}, # F3 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([-.55, .67, .50])}, # F4 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([.55, .67, .50])}, # Cz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0.0, 0.0, 1.0])}, # Pz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, -.72, .69])}, ] for d in dig: d['r'] *= rad / 1000. d['r'] += center / 1000. # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = Transform('meg', 'head', translation(*(dev_trans / 1000.))) info = {'dig': dig, 'dev_head_t': dev_head_t} # Degenerate conditions assert_raises(ValueError, fit_sphere_to_headshape, info, dig_kinds=(FIFF.FIFFV_POINT_HPI,)) info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_DEVICE assert_raises(RuntimeError, fit_sphere_to_headshape, info) info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_HEAD # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=1e-2) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with all points dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA, FIFF.FIFFV_POINT_EEG) kwargs = dict(rtol=1e-3, atol=1.) # in mm r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with some noisy EEG points only. dig_kinds = (FIFF.FIFFV_POINT_EEG,) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=10.) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, center, **kwargs) # Test big size dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) info_big = deepcopy(info) for d in info_big['dig']: d['r'] -= center / 1000. d['r'] *= big_rad / rad d['r'] += center / 1000. with warnings.catch_warnings(record=True): # fit with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape(info_big, dig_kinds=dig_kinds, verbose='warning') log_file = log_file.getvalue().strip() assert_equal(len(log_file.split('\n')), 1) assert_true(log_file.startswith('Estimated head size')) assert_allclose(oh, center, atol=1e-3) assert_allclose(r, big_rad, atol=1e-3) del info_big # Test offcenter dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) info_shift = deepcopy(info) shift_center = np.array([0., -30, 0.]) for d in info_shift['dig']: d['r'] -= center / 1000. d['r'] += shift_center / 1000. with warnings.catch_warnings(record=True): with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape( info_shift, dig_kinds=dig_kinds, verbose='warning') log_file = log_file.getvalue().strip() assert_equal(len(log_file.split('\n')), 1) assert_true('from head frame origin' in log_file) assert_allclose(oh, shift_center, atol=1e-3) assert_allclose(r, rad, atol=1e-3)
def test_fit_sphere_to_headshape(): """ Test fitting a sphere to digitization points. """ # Create points of various kinds dig = [ # Left auricular {'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0])}, # Nasion {'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0])}, # Right auricular {'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0])}, # Top of the head (extra point) {'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EXTRA, 'r': np.array([0.0, 0.0, 1.0])}, # EEG points # Fz {'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, .72, .69])}, # F3 {'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([-.55, .67, .50])}, # F4 {'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([.55, .67, .50])}, # Cz {'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0.0, 0.0, 1.0])}, # Pz {'coord_frame': FIFF.FIFFV_COORD_DEVICE, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, -.72, .69])}, ] # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = { 'from': FIFF.FIFFV_COORD_DEVICE, 'to': FIFF.FIFFV_COORD_HEAD, 'trans': rotation(x=0.2), } info = {'dig': dig, 'dev_head_t': dev_head_t} # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, verbose=logging.ERROR) assert_almost_equal(r / 1000, 1.0, decimal=10) assert_almost_equal(oh / 1000, [0.0, 0.0, 0.0], decimal=10) assert_almost_equal(od / 1000, [0.0, 0.0, 0.0], decimal=10) # Test with all points. Digitization points are no longer perfect, so # allow for a wider margin of error. dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, verbose=logging.ERROR) assert_almost_equal(r / 1000, 1.0, decimal=3) assert_almost_equal(oh / 1000, [0.0, 0.0, 0.0], decimal=3) assert_almost_equal(od / 1000, [0.0, 0.0, 0.0], decimal=3) # Test with some noisy EEG points only. dig_kinds = (FIFF.FIFFV_POINT_EEG,) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, verbose=logging.ERROR) assert_almost_equal(r / 1000, 1.0, decimal=2) assert_almost_equal(oh / 1000, [0.0, 0.0, 0.0], decimal=2) assert_almost_equal(od / 1000, [0.0, 0.0, 0.0], decimal=2)
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points""" # Create points of various kinds rad = 90.0 # mm big_rad = 120.0 center = np.array([0.5, -10.0, 40.0]) # mm dev_trans = np.array([0.0, -0.005, -10.0]) dev_center = center - dev_trans dig = [ # Left auricular { "coord_frame": FIFF.FIFFV_COORD_HEAD, "ident": FIFF.FIFFV_POINT_LPA, "kind": FIFF.FIFFV_POINT_CARDINAL, "r": np.array([-1.0, 0.0, 0.0]), }, # Nasion { "coord_frame": FIFF.FIFFV_COORD_HEAD, "ident": FIFF.FIFFV_POINT_NASION, "kind": FIFF.FIFFV_POINT_CARDINAL, "r": np.array([0.0, 1.0, 0.0]), }, # Right auricular { "coord_frame": FIFF.FIFFV_COORD_HEAD, "ident": FIFF.FIFFV_POINT_RPA, "kind": FIFF.FIFFV_POINT_CARDINAL, "r": np.array([1.0, 0.0, 0.0]), }, # Top of the head (extra point) {"coord_frame": FIFF.FIFFV_COORD_HEAD, "kind": FIFF.FIFFV_POINT_EXTRA, "r": np.array([0.0, 0.0, 1.0])}, # EEG points # Fz {"coord_frame": FIFF.FIFFV_COORD_HEAD, "kind": FIFF.FIFFV_POINT_EEG, "r": np.array([0, 0.72, 0.69])}, # F3 {"coord_frame": FIFF.FIFFV_COORD_HEAD, "kind": FIFF.FIFFV_POINT_EEG, "r": np.array([-0.55, 0.67, 0.50])}, # F4 {"coord_frame": FIFF.FIFFV_COORD_HEAD, "kind": FIFF.FIFFV_POINT_EEG, "r": np.array([0.55, 0.67, 0.50])}, # Cz {"coord_frame": FIFF.FIFFV_COORD_HEAD, "kind": FIFF.FIFFV_POINT_EEG, "r": np.array([0.0, 0.0, 1.0])}, # Pz {"coord_frame": FIFF.FIFFV_COORD_HEAD, "kind": FIFF.FIFFV_POINT_EEG, "r": np.array([0, -0.72, 0.69])}, ] for d in dig: d["r"] *= rad / 1000.0 d["r"] += center / 1000.0 # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = Transform("meg", "head", translation(*(dev_trans / 1000.0))) info = {"dig": dig, "dev_head_t": dev_head_t} # Degenerate conditions assert_raises(ValueError, fit_sphere_to_headshape, info, dig_kinds=(FIFF.FIFFV_POINT_HPI,)) info["dig"][0]["coord_frame"] = FIFF.FIFFV_COORD_DEVICE assert_raises(RuntimeError, fit_sphere_to_headshape, info) info["dig"][0]["coord_frame"] = FIFF.FIFFV_COORD_HEAD # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=1e-2) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with all points dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA, FIFF.FIFFV_POINT_EEG) kwargs = dict(rtol=1e-3, atol=1.0) # in mm r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with some noisy EEG points only. dig_kinds = (FIFF.FIFFV_POINT_EEG,) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=10.0) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, center, **kwargs) # Test big size dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) info_big = deepcopy(info) for d in info_big["dig"]: d["r"] -= center / 1000.0 d["r"] *= big_rad / rad d["r"] += center / 1000.0 with warnings.catch_warnings(record=True): # fit with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape(info_big, dig_kinds=dig_kinds, verbose="warning") log_file = log_file.getvalue().strip() assert_equal(len(log_file.split("\n")), 1) assert_true(log_file.startswith("Estimated head size")) assert_allclose(oh, center, atol=1e-3) assert_allclose(r, big_rad, atol=1e-3) del info_big # Test offcenter dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) info_shift = deepcopy(info) shift_center = np.array([0.0, -30, 0.0]) for d in info_shift["dig"]: d["r"] -= center / 1000.0 d["r"] += shift_center / 1000.0 with warnings.catch_warnings(record=True): with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape(info_shift, dig_kinds=dig_kinds, verbose="warning") log_file = log_file.getvalue().strip() assert_equal(len(log_file.split("\n")), 1) assert_true("from head frame origin" in log_file) assert_allclose(oh, shift_center, atol=1e-3) assert_allclose(r, rad, atol=1e-3)
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points""" # Create points of various kinds rad = 0.09 big_rad = 0.12 center = np.array([0.0005, -0.01, 0.04]) dev_trans = np.array([0., -0.005, -0.01]) dev_center = center - dev_trans dig = [ # Left auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0])}, # Nasion {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0])}, # Right auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0])}, # Top of the head (extra point) {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EXTRA, 'r': np.array([0.0, 0.0, 1.0])}, # EEG points # Fz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, .72, .69])}, # F3 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([-.55, .67, .50])}, # F4 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([.55, .67, .50])}, # Cz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0.0, 0.0, 1.0])}, # Pz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, -.72, .69])}, ] for d in dig: d['r'] *= rad d['r'] += center # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = Transform('meg', 'head', translation(*(dev_trans))) info = {'dig': dig, 'dev_head_t': dev_head_t} # Degenerate conditions with warnings.catch_warnings(record=True) as w: assert_raises(ValueError, fit_sphere_to_headshape, info, dig_kinds=(FIFF.FIFFV_POINT_HPI,)) assert_equal(len(w), 1) assert_true(w[0].category == DeprecationWarning) assert_raises(ValueError, fit_sphere_to_headshape, info, dig_kinds='foo', units='m') info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_DEVICE assert_raises(RuntimeError, fit_sphere_to_headshape, info, units='m') info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_HEAD # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) with warnings.catch_warnings(record=True): # not enough points r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') kwargs = dict(rtol=1e-3, atol=1e-5) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with all points dig_kinds = ('cardinal', FIFF.FIFFV_POINT_EXTRA, 'eeg') kwargs = dict(rtol=1e-3, atol=1e-3) with warnings.catch_warnings(record=True): # not enough points r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with some noisy EEG points only. dig_kinds = 'eeg' with warnings.catch_warnings(record=True): # not enough points r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds, units='m') kwargs = dict(rtol=1e-3, atol=1e-2) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, center, **kwargs) # Test big size dig_kinds = ('cardinal', 'extra') info_big = deepcopy(info) for d in info_big['dig']: d['r'] -= center d['r'] *= big_rad / rad d['r'] += center with warnings.catch_warnings(record=True): # fit with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape(info_big, dig_kinds=dig_kinds, verbose='warning', units='mm') log_file = log_file.getvalue().strip() assert_equal(len(log_file.split('\n')), 2) assert_true('Estimated head size' in log_file) assert_allclose(oh, center * 1000, atol=1e-3) assert_allclose(r, big_rad * 1000, atol=1e-3) del info_big # Test offcenter dig_kinds = ('cardinal', 'extra') info_shift = deepcopy(info) shift_center = np.array([0., -0.03, 0.]) for d in info_shift['dig']: d['r'] -= center d['r'] += shift_center with warnings.catch_warnings(record=True): with catch_logging() as log_file: r, oh, od = fit_sphere_to_headshape( info_shift, dig_kinds=dig_kinds, verbose='warning', units='m') log_file = log_file.getvalue().strip() assert_equal(len(log_file.split('\n')), 2) assert_true('from head frame origin' in log_file) assert_allclose(oh, shift_center, atol=1e-6) assert_allclose(r, rad, atol=1e-6) # Test "auto" mode (default) # Should try "extra", fail, and go on to EEG with warnings.catch_warnings(record=True): # not enough points r, oh, od = fit_sphere_to_headshape(info, units='m') kwargs = dict(rtol=1e-3, atol=1e-3) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) with warnings.catch_warnings(record=True): # not enough points r2, oh2, od2 = fit_sphere_to_headshape(info, units='m') assert_allclose(r, r2, atol=1e-7) assert_allclose(oh, oh2, atol=1e-7) assert_allclose(od, od2, atol=1e-7) # this one should pass, 1 EXTRA point and 3 EEG (but the fit is terrible) info = {'dig': dig[:7], 'dev_head_t': dev_head_t} with warnings.catch_warnings(record=True): # bad fit r, oh, od = fit_sphere_to_headshape(info, units='m') # this one should fail, 1 EXTRA point and 3 EEG (but the fit is terrible) info = {'dig': dig[:6], 'dev_head_t': dev_head_t} assert_raises(ValueError, fit_sphere_to_headshape, info, units='m')
fnum_raw = "%02d" % ii_raw mfp["input_file"] = raw_fname if len(session_input_files) > 1: output_name_base = output_folder + "/" + session + "-" + fnum_raw else: output_name_base = output_folder + "/" + session if not "empt" in session.lower(): #### TYPO IN ONE SESSION NAME: emptRy!! # change this to test existence of initial HPI measurement... mfp["output_file"] = output_name_base + mf_fname_suffix + ".fif" mfp["mv_hp"] = output_name_base + mf_fname_suffix + ".pos" mfp["logfile"] = output_name_base + mf_fname_suffix + ".log" if radius_head is None: # only needed once per study (same HPI digs) raw = Raw(raw_fname) radius_head, origin_head, origin_devive = fit_sphere_to_headshape(raw.info, verbose=VERBOSE) raw.close() mfp["origin_head"] = origin_head mfp["radius_head"] = radius_head else: mfp["output_file"] = output_name_base + mf_fname_suffix + ".fif" mfp["mv_hp"] = None mfp["logfile"] = output_name_base + mf_fname_suffix + ".log" mfp["movecomp"] = False mfp["hpicons"] = False mfp["origin_head"] = False # Must be False, if None, will try to estimate it! mfp["radius_head"] = False # Since both session_input and session_output_files are lists, they # will now remain ordered 1-to-1
def test_fit_sphere_to_headshape(): """Test fitting a sphere to digitization points""" # Create points of various kinds rad = 90. # mm center = np.array([0.5, -10., 40.]) # mm dev_trans = np.array([0., -0.005, -10.]) dev_center = center - dev_trans dig = [ # Left auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_LPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([-1.0, 0.0, 0.0])}, # Nasion {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_NASION, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([0.0, 1.0, 0.0])}, # Right auricular {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'ident': FIFF.FIFFV_POINT_RPA, 'kind': FIFF.FIFFV_POINT_CARDINAL, 'r': np.array([1.0, 0.0, 0.0])}, # Top of the head (extra point) {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EXTRA, 'r': np.array([0.0, 0.0, 1.0])}, # EEG points # Fz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, .72, .69])}, # F3 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([-.55, .67, .50])}, # F4 {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([.55, .67, .50])}, # Cz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0.0, 0.0, 1.0])}, # Pz {'coord_frame': FIFF.FIFFV_COORD_HEAD, 'kind': FIFF.FIFFV_POINT_EEG, 'r': np.array([0, -.72, .69])}, ] for d in dig: d['r'] *= rad / 1000. d['r'] += center / 1000. # Device to head transformation (rotate .2 rad over X-axis) dev_head_t = Transform('meg', 'head', translation(*(dev_trans / 1000.))) info = {'dig': dig, 'dev_head_t': dev_head_t} # Degenerate conditions assert_raises(ValueError, fit_sphere_to_headshape, info, dig_kinds=(FIFF.FIFFV_POINT_HPI,)) info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_DEVICE assert_raises(RuntimeError, fit_sphere_to_headshape, info) info['dig'][0]['coord_frame'] = FIFF.FIFFV_COORD_HEAD # # Test with 4 points that match a perfect sphere dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=1e-2) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with all points dig_kinds = (FIFF.FIFFV_POINT_CARDINAL, FIFF.FIFFV_POINT_EXTRA, FIFF.FIFFV_POINT_EXTRA) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, dev_center, **kwargs) # Test with some noisy EEG points only. dig_kinds = (FIFF.FIFFV_POINT_EEG,) r, oh, od = fit_sphere_to_headshape(info, dig_kinds=dig_kinds) kwargs = dict(rtol=1e-3, atol=10.) # in mm assert_allclose(r, rad, **kwargs) assert_allclose(oh, center, **kwargs) assert_allclose(od, center, **kwargs) dig = [dict(coord_frame=FIFF.FIFFV_COORD_DEVICE, )]
mfp['input_file'] = raw_fname if len(session_input_files) > 1: output_name_base = output_folder + '/' + session + '-' + fnum_raw else: output_name_base = output_folder + '/' + session if not 'empt' in session.lower( ): #### TYPO IN ONE SESSION NAME: emptRy!! # change this to test existence of initial HPI measurement... mfp['output_file'] = output_name_base + mf_fname_suffix + '.fif' mfp['mv_hp'] = output_name_base + mf_fname_suffix + '.pos' mfp['logfile'] = output_name_base + mf_fname_suffix + '.log' if radius_head is None: # only needed once per study (same HPI digs) raw = Raw(raw_fname) radius_head, origin_head, origin_devive = fit_sphere_to_headshape( raw.info, verbose=VERBOSE) raw.close() mfp['origin_head'] = origin_head mfp['radius_head'] = radius_head else: mfp['output_file'] = output_name_base + mf_fname_suffix + '.fif' mfp['mv_hp'] = None mfp['logfile'] = output_name_base + mf_fname_suffix + '.log' mfp['movecomp'] = False mfp['hpicons'] = False mfp['origin_head'] = False # Must be False, if None, will try to estimate it! mfp['radius_head'] = False # Since both session_input and session_output_files are lists, they # will now remain ordered 1-to-1