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 _state_to_glm(glm): """ Convert state of GLM stored as dictionary to a MNE-NIRS GLM type. Parameters ---------- glm : dict State of GLM type. Returns ------- glm : _BaseGLM RegressionResults or ContrastResults class which stores the GLM results. """ if glm['classname'] == "<class 'mne_nirs.statistics._glm_level_first" \ ".RegressionResults'>": for channel in glm['data']: # Recreate model type if glm['data'][channel]['modelname'] == \ "<class 'nilearn.glm.regression.ARModel'>": model = nilearn.glm.regression.ARModel( glm['data'][channel]['model']['design'], glm['data'][channel]['model']['rho'], ) elif glm['data'][channel]['modelname'] == \ "<class 'nilearn.glm.regression.OLSModel'>": model = nilearn.glm.regression.OLSModel( glm['data'][channel]['model']['design'], ) else: raise IOError("Unknown model type " f"{glm['data'][channel]['modelname']}") for key in glm['data'][channel]['model']: model.__setattr__(key, glm['data'][channel]['model'][key]) glm['data'][channel]['model'] = model # Then recreate result type res = nilearn.glm.regression.RegressionResults( glm['data'][channel]['theta'], glm['data'][channel]['Y'], glm['data'][channel]['model'], glm['data'][channel]['whitened_Y'], glm['data'][channel]['whitened_residuals'], cov=glm['data'][channel]['cov'] ) for key in glm['data'][channel]: res.__setattr__(key, glm['data'][channel][key]) glm['data'][channel] = res # Ensure order of dictionary matches info data = {k: glm['data'][k] for k in glm['info']['ch_names']} return RegressionResults(Info(glm['info']), data, glm['design']) elif glm['classname'] == "<class 'mne_nirs.statistics._glm_level_first" \ ".ContrastResults'>": data = nilearn.glm.contrasts.Contrast(glm['data']['effect'], glm['data']['variance']) for key in glm['data']: data.__setattr__(key, glm['data'][key]) return ContrastResults(Info(glm['info']), data, glm['design']) else: raise IOError('Unable to read data')