def test_make_sphere_model(): """Test making a sphere model.""" info = read_info(fname_raw) pytest.raises(ValueError, make_sphere_model, 'foo', 'auto', info) pytest.raises(ValueError, make_sphere_model, 'auto', 'auto', None) pytest.raises(ValueError, make_sphere_model, 'auto', 'auto', info, relative_radii=(), sigmas=()) pytest.raises(ValueError, make_sphere_model, 'auto', 'auto', info, relative_radii=(1,)) # wrong number of radii # here we just make sure it works -- the functionality is actually # tested more extensively e.g. in the forward and dipole code with catch_logging() as log: bem = make_sphere_model('auto', 'auto', info, verbose=True) log = log.getvalue() assert ' RV = ' in log for line in log.split('\n'): if ' RV = ' in line: val = float(line.split()[-2]) assert val < 0.01 # actually decent fitting break assert '3 layers' in repr(bem) assert 'Sphere ' in repr(bem) assert ' mm' in repr(bem) bem = make_sphere_model('auto', None, info) assert 'no layers' in repr(bem) assert 'Sphere ' in repr(bem) pytest.raises(ValueError, make_sphere_model, sigmas=(0.33,), relative_radii=(1.0,))
def test_volume_source_space(): """Test setting up volume source spaces.""" tempdir = _TempDir() src = read_source_spaces(fname_vol) temp_name = op.join(tempdir, 'temp-src.fif') surf = read_bem_surfaces(fname_bem, s_id=FIFF.FIFFV_BEM_SURF_ID_BRAIN) surf['rr'] *= 1e3 # convert to mm # The one in the testing dataset (uses bem as bounds) for bem, surf in zip((fname_bem, None), (None, surf)): src_new = setup_volume_source_space( 'sample', pos=7.0, bem=bem, surface=surf, mri='T1.mgz', subjects_dir=subjects_dir) write_source_spaces(temp_name, src_new, overwrite=True) src[0]['subject_his_id'] = 'sample' # XXX: to make comparison pass _compare_source_spaces(src, src_new, mode='approx') del src_new src_new = read_source_spaces(temp_name) _compare_source_spaces(src, src_new, mode='approx') pytest.raises(IOError, setup_volume_source_space, 'sample', pos=7.0, bem=None, surface='foo', # bad surf mri=fname_mri, subjects_dir=subjects_dir) assert repr(src) == repr(src_new) assert src.kind == 'volume' # Spheres sphere = make_sphere_model(r0=(0., 0., 0.), head_radius=0.1, relative_radii=(0.9, 1.0), sigmas=(0.33, 1.0)) src = setup_volume_source_space(pos=10) src_new = setup_volume_source_space(pos=10, sphere=sphere) _compare_source_spaces(src, src_new, mode='exact') pytest.raises(ValueError, setup_volume_source_space, sphere='foo') # Need a radius sphere = make_sphere_model(head_radius=None) pytest.raises(ValueError, setup_volume_source_space, sphere=sphere)
def test_make_sphere_model(): """Test making a sphere model""" info = read_info(fname_raw) assert_raises(ValueError, make_sphere_model, 'foo', 'auto', info) assert_raises(ValueError, make_sphere_model, 'auto', 'auto', None) # here we just make sure it works -- the functionality is actually # tested more extensively e.g. in the forward and dipole code make_sphere_model('auto', 'auto', info)
def test_make_sphere_model(): """Test making a sphere model""" info = read_info(fname_raw) assert_raises(ValueError, make_sphere_model, "foo", "auto", info) assert_raises(ValueError, make_sphere_model, "auto", "auto", None) # here we just make sure it works -- the functionality is actually # tested more extensively e.g. in the forward and dipole code bem = make_sphere_model("auto", "auto", info) assert_true("3 layers" in repr(bem)) assert_true("Sphere " in repr(bem)) assert_true(" mm" in repr(bem)) bem = make_sphere_model("auto", None, info) assert_true("no layers" in repr(bem)) assert_true("Sphere " in repr(bem))
def test_make_forward_solution_sphere(): """Test making a forward solution with a sphere model""" temp_dir = _TempDir() fname_src_small = op.join(temp_dir, "sample-oct-2-src.fif") src = setup_source_space("sample", fname_src_small, "oct2", subjects_dir=subjects_dir, add_dist=False) out_name = op.join(temp_dir, "tmp-fwd.fif") run_subprocess( [ "mne_forward_solution", "--meg", "--eeg", "--meas", fname_raw, "--src", fname_src_small, "--mri", fname_trans, "--fwd", out_name, ] ) fwd = read_forward_solution(out_name) sphere = make_sphere_model(verbose=True) fwd_py = make_forward_solution(fname_raw, fname_trans, src, sphere, meg=True, eeg=True, verbose=True) _compare_forwards(fwd, fwd_py, 366, 108, meg_rtol=5e-1, meg_atol=1e-6, eeg_rtol=5e-1, eeg_atol=5e-1) # Since the above is pretty lax, let's check a different way for meg, eeg in zip([True, False], [False, True]): fwd_ = pick_types_forward(fwd, meg=meg, eeg=eeg) fwd_py_ = pick_types_forward(fwd, meg=meg, eeg=eeg) assert_allclose(np.corrcoef(fwd_["sol"]["data"].ravel(), fwd_py_["sol"]["data"].ravel())[0, 1], 1.0, rtol=1e-3)
def make_montage(info, kind, check=False): from . import _reorder assert kind in ('mgh60', 'mgh70', 'uw_70', 'uw_60') picks = mne.pick_types(info, meg=False, eeg=True, exclude=()) if kind in ('mgh60', 'mgh70'): ch_names = mne.utils._clean_names( [info['ch_names'][pick] for pick in picks], remove_whitespace=True) if kind == 'mgh60': assert len(ch_names) in (59, 60) else: assert len(ch_names) in (70,) montage = mne.channels.read_montage(kind, ch_names=ch_names) else: ch_names = getattr(_reorder, 'ch_names_' + kind) ch_names = ch_names montage = mne.channels.read_montage('standard_1020', ch_names=ch_names) assert len(montage.ch_names) == len(ch_names) montage.ch_names = ['EEG%03d' % ii for ii in range(1, 61)] sphere = mne.make_sphere_model('auto', 'auto', info) montage.pos /= np.linalg.norm(montage.pos, axis=-1, keepdims=True) montage.pos *= sphere.radius montage.pos += sphere['r0'] info = mne.pick_info(info, picks) eeg_pos = np.array([ch['loc'][:3] for ch in info['chs']]) assert len(eeg_pos) == len(montage.pos), (len(eeg_pos), len(montage.pos)) if check: from mayavi import mlab mlab.figure(size=(800, 800)) mlab.points3d(*sphere['r0'], scale_factor=2 * sphere.radius, color=(0., 0., 1.), opacity=0.1, mode='sphere') mlab.points3d(*montage.pos.T, scale_factor=0.01, color=(1, 0, 0), mode='sphere', opacity=0.5) mlab.points3d(*eeg_pos.T, scale_factor=0.005, color=(1, 1, 1), mode='sphere', opacity=1) return montage, sphere
def test_apply_inverse_sphere(): """Test applying an inverse with a sphere model (rank-deficient).""" evoked = _get_evoked() evoked.pick_channels(evoked.ch_names[:306:8]) evoked.info['projs'] = [] cov = make_ad_hoc_cov(evoked.info) sphere = make_sphere_model('auto', 'auto', evoked.info) fwd = read_forward_solution(fname_fwd) vertices = [fwd['src'][0]['vertno'][::5], fwd['src'][1]['vertno'][::5]] stc = SourceEstimate(np.zeros((sum(len(v) for v in vertices), 1)), vertices, 0., 1.) fwd = restrict_forward_to_stc(fwd, stc) fwd = make_forward_solution(evoked.info, fwd['mri_head_t'], fwd['src'], sphere, mindist=5.) evoked = EvokedArray(fwd['sol']['data'].copy(), evoked.info) assert fwd['sol']['nrow'] == 39 assert fwd['nsource'] == 101 assert fwd['sol']['ncol'] == 303 tempdir = _TempDir() temp_fname = op.join(tempdir, 'temp-inv.fif') inv = make_inverse_operator(evoked.info, fwd, cov, loose=1.) # This forces everything to be float32 write_inverse_operator(temp_fname, inv) inv = read_inverse_operator(temp_fname) stc = apply_inverse(evoked, inv, method='eLORETA', method_params=dict(eps=1e-2)) # assert zero localization bias assert_array_equal(np.argmax(stc.data, axis=0), np.repeat(np.arange(101), 3))
def test_simulate_raw_chpi(): """Test simulation of raw data with cHPI""" with warnings.catch_warnings(record=True): # MaxShield raw = Raw(raw_chpi_fname, allow_maxshield=True) sphere = make_sphere_model('auto', 'auto', raw.info) # make sparse spherical source space sphere_vol = tuple(sphere['r0'] * 1000.) + (sphere.radius * 1000.,) src = setup_volume_source_space('sample', sphere=sphere_vol, pos=70.) stc = _make_stc(raw, src) # simulate data with cHPI on raw_sim = simulate_raw(raw, stc, None, src, sphere, cov=None, chpi=False) raw_chpi = simulate_raw(raw, stc, None, src, sphere, cov=None, chpi=True) # XXX we need to test that the cHPI signals are actually in the correct # place, but that should be a subsequent enhancement (not trivial to do so) psd_sim, freqs_sim = compute_raw_psd(raw_sim) psd_chpi, freqs_chpi = compute_raw_psd(raw_chpi) assert_array_equal(freqs_sim, freqs_chpi) hpi_freqs = np.array([x['custom_ref'][0] for x in raw.info['hpi_meas'][0]['hpi_coils']]) freq_idx = np.sort([np.argmin(np.abs(freqs_sim - f)) for f in hpi_freqs]) picks_meg = pick_types(raw.info, meg=True, eeg=False) picks_eeg = pick_types(raw.info, meg=False, eeg=True) assert_allclose(psd_sim[picks_eeg], psd_chpi[picks_eeg]) assert_true((psd_chpi[picks_meg][:, freq_idx] > 100 * psd_sim[picks_meg][:, freq_idx]).all())
def test_make_forward_solution_sphere(): """Test making a forward solution with a sphere model.""" temp_dir = _TempDir() fname_src_small = op.join(temp_dir, 'sample-oct-2-src.fif') src = setup_source_space('sample', 'oct2', subjects_dir=subjects_dir, add_dist=False) write_source_spaces(fname_src_small, src) # to enable working with MNE-C out_name = op.join(temp_dir, 'tmp-fwd.fif') run_subprocess(['mne_forward_solution', '--meg', '--eeg', '--meas', fname_raw, '--src', fname_src_small, '--mri', fname_trans, '--fwd', out_name]) fwd = read_forward_solution(out_name) sphere = make_sphere_model(verbose=True) fwd_py = make_forward_solution(fname_raw, fname_trans, src, sphere, meg=True, eeg=True, verbose=True) _compare_forwards(fwd, fwd_py, 366, 108, meg_rtol=5e-1, meg_atol=1e-6, eeg_rtol=5e-1, eeg_atol=5e-1) # Since the above is pretty lax, let's check a different way for meg, eeg in zip([True, False], [False, True]): fwd_ = pick_types_forward(fwd, meg=meg, eeg=eeg) fwd_py_ = pick_types_forward(fwd, meg=meg, eeg=eeg) assert_allclose(np.corrcoef(fwd_['sol']['data'].ravel(), fwd_py_['sol']['data'].ravel())[0, 1], 1.0, rtol=1e-3)
def test_simulate_raw_chpi(): """Test simulation of raw data with cHPI""" with warnings.catch_warnings(record=True): # MaxShield raw = Raw(raw_chpi_fname, allow_maxshield=True) sphere = make_sphere_model('auto', 'auto', raw.info) # make sparse spherical source space sphere_vol = tuple(sphere['r0'] * 1000.) + (sphere.radius * 1000.,) src = setup_volume_source_space('sample', sphere=sphere_vol, pos=70.) stc = _make_stc(raw, src) # simulate data with cHPI on raw_sim = simulate_raw(raw, stc, None, src, sphere, cov=None, chpi=False) # need to trim extra samples off this one raw_chpi = simulate_raw(raw, stc, None, src, sphere, cov=None, chpi=True, head_pos=pos_fname) # test that the cHPI signals make some reasonable values psd_sim, freqs_sim = compute_raw_psd(raw_sim) psd_chpi, freqs_chpi = compute_raw_psd(raw_chpi) assert_array_equal(freqs_sim, freqs_chpi) hpi_freqs = _get_hpi_info(raw.info)[0] freq_idx = np.sort([np.argmin(np.abs(freqs_sim - f)) for f in hpi_freqs]) picks_meg = pick_types(raw.info, meg=True, eeg=False) picks_eeg = pick_types(raw.info, meg=False, eeg=True) assert_allclose(psd_sim[picks_eeg], psd_chpi[picks_eeg], atol=1e-20) assert_true((psd_chpi[picks_meg][:, freq_idx] > 100 * psd_sim[picks_meg][:, freq_idx]).all()) # test localization based on cHPI information trans_sim, rot_sim, t_sim = _calculate_chpi_positions(raw_chpi) trans, rot, t = get_chpi_positions(pos_fname) t -= raw.first_samp / raw.info['sfreq'] _compare_positions((trans, rot, t), (trans_sim, rot_sim, t_sim), max_dist=0.005)
def test_volume_labels_morph(tmpdir): """Test generating a source space from volume label.""" # see gh-5224 evoked = mne.read_evokeds(fname_evoked)[0].crop(0, 0) evoked.pick_channels(evoked.ch_names[:306:8]) evoked.info.normalize_proj() n_ch = len(evoked.ch_names) aseg_fname = op.join(subjects_dir, 'sample', 'mri', 'aseg.mgz') label_names = get_volume_labels_from_aseg(aseg_fname) src = setup_volume_source_space( 'sample', subjects_dir=subjects_dir, volume_label=label_names[:2], mri=aseg_fname) assert len(src) == 2 assert src.kind == 'volume' n_src = sum(s['nuse'] for s in src) sphere = make_sphere_model('auto', 'auto', evoked.info) fwd = make_forward_solution(evoked.info, fname_trans, src, sphere) assert fwd['sol']['data'].shape == (n_ch, n_src * 3) inv = make_inverse_operator(evoked.info, fwd, make_ad_hoc_cov(evoked.info), loose=1.) stc = apply_inverse(evoked, inv) assert stc.data.shape == (n_src, 1) img = stc.as_volume(src, mri_resolution=True) n_on = np.array(img.dataobj).astype(bool).sum() assert n_on == 291 # was 291 on `master` before gh-5590 img = stc.as_volume(src, mri_resolution=False) n_on = np.array(img.dataobj).astype(bool).sum() assert n_on == 44 # was 20 on `master` before gh-5590
def test_gamma_map_vol_sphere(): """Gamma MAP with a sphere forward and volumic source space""" evoked = read_evokeds(fname_evoked, condition=0, baseline=(None, 0), proj=False) evoked.resample(50, npad=100) evoked.crop(tmin=0.1, tmax=0.16) # crop to window around peak cov = read_cov(fname_cov) cov = regularize(cov, evoked.info) info = evoked.info sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080) src = mne.setup_volume_source_space(subject=None, pos=15., mri=None, sphere=(0.0, 0.0, 0.0, 80.0), bem=None, mindist=5.0, exclude=2.0) fwd = mne.make_forward_solution(info, trans=None, src=src, bem=sphere, eeg=False, meg=True) alpha = 0.5 assert_raises(ValueError, gamma_map, evoked, fwd, cov, alpha, loose=0, return_residual=False) assert_raises(ValueError, gamma_map, evoked, fwd, cov, alpha, loose=0.2, return_residual=False) stc = gamma_map(evoked, fwd, cov, alpha, tol=1e-4, xyz_same_gamma=False, update_mode=2, return_residual=False) assert_array_almost_equal(stc.times, evoked.times, 5)
def test_make_sphere_model(): """Test making a sphere model""" info = read_info(fname_raw) assert_raises(ValueError, make_sphere_model, 'foo', 'auto', info) assert_raises(ValueError, make_sphere_model, 'auto', 'auto', None) assert_raises(ValueError, make_sphere_model, 'auto', 'auto', info, relative_radii=(), sigmas=()) assert_raises(ValueError, make_sphere_model, 'auto', 'auto', info, relative_radii=(1,)) # wrong number of radii # here we just make sure it works -- the functionality is actually # tested more extensively e.g. in the forward and dipole code bem = make_sphere_model('auto', 'auto', info) assert_true('3 layers' in repr(bem)) assert_true('Sphere ' in repr(bem)) assert_true(' mm' in repr(bem)) bem = make_sphere_model('auto', None, info) assert_true('no layers' in repr(bem)) assert_true('Sphere ' in repr(bem))
def test_dipole_fitting_fixed(): """Test dipole fitting with a fixed position.""" import matplotlib.pyplot as plt tpeak = 0.073 sphere = make_sphere_model(head_radius=0.1) evoked = read_evokeds(fname_evo, baseline=(None, 0))[0] evoked.pick_types(meg=True) t_idx = np.argmin(np.abs(tpeak - evoked.times)) evoked_crop = evoked.copy().crop(tpeak, tpeak) assert_equal(len(evoked_crop.times), 1) cov = read_cov(fname_cov) dip_seq, resid = fit_dipole(evoked_crop, cov, sphere) assert isinstance(dip_seq, Dipole) assert isinstance(resid, Evoked) assert_equal(len(dip_seq.times), 1) pos, ori, gof = dip_seq.pos[0], dip_seq.ori[0], dip_seq.gof[0] amp = dip_seq.amplitude[0] # Fix position, allow orientation to change dip_free, resid_free = fit_dipole(evoked, cov, sphere, pos=pos) assert isinstance(dip_free, Dipole) assert isinstance(resid_free, Evoked) assert_allclose(dip_free.times, evoked.times) assert_allclose(np.tile(pos[np.newaxis], (len(evoked.times), 1)), dip_free.pos) assert_allclose(ori, dip_free.ori[t_idx]) # should find same ori assert (np.dot(dip_free.ori, ori).mean() < 0.9) # but few the same assert_allclose(gof, dip_free.gof[t_idx]) # ... same gof assert_allclose(amp, dip_free.amplitude[t_idx]) # and same amp assert_allclose(resid.data, resid_free.data[:, [t_idx]]) # Fix position and orientation dip_fixed, resid_fixed = fit_dipole(evoked, cov, sphere, pos=pos, ori=ori) assert (isinstance(dip_fixed, DipoleFixed)) assert_allclose(dip_fixed.times, evoked.times) assert_allclose(dip_fixed.info['chs'][0]['loc'][:3], pos) assert_allclose(dip_fixed.info['chs'][0]['loc'][3:6], ori) assert_allclose(dip_fixed.data[1, t_idx], gof) assert_allclose(resid.data, resid_fixed.data[:, [t_idx]]) _check_roundtrip_fixed(dip_fixed) # bad resetting evoked.info['bads'] = [evoked.ch_names[3]] dip_fixed, resid_fixed = fit_dipole(evoked, cov, sphere, pos=pos, ori=ori) # Degenerate conditions evoked_nan = evoked.copy().crop(0, 0) evoked_nan.data[0, 0] = None pytest.raises(ValueError, fit_dipole, evoked_nan, cov, sphere) pytest.raises(ValueError, fit_dipole, evoked, cov, sphere, ori=[1, 0, 0]) pytest.raises(ValueError, fit_dipole, evoked, cov, sphere, pos=[0, 0, 0], ori=[2, 0, 0]) pytest.raises(ValueError, fit_dipole, evoked, cov, sphere, pos=[0.1, 0, 0]) # copying dip_fixed_2 = dip_fixed.copy() dip_fixed_2.data[:] = 0. assert not np.isclose(dip_fixed.data, 0., atol=1e-20).any() # plotting plt.close('all') dip_fixed.plot() plt.close('all')
def test_make_forward_solution_discrete(): """Test making and converting a forward solution with discrete src.""" # smoke test for depth weighting and discrete source spaces src = read_source_spaces(fname_src)[0] src = SourceSpaces([src] + setup_volume_source_space( pos=dict(rr=src['rr'][src['vertno'][:3]].copy(), nn=src['nn'][src['vertno'][:3]].copy()))) sphere = make_sphere_model() fwd = make_forward_solution(fname_raw, fname_trans, src, sphere, meg=True, eeg=False) convert_forward_solution(fwd, surf_ori=True)
def test_dipole_fitting_ctf(): """Test dipole fitting with CTF data.""" raw_ctf = read_raw_ctf(fname_ctf).set_eeg_reference() events = make_fixed_length_events(raw_ctf, 1) evoked = Epochs(raw_ctf, events, 1, 0, 0, baseline=None).average() cov = make_ad_hoc_cov(evoked.info) sphere = make_sphere_model((0., 0., 0.)) # XXX Eventually we should do some better checks about accuracy, but # for now our CTF phantom fitting tutorials will have to do # (otherwise we need to add that to the testing dataset, which is # a bit too big) fit_dipole(evoked, cov, sphere)
def test_make_forward_solution_sphere(): """Test making a forward solution with a sphere model.""" temp_dir = _TempDir() fname_src_small = op.join(temp_dir, 'sample-oct-2-src.fif') src = setup_source_space('sample', 'oct2', subjects_dir=subjects_dir, add_dist=False) write_source_spaces(fname_src_small, src) # to enable working with MNE-C out_name = op.join(temp_dir, 'tmp-fwd.fif') run_subprocess(['mne_forward_solution', '--meg', '--eeg', '--meas', fname_raw, '--src', fname_src_small, '--mri', fname_trans, '--fwd', out_name]) fwd = read_forward_solution(out_name) sphere = make_sphere_model(verbose=True) fwd_py = make_forward_solution(fname_raw, fname_trans, src, sphere, meg=True, eeg=True, verbose=True) _compare_forwards(fwd, fwd_py, 366, 108, meg_rtol=5e-1, meg_atol=1e-6, eeg_rtol=5e-1, eeg_atol=5e-1) # Since the above is pretty lax, let's check a different way for meg, eeg in zip([True, False], [False, True]): fwd_ = pick_types_forward(fwd, meg=meg, eeg=eeg) fwd_py_ = pick_types_forward(fwd, meg=meg, eeg=eeg) assert_allclose(np.corrcoef(fwd_['sol']['data'].ravel(), fwd_py_['sol']['data'].ravel())[0, 1], 1.0, rtol=1e-3) # Number of layers in the sphere model doesn't matter for MEG # (as long as no sources are omitted due to distance) assert len(sphere['layers']) == 4 fwd = make_forward_solution(fname_raw, fname_trans, src, sphere, meg=True, eeg=False) sphere_1 = make_sphere_model(head_radius=None) assert len(sphere_1['layers']) == 0 assert_array_equal(sphere['r0'], sphere_1['r0']) fwd_1 = make_forward_solution(fname_raw, fname_trans, src, sphere, meg=True, eeg=False) _compare_forwards(fwd, fwd_1, 306, 108, meg_rtol=1e-12, meg_atol=1e-12) # Homogeneous model sphere = make_sphere_model(head_radius=None) with pytest.raises(RuntimeError, match='zero shells.*EEG'): make_forward_solution(fname_raw, fname_trans, src, sphere)
def test_inverse_ctf_comp(): """Test interpolation with compensated CTF data.""" ctf_dir = op.join(testing.data_path(download=False), 'CTF') raw_fname = op.join(ctf_dir, 'somMDYO-18av.ds') raw = mne.io.read_raw_ctf(raw_fname) raw.apply_gradient_compensation(1) sphere = make_sphere_model() cov = make_ad_hoc_cov(raw.info) src = mne.setup_volume_source_space( pos=dict(rr=[[0., 0., 0.01]], nn=[[0., 1., 0.]])) fwd = make_forward_solution(raw.info, None, src, sphere, eeg=False) inv = make_inverse_operator(raw.info, fwd, cov, loose=1.) apply_inverse_raw(raw, inv, 1. / 9.)
def test_gamma_map_vol_sphere(): """Gamma MAP with a sphere forward and volumic source space.""" evoked = read_evokeds(fname_evoked, condition=0, baseline=(None, 0), proj=False) evoked.resample(50, npad=100) evoked.crop(tmin=0.1, tmax=0.16) # crop to window around peak cov = read_cov(fname_cov) cov = regularize(cov, evoked.info, rank=None) info = evoked.info sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080) src = mne.setup_volume_source_space(subject=None, pos=30., mri=None, sphere=(0.0, 0.0, 0.0, 80.0), bem=None, mindist=5.0, exclude=2.0) fwd = mne.make_forward_solution(info, trans=None, src=src, bem=sphere, eeg=False, meg=True) alpha = 0.5 pytest.raises(ValueError, gamma_map, evoked, fwd, cov, alpha, loose=0, return_residual=False) pytest.raises(ValueError, gamma_map, evoked, fwd, cov, alpha, loose=0.2, return_residual=False) stc = gamma_map(evoked, fwd, cov, alpha, tol=1e-4, xyz_same_gamma=False, update_mode=2, return_residual=False) assert_array_almost_equal(stc.times, evoked.times, 5) # Compare orientation obtained using fit_dipole and gamma_map # for a simulated evoked containing a single dipole stc = mne.VolSourceEstimate(50e-9 * np.random.RandomState(42).randn(1, 4), vertices=stc.vertices[:1], tmin=stc.tmin, tstep=stc.tstep) evoked_dip = mne.simulation.simulate_evoked(fwd, stc, info, cov, nave=1e9, use_cps=True) dip_gmap = gamma_map(evoked_dip, fwd, cov, 0.1, return_as_dipoles=True) amp_max = [np.max(d.amplitude) for d in dip_gmap] dip_gmap = dip_gmap[np.argmax(amp_max)] assert (dip_gmap[0].pos[0] in src[0]['rr'][stc.vertices]) dip_fit = mne.fit_dipole(evoked_dip, cov, sphere)[0] assert (np.abs(np.dot(dip_fit.ori[0], dip_gmap.ori[0])) > 0.99)
def compute_bias(raw): events = find_events(raw, 'STI201', verbose=False) events = events[1:] # first one has an artifact tmin, tmax = -0.2, 0.1 epochs = mne.Epochs(raw, events, dipole_number, tmin, tmax, baseline=(None, -0.01), preload=True, verbose=False) sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=None, verbose=False) cov = mne.compute_covariance(epochs, tmax=0, method='oas', rank=None, verbose=False) idx = epochs.time_as_index(0.036)[0] data = epochs.get_data()[:, :, idx].T evoked = mne.EvokedArray(data, epochs.info, tmin=0.) dip = fit_dipole(evoked, cov, sphere, n_jobs=1, verbose=False)[0] actual_pos = mne.dipole.get_phantom_dipoles()[0][dipole_number - 1] misses = 1000 * np.linalg.norm(dip.pos - actual_pos, axis=-1) return misses
def test_simulate_raw_chpi(): """Test simulation of raw data with cHPI.""" raw = read_raw_fif(raw_chpi_fname, allow_maxshield='yes') picks = np.arange(len(raw.ch_names)) picks = np.setdiff1d(picks, pick_types(raw.info, meg=True, eeg=True)[::4]) raw.load_data().pick_channels([raw.ch_names[pick] for pick in picks]) raw.info.normalize_proj() sphere = make_sphere_model('auto', 'auto', raw.info) # make sparse spherical source space sphere_vol = tuple(sphere['r0'] * 1000.) + (sphere.radius * 1000.,) src = setup_volume_source_space(sphere=sphere_vol, pos=70.) stc = _make_stc(raw, src) # simulate data with cHPI on with pytest.deprecated_call(): raw_sim = simulate_raw(raw, stc, None, src, sphere, cov=None, head_pos=pos_fname, interp='zero') # need to trim extra samples off this one with pytest.deprecated_call(): raw_chpi = simulate_raw(raw, stc, None, src, sphere, cov=None, chpi=True, head_pos=pos_fname, interp='zero') # test cHPI indication hpi_freqs, hpi_pick, hpi_ons = _get_hpi_info(raw.info) assert_allclose(raw_sim[hpi_pick][0], 0.) assert_allclose(raw_chpi[hpi_pick][0], hpi_ons.sum()) # test that the cHPI signals make some reasonable values picks_meg = pick_types(raw.info, meg=True, eeg=False) picks_eeg = pick_types(raw.info, meg=False, eeg=True) for picks in [picks_meg[:3], picks_eeg[:3]]: psd_sim, freqs_sim = psd_welch(raw_sim, picks=picks) psd_chpi, freqs_chpi = psd_welch(raw_chpi, picks=picks) assert_array_equal(freqs_sim, freqs_chpi) freq_idx = np.sort([np.argmin(np.abs(freqs_sim - f)) for f in hpi_freqs]) if picks is picks_meg: assert (psd_chpi[:, freq_idx] > 100 * psd_sim[:, freq_idx]).all() else: assert_allclose(psd_sim, psd_chpi, atol=1e-20) # test localization based on cHPI information quats_sim = _calculate_chpi_positions(raw_chpi, t_step_min=10.) quats = read_head_pos(pos_fname) _assert_quats(quats, quats_sim, dist_tol=5e-3, angle_tol=3.5)
def _get_data(): """Helper to get some starting data""" # raw with ECG channel raw = Raw(raw_fname).crop(0.0, 5.0).load_data() data_picks = pick_types(raw.info, meg=True, eeg=True) other_picks = pick_types(raw.info, meg=False, stim=True, eog=True) picks = np.sort(np.concatenate((data_picks[::16], other_picks))) raw = raw.pick_channels([raw.ch_names[p] for p in picks]) ecg = RawArray(np.zeros((1, len(raw.times))), create_info(["ECG 063"], raw.info["sfreq"], "ecg")) for key in ("dev_head_t", "buffer_size_sec", "highpass", "lowpass", "filename", "dig"): ecg.info[key] = raw.info[key] raw.add_channels([ecg]) src = read_source_spaces(src_fname) trans = read_trans(trans_fname) sphere = make_sphere_model("auto", "auto", raw.info) stc = _make_stc(raw, src) return raw, src, stc, trans, sphere
def test_lcmv_ctf_comp(): """Test interpolation with compensated CTF data.""" ctf_dir = op.join(testing.data_path(download=False), 'CTF') raw_fname = op.join(ctf_dir, 'somMDYO-18av.ds') raw = mne.io.read_raw_ctf(raw_fname, preload=True) events = mne.make_fixed_length_events(raw, duration=0.2)[:2] epochs = mne.Epochs(raw, events, tmin=0., tmax=0.2) evoked = epochs.average() with pytest.warns(RuntimeWarning, match='Too few samples .* estimate may be unreliable'): data_cov = mne.compute_covariance(epochs) fwd = mne.make_forward_solution(evoked.info, None, mne.setup_volume_source_space(pos=15.0), mne.make_sphere_model()) filters = mne.beamformer.make_lcmv(evoked.info, fwd, data_cov) assert 'weights' in filters
def test_inverse_ctf_comp(): """Test interpolation with compensated CTF data.""" raw = mne.io.read_raw_ctf(fname_raw_ctf).crop(0, 0) raw.apply_gradient_compensation(1) sphere = make_sphere_model() cov = make_ad_hoc_cov(raw.info) src = mne.setup_volume_source_space( pos=dict(rr=[[0., 0., 0.01]], nn=[[0., 1., 0.]])) fwd = make_forward_solution(raw.info, None, src, sphere, eeg=False) raw.apply_gradient_compensation(0) with pytest.raises(RuntimeError, match='compensation grade mismatch'): make_inverse_operator(raw.info, fwd, cov, loose=1.) raw.apply_gradient_compensation(1) inv = make_inverse_operator(raw.info, fwd, cov, loose=1.) apply_inverse_raw(raw, inv, 1. / 9.) # smoke test raw.apply_gradient_compensation(0) with pytest.raises(RuntimeError, match='compensation grade mismatch'): apply_inverse_raw(raw, inv, 1. / 9.)
def test_rap_music_sphere(): """Test RAP-MUSIC with real data, sphere model, MEG only.""" evoked, noise_cov = _get_data(ch_decim=8) sphere = mne.make_sphere_model(r0=(0., 0., 0.04)) src = mne.setup_volume_source_space(subject=None, pos=10., sphere=(0.0, 0.0, 40, 65.0), mindist=5.0, exclude=0.0) forward = mne.make_forward_solution(evoked.info, trans=None, src=src, bem=sphere) dipoles = rap_music(evoked, forward, noise_cov, n_dipoles=2) # Test that there is one dipole on each hemisphere pos = np.array([dip.pos[0] for dip in dipoles]) assert_equal(pos.shape, (2, 3)) assert_equal((pos[:, 0] < 0).sum(), 1) assert_equal((pos[:, 0] > 0).sum(), 1) # Check the amplitude scale assert_true(1e-10 < dipoles[0].amplitude[0] < 1e-7)
def test_mxne_vol_sphere(): """(TF-)MxNE with a sphere forward and volumic source space""" evoked = read_evokeds(fname_data, condition=0, baseline=(None, 0)) evoked.crop(tmin=-0.05, tmax=0.2) cov = read_cov(fname_cov) evoked_l21 = evoked.copy() evoked_l21.crop(tmin=0.081, tmax=0.1) info = evoked.info sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080) src = mne.setup_volume_source_space(subject=None, pos=15., mri=None, sphere=(0.0, 0.0, 0.0, 80.0), bem=None, mindist=5.0, exclude=2.0) fwd = mne.make_forward_solution(info, trans=None, src=src, bem=sphere, eeg=False, meg=True) alpha = 80. assert_raises(ValueError, mixed_norm, evoked, fwd, cov, alpha, loose=0.0, return_residual=False, maxit=3, tol=1e-8, active_set_size=10) assert_raises(ValueError, mixed_norm, evoked, fwd, cov, alpha, loose=0.2, return_residual=False, maxit=3, tol=1e-8, active_set_size=10) # irMxNE tests stc = mixed_norm(evoked_l21, fwd, cov, alpha, n_mxne_iter=1, maxit=30, tol=1e-8, active_set_size=10) assert_true(isinstance(stc, VolSourceEstimate)) assert_array_almost_equal(stc.times, evoked_l21.times, 5) # Do with TF-MxNE for test memory savings alpha_space = 60. # spatial regularization parameter alpha_time = 1. # temporal regularization parameter stc, _ = tf_mixed_norm(evoked, fwd, cov, alpha_space, alpha_time, maxit=3, tol=1e-4, tstep=16, wsize=32, window=0.1, return_residual=True) assert_true(isinstance(stc, VolSourceEstimate)) assert_array_almost_equal(stc.times, evoked.times, 5)
def test_simulate_raw_chpi(): """Test simulation of raw data with cHPI.""" raw = read_raw_fif(raw_chpi_fname, allow_maxshield='yes', add_eeg_ref=False) sphere = make_sphere_model('auto', 'auto', raw.info) # make sparse spherical source space sphere_vol = tuple(sphere['r0'] * 1000.) + (sphere.radius * 1000.,) src = setup_volume_source_space('sample', sphere=sphere_vol, pos=70.) stc = _make_stc(raw, src) # simulate data with cHPI on raw_sim = simulate_raw(raw, stc, None, src, sphere, cov=None, chpi=False) # need to trim extra samples off this one raw_chpi = simulate_raw(raw, stc, None, src, sphere, cov=None, chpi=True, head_pos=pos_fname) # test cHPI indication hpi_freqs, _, hpi_pick, hpi_ons = _get_hpi_info(raw.info)[:4] assert_allclose(raw_sim[hpi_pick][0], 0.) assert_allclose(raw_chpi[hpi_pick][0], hpi_ons.sum()) # test that the cHPI signals make some reasonable values picks_meg = pick_types(raw.info, meg=True, eeg=False) picks_eeg = pick_types(raw.info, meg=False, eeg=True) for picks in [picks_meg, picks_eeg]: psd_sim, freqs_sim = psd_welch(raw_sim, picks=picks) psd_chpi, freqs_chpi = psd_welch(raw_chpi, picks=picks) assert_array_equal(freqs_sim, freqs_chpi) freq_idx = np.sort([np.argmin(np.abs(freqs_sim - f)) for f in hpi_freqs]) if picks is picks_meg: assert_true((psd_chpi[:, freq_idx] > 100 * psd_sim[:, freq_idx]).all()) else: assert_allclose(psd_sim, psd_chpi, atol=1e-20) # test localization based on cHPI information quats_sim = _calculate_chpi_positions(raw_chpi) trans_sim, rot_sim, t_sim = head_pos_to_trans_rot_t(quats_sim) trans, rot, t = head_pos_to_trans_rot_t(read_head_pos(pos_fname)) t -= raw.first_samp / raw.info['sfreq'] _compare_positions((trans, rot, t), (trans_sim, rot_sim, t_sim), max_dist=0.005)
def _get_data(): """Helper to get some starting data.""" # raw with ECG channel raw = read_raw_fif(raw_fname).crop(0., 5.0).load_data() data_picks = pick_types(raw.info, meg=True, eeg=True) other_picks = pick_types(raw.info, meg=False, stim=True, eog=True) picks = np.sort(np.concatenate((data_picks[::16], other_picks))) raw = raw.pick_channels([raw.ch_names[p] for p in picks]) raw.info.normalize_proj() ecg = RawArray(np.zeros((1, len(raw.times))), create_info(['ECG 063'], raw.info['sfreq'], 'ecg')) for key in ('dev_head_t', 'buffer_size_sec', 'highpass', 'lowpass', 'dig'): ecg.info[key] = raw.info[key] raw.add_channels([ecg]) src = read_source_spaces(src_fname) trans = read_trans(trans_fname) sphere = make_sphere_model('auto', 'auto', raw.info) stc = _make_stc(raw, src) return raw, src, stc, trans, sphere
def test_dipole_fitting_fixed(): """Test dipole fitting with a fixed position""" tpeak = 0.073 sphere = make_sphere_model(head_radius=0.1) evoked = read_evokeds(fname_evo, baseline=(None, 0))[0] evoked.pick_types(meg=True) t_idx = np.argmin(np.abs(tpeak - evoked.times)) evoked_crop = evoked.copy().crop(tpeak, tpeak) assert_equal(len(evoked_crop.times), 1) cov = read_cov(fname_cov) dip_seq, resid = fit_dipole(evoked_crop, cov, sphere) assert_true(isinstance(dip_seq, Dipole)) assert_equal(len(dip_seq.times), 1) pos, ori, gof = dip_seq.pos[0], dip_seq.ori[0], dip_seq.gof[0] amp = dip_seq.amplitude[0] # Fix position, allow orientation to change dip_free, resid_free = fit_dipole(evoked, cov, sphere, pos=pos) assert_true(isinstance(dip_free, Dipole)) assert_allclose(dip_free.times, evoked.times) assert_allclose(np.tile(pos[np.newaxis], (len(evoked.times), 1)), dip_free.pos) assert_allclose(ori, dip_free.ori[t_idx]) # should find same ori assert_true(np.dot(dip_free.ori, ori).mean() < 0.9) # but few the same assert_allclose(gof, dip_free.gof[t_idx]) # ... same gof assert_allclose(amp, dip_free.amplitude[t_idx]) # and same amp assert_allclose(resid, resid_free[:, [t_idx]]) # Fix position and orientation dip_fixed, resid_fixed = fit_dipole(evoked, cov, sphere, pos=pos, ori=ori) assert_true(isinstance(dip_fixed, DipoleFixed)) assert_allclose(dip_fixed.times, evoked.times) assert_allclose(dip_fixed.info['chs'][0]['loc'][:3], pos) assert_allclose(dip_fixed.info['chs'][0]['loc'][3:6], ori) assert_allclose(dip_fixed.data[1, t_idx], gof) assert_allclose(resid, resid_fixed[:, [t_idx]]) _check_roundtrip_fixed(dip_fixed) # Degenerate conditions assert_raises(ValueError, fit_dipole, evoked, cov, sphere, pos=[0]) assert_raises(ValueError, fit_dipole, evoked, cov, sphere, ori=[1, 0, 0]) assert_raises(ValueError, fit_dipole, evoked, cov, sphere, pos=[0, 0, 0], ori=[2, 0, 0]) assert_raises(ValueError, fit_dipole, evoked, cov, sphere, pos=[0.1, 0, 0])
def test_accuracy(): """Test dipole fitting to sub-mm accuracy.""" evoked = read_evokeds(fname_evo)[0].crop(0., 0.,) evoked.pick_types(meg=True, eeg=False) evoked.pick_channels([c for c in evoked.ch_names[::4]]) for rad, perc_90 in zip((0.09, None), (0.002, 0.004)): bem = make_sphere_model('auto', rad, evoked.info, relative_radii=(0.999, 0.998, 0.997, 0.995)) src = read_source_spaces(fname_src) fwd = make_forward_solution(evoked.info, None, src, bem) fwd = convert_forward_solution(fwd, force_fixed=True, use_cps=True) vertices = [src[0]['vertno'], src[1]['vertno']] n_vertices = sum(len(v) for v in vertices) amp = 10e-9 data = np.eye(n_vertices + 1)[:n_vertices] data[-1, -1] = 1. data *= amp stc = SourceEstimate(data, vertices, 0., 1e-3, 'sample') evoked.info.normalize_proj() sim = simulate_evoked(fwd, stc, evoked.info, cov=None, nave=np.inf) cov = make_ad_hoc_cov(evoked.info) dip = fit_dipole(sim, cov, bem, min_dist=0.001)[0] ds = [] for vi in range(n_vertices): if vi < len(vertices[0]): hi = 0 vertno = vi else: hi = 1 vertno = vi - len(vertices[0]) vertno = src[hi]['vertno'][vertno] rr = src[hi]['rr'][vertno] d = np.sqrt(np.sum((rr - dip.pos[vi]) ** 2)) ds.append(d) # make sure that our median is sub-mm and the large majority are very # close (we expect some to be off by a bit e.g. because they are # radial) assert_true((np.percentile(ds, [50, 90]) < [0.0005, perc_90]).all())
def test_iterable(): """Test iterable support for simulate_raw.""" raw = read_raw_fif(raw_fname_short).load_data() raw.pick_channels(raw.ch_names[:10] + ['STI 014']) src = setup_volume_source_space( pos=dict(rr=[[-0.05, 0, 0], [0.1, 0, 0]], nn=[[0, 1., 0], [0, 1., 0]])) assert src.kind == 'discrete' trans = None sphere = make_sphere_model(head_radius=None, info=raw.info) tstep = 1. / raw.info['sfreq'] rng = np.random.RandomState(0) vertices = np.array([1]) data = rng.randn(1, 2) stc = VolSourceEstimate(data, vertices, 0, tstep) assert isinstance(stc.vertices, np.ndarray) with pytest.raises(ValueError, match='at least three time points'): simulate_raw(raw.info, stc, trans, src, sphere, None) data = rng.randn(1, 1000) n_events = (len(raw.times) - 1) // 1000 + 1 stc = VolSourceEstimate(data, vertices, 0, tstep) assert isinstance(stc.vertices, np.ndarray) raw_sim = simulate_raw(raw.info, [stc] * 15, trans, src, sphere, None, first_samp=raw.first_samp) raw_sim.crop(0, raw.times[-1]) assert_allclose(raw.times, raw_sim.times) events = find_events(raw_sim, initial_event=True) assert len(events) == n_events assert_array_equal(events[:, 2], 1) # Degenerate STCs with pytest.raises(RuntimeError, match=r'Iterable did not provide stc\[0\]'): simulate_raw(raw.info, [], trans, src, sphere, None) # tuple with ndarray event_data = np.zeros(len(stc.times), int) event_data[0] = 3 raw_new = simulate_raw(raw.info, [(stc, event_data)] * 15, trans, src, sphere, None, first_samp=raw.first_samp) assert raw_new.n_times == 15000 raw_new.crop(0, raw.times[-1]) _assert_iter_sim(raw_sim, raw_new, 3) with pytest.raises(ValueError, match='event data had shape .* but need'): simulate_raw(raw.info, [(stc, event_data[:-1])], trans, src, sphere, None) with pytest.raises(ValueError, match='stim_data in a stc tuple .* int'): simulate_raw(raw.info, [(stc, event_data * 1.)], trans, src, sphere, None) # iterable def stc_iter(): stim_data = np.zeros(len(stc.times), int) stim_data[0] = 4 ii = 0 while ii < 15: ii += 1 yield (stc, stim_data) raw_new = simulate_raw(raw.info, stc_iter(), trans, src, sphere, None, first_samp=raw.first_samp) raw_new.crop(0, raw.times[-1]) _assert_iter_sim(raw_sim, raw_new, 4) def stc_iter_bad(): ii = 0 while ii < 100: ii += 1 yield (stc, 4, 3) with pytest.raises(ValueError, match='stc, if tuple, must be length'): simulate_raw(raw.info, stc_iter_bad(), trans, src, sphere, None) _assert_iter_sim(raw_sim, raw_new, 4) def stc_iter_bad(): ii = 0 while ii < 100: ii += 1 stc_new = stc.copy() stc_new.vertices = np.array([ii % 2]) yield stc_new with pytest.raises(RuntimeError, match=r'Vertex mismatch for stc\[1\]'): simulate_raw(raw.info, stc_iter_bad(), trans, src, sphere, None) # Forward omission vertices = np.array([0, 1]) data = rng.randn(2, 1000) stc = VolSourceEstimate(data, vertices, 0, tstep) assert isinstance(stc.vertices, np.ndarray) # XXX eventually we should support filtering based on sphere radius, too, # by refactoring the code in source_space.py that does it! surf = _get_ico_surface(3) surf['rr'] *= 60 # mm model = _surfaces_to_bem([surf], [FIFF.FIFFV_BEM_SURF_ID_BRAIN], [0.3]) bem = make_bem_solution(model) with pytest.warns(RuntimeWarning, match='1 of 2 SourceEstimate vertices'): simulate_raw(raw.info, stc, trans, src, bem, None)
def test_plot_alignment(): """Test plotting of -trans.fif files and MEG sensor layouts.""" # generate fiducials file for testing tempdir = _TempDir() fiducials_path = op.join(tempdir, 'fiducials.fif') fid = [{'coord_frame': 5, 'ident': 1, 'kind': 1, 'r': [-0.08061612, -0.02908875, -0.04131077]}, {'coord_frame': 5, 'ident': 2, 'kind': 1, 'r': [0.00146763, 0.08506715, -0.03483611]}, {'coord_frame': 5, 'ident': 3, 'kind': 1, 'r': [0.08436285, -0.02850276, -0.04127743]}] write_dig(fiducials_path, fid, 5) mlab = _import_mlab() evoked = read_evokeds(evoked_fname)[0] sample_src = read_source_spaces(src_fname) with warnings.catch_warnings(record=True): # 4D weight tables bti = read_raw_bti(pdf_fname, config_fname, hs_fname, convert=True, preload=False).info infos = dict( Neuromag=evoked.info, CTF=read_raw_ctf(ctf_fname).info, BTi=bti, KIT=read_raw_kit(sqd_fname).info, ) for system, info in infos.items(): meg = ['helmet', 'sensors'] if system == 'KIT': meg.append('ref') plot_alignment(info, trans_fname, subject='sample', subjects_dir=subjects_dir, meg=meg) mlab.close(all=True) # KIT ref sensor coil def is defined mlab.close(all=True) info = infos['Neuromag'] assert_raises(TypeError, plot_alignment, 'foo', trans_fname, subject='sample', subjects_dir=subjects_dir) assert_raises(TypeError, plot_alignment, info, trans_fname, subject='sample', subjects_dir=subjects_dir, src='foo') assert_raises(ValueError, plot_alignment, info, trans_fname, subject='fsaverage', subjects_dir=subjects_dir, src=sample_src) sample_src.plot(subjects_dir=subjects_dir, head=True, skull=True, brain='white') mlab.close(all=True) # no-head version mlab.close(all=True) # all coord frames for coord_frame in ('meg', 'head', 'mri'): plot_alignment(info, meg=['helmet', 'sensors'], dig=True, coord_frame=coord_frame, trans=trans_fname, subject='sample', mri_fiducials=fiducials_path, subjects_dir=subjects_dir, src=sample_src) mlab.close(all=True) # EEG only with strange options evoked_eeg_ecog = evoked.copy().pick_types(meg=False, eeg=True) evoked_eeg_ecog.info['projs'] = [] # "remove" avg proj evoked_eeg_ecog.set_channel_types({'EEG 001': 'ecog'}) with warnings.catch_warnings(record=True) as w: plot_alignment(evoked_eeg_ecog.info, subject='sample', trans=trans_fname, subjects_dir=subjects_dir, surfaces=['white', 'outer_skin', 'outer_skull'], meg=['helmet', 'sensors'], eeg=['original', 'projected'], ecog=True) mlab.close(all=True) assert_true(['Cannot plot MEG' in str(ww.message) for ww in w]) sphere = make_sphere_model(info=evoked.info, r0='auto', head_radius='auto') bem_sol = read_bem_solution(op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem-sol.fif')) bem_surfs = read_bem_surfaces(op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem.fif')) sample_src[0]['coord_frame'] = 4 # hack for coverage plot_alignment(info, trans_fname, subject='sample', meg='helmet', subjects_dir=subjects_dir, eeg='projected', bem=sphere, surfaces=['head', 'brain'], src=sample_src) plot_alignment(info, trans_fname, subject='sample', meg=[], subjects_dir=subjects_dir, bem=bem_sol, eeg=True, surfaces=['head', 'inflated', 'outer_skull', 'inner_skull']) plot_alignment(info, trans_fname, subject='sample', meg=True, subjects_dir=subjects_dir, surfaces=['head', 'inner_skull'], bem=bem_surfs) sphere = make_sphere_model('auto', None, evoked.info) # one layer plot_alignment(info, trans_fname, subject='sample', meg=False, coord_frame='mri', subjects_dir=subjects_dir, surfaces=['brain'], bem=sphere) # one layer bem with skull surfaces: assert_raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['brain', 'head', 'inner_skull'], bem=sphere) # wrong eeg value: assert_raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, eeg='foo') # wrong meg value: assert_raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, meg='bar') # multiple brain surfaces: assert_raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['white', 'pial']) assert_raises(TypeError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=[1]) assert_raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['foo'])
import mne from mne.datasets import sample import numpy as np from sim_funcs import fit_dips sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=None) # Use this for all testing perts = dict(max_percent_imb=10, variance_imb=0, preferred_side_imb=1, max_error_nn=0, variance_nn=0, preferred_direction_nn=0, max_translation=4) sign = perts['preferred_side_imb'] max_imbalance = perts['max_percent_imb'] max_shift = perts['max_translation'] local_data_path = 'C:\Pert_Inv\Local_mne_data\side%s' % (sign, ) min_rad, max_rad = 0, 90 big_data = np.zeros( (max_shift + 1, max_imbalance + 1, max_rad - min_rad + 1, 22)) nn = [0, 1, 1] sourcenorm = [0, 1, 0] / np.linalg.norm([0, 1, 0]) for l in range(0, max_shift + 1): perts['max_translation'] = l for k in range(0, max_imbalance + 1): perts['max_percent_imb'] = k dip_fit_long, dip_fit_pert, testsources = fit_dips( min_rad, max_rad, nn, sphere, perts, sourcenorm)
def test_simulate_raw_sphere(): """Test simulation of raw data with sphere model.""" seed = 42 raw, src, stc, trans, sphere = _get_data() assert len(pick_types(raw.info, meg=False, ecg=True)) == 1 # head pos head_pos_sim = dict() # these will be at 1., 2., ... sec shifts = [[0.001, 0., -0.001], [-0.001, 0.001, 0.]] for time_key, shift in enumerate(shifts): # Create 4x4 matrix transform and normalize temp_trans = deepcopy(raw.info['dev_head_t']) temp_trans['trans'][:3, 3] += shift head_pos_sim[time_key + 1.] = temp_trans['trans'] # # Test raw simulation with basic parameters # raw_sim = simulate_raw(raw, stc, trans, src, sphere, read_cov(cov_fname), head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed, use_cps=True) raw_sim_2 = simulate_raw(raw, stc, trans_fname, src_fname, sphere, cov_fname, head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed, use_cps=True) assert_array_equal(raw_sim_2[:][0], raw_sim[:][0]) std = dict(grad=2e-13, mag=10e-15, eeg=0.1e-6) raw_sim = simulate_raw(raw, stc, trans, src, sphere, make_ad_hoc_cov(raw.info, std=std), head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed, use_cps=True) raw_sim_2 = simulate_raw(raw, stc, trans_fname, src_fname, sphere, cov=std, head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed, use_cps=True) assert_array_equal(raw_sim_2[:][0], raw_sim[:][0]) sphere_norad = make_sphere_model('auto', None, raw.info) raw_meg = raw.copy().pick_types() raw_sim = simulate_raw(raw_meg, stc, trans, src, sphere_norad, make_ad_hoc_cov(raw.info, std=None), head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed, use_cps=True) raw_sim_2 = simulate_raw(raw_meg, stc, trans_fname, src_fname, sphere_norad, cov='simple', head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed, use_cps=True) assert_array_equal(raw_sim_2[:][0], raw_sim[:][0]) # Test IO on processed data tempdir = _TempDir() test_outname = op.join(tempdir, 'sim_test_raw.fif') raw_sim.save(test_outname) raw_sim_loaded = read_raw_fif(test_outname, preload=True) assert_allclose(raw_sim_loaded[:][0], raw_sim[:][0], rtol=1e-6, atol=1e-20) del raw_sim, raw_sim_2 # with no cov (no noise) but with artifacts, most time periods should match # but the EOG/ECG channels should not for ecg, eog in ((True, False), (False, True), (True, True)): raw_sim_3 = simulate_raw(raw, stc, trans, src, sphere, cov=None, head_pos=head_pos_sim, blink=eog, ecg=ecg, random_state=seed, use_cps=True) raw_sim_4 = simulate_raw(raw, stc, trans, src, sphere, cov=None, head_pos=head_pos_sim, blink=False, ecg=False, random_state=seed, use_cps=True) picks = np.arange(len(raw.ch_names)) diff_picks = pick_types(raw.info, meg=False, ecg=ecg, eog=eog) these_picks = np.setdiff1d(picks, diff_picks) close = np.isclose(raw_sim_3[these_picks][0], raw_sim_4[these_picks][0], atol=1e-20) assert np.mean(close) > 0.7 far = ~np.isclose( raw_sim_3[diff_picks][0], raw_sim_4[diff_picks][0], atol=1e-20) assert np.mean(far) > 0.99 del raw_sim_3, raw_sim_4 # make sure it works with EEG-only and MEG-only raw_sim_meg = simulate_raw(raw.copy().pick_types(meg=True, eeg=False), stc, trans, src, sphere, cov=None, ecg=True, blink=True, random_state=seed, use_cps=True) raw_sim_eeg = simulate_raw(raw.copy().pick_types(meg=False, eeg=True), stc, trans, src, sphere, cov=None, ecg=True, blink=True, random_state=seed, use_cps=True) raw_sim_meeg = simulate_raw(raw.copy().pick_types(meg=True, eeg=True), stc, trans, src, sphere, cov=None, ecg=True, blink=True, random_state=seed, use_cps=True) assert_allclose(np.concatenate((raw_sim_meg[:][0], raw_sim_eeg[:][0])), raw_sim_meeg[:][0], rtol=1e-7, atol=1e-20) del raw_sim_meg, raw_sim_eeg, raw_sim_meeg # check that different interpolations are similar given small movements raw_sim = simulate_raw(raw, stc, trans, src, sphere, cov=None, head_pos=head_pos_sim, interp='linear', use_cps=True) raw_sim_hann = simulate_raw(raw, stc, trans, src, sphere, cov=None, head_pos=head_pos_sim, interp='hann', use_cps=True) assert_allclose(raw_sim[:][0], raw_sim_hann[:][0], rtol=1e-1, atol=1e-14) del raw_sim, raw_sim_hann # Make impossible transform (translate up into helmet) and ensure failure head_pos_sim_err = deepcopy(head_pos_sim) head_pos_sim_err[1.][2, 3] -= 0.1 # z trans upward 10cm pytest.raises(RuntimeError, simulate_raw, raw, stc, trans, src, sphere, ecg=False, blink=False, head_pos=head_pos_sim_err, use_cps=True) pytest.raises(RuntimeError, simulate_raw, raw, stc, trans, src, bem_fname, ecg=False, blink=False, head_pos=head_pos_sim_err, use_cps=True) # other degenerate conditions pytest.raises(TypeError, simulate_raw, 'foo', stc, trans, src, sphere, use_cps=True) pytest.raises(TypeError, simulate_raw, raw, 'foo', trans, src, sphere, use_cps=True) pytest.raises(ValueError, simulate_raw, raw, stc.copy().crop(0, 0), trans, src, sphere, use_cps=True) stc_bad = stc.copy() stc_bad.tstep += 0.1 pytest.raises(ValueError, simulate_raw, raw, stc_bad, trans, src, sphere, use_cps=True) pytest.raises(TypeError, simulate_raw, raw, stc, trans, src, sphere, cov=0, use_cps=True) # wrong covariance type pytest.raises(RuntimeError, simulate_raw, raw, stc, trans, src, sphere, chpi=True, use_cps=True) # no cHPI info pytest.raises(ValueError, simulate_raw, raw, stc, trans, src, sphere, interp='foo', use_cps=True) pytest.raises(TypeError, simulate_raw, raw, stc, trans, src, sphere, head_pos=1., use_cps=True) pytest.raises(RuntimeError, simulate_raw, raw, stc, trans, src, sphere, head_pos=pos_fname, use_cps=True) # ends up with t>t_end head_pos_sim_err = deepcopy(head_pos_sim) head_pos_sim_err[-1.] = head_pos_sim_err[1.] # negative time pytest.raises(RuntimeError, simulate_raw, raw, stc, trans, src, sphere, head_pos=head_pos_sim_err, use_cps=True) raw_bad = raw.copy() raw_bad.info['dig'] = None pytest.raises(RuntimeError, simulate_raw, raw_bad, stc, trans, src, sphere, blink=True, use_cps=True)
def test_dipole_fitting(tmpdir): """Test dipole fitting.""" amp = 100e-9 tempdir = str(tmpdir) rng = np.random.RandomState(0) fname_dtemp = op.join(tempdir, 'test.dip') fname_sim = op.join(tempdir, 'test-ave.fif') fwd = convert_forward_solution(read_forward_solution(fname_fwd), surf_ori=False, force_fixed=True, use_cps=True) evoked = read_evokeds(fname_evo)[0] cov = read_cov(fname_cov) n_per_hemi = 5 vertices = [ np.sort(rng.permutation(s['vertno'])[:n_per_hemi]) for s in fwd['src'] ] nv = sum(len(v) for v in vertices) stc = SourceEstimate(amp * np.eye(nv), vertices, 0, 0.001) evoked = simulate_evoked(fwd, stc, evoked.info, cov, nave=evoked.nave, random_state=rng) # For speed, let's use a subset of channels (strange but works) picks = np.sort( np.concatenate([ pick_types(evoked.info, meg=True, eeg=False)[::2], pick_types(evoked.info, meg=False, eeg=True)[::2] ])) evoked.pick_channels([evoked.ch_names[p] for p in picks]) evoked.add_proj(make_eeg_average_ref_proj(evoked.info)) write_evokeds(fname_sim, evoked) # Run MNE-C version run_subprocess([ 'mne_dipole_fit', '--meas', fname_sim, '--meg', '--eeg', '--noise', fname_cov, '--dip', fname_dtemp, '--mri', fname_fwd, '--reg', '0', '--tmin', '0', ]) dip_c = read_dipole(fname_dtemp) # Run mne-python version sphere = make_sphere_model(head_radius=0.1) with pytest.warns(RuntimeWarning, match='projection'): dip, residual = fit_dipole(evoked, cov, sphere, fname_fwd) assert isinstance(residual, Evoked) # Sanity check: do our residuals have less power than orig data? data_rms = np.sqrt(np.sum(evoked.data**2, axis=0)) resi_rms = np.sqrt(np.sum(residual.data**2, axis=0)) assert (data_rms > resi_rms * 0.95).all(), \ '%s (factor: %s)' % ((data_rms / resi_rms).min(), 0.95) # Compare to original points transform_surface_to(fwd['src'][0], 'head', fwd['mri_head_t']) transform_surface_to(fwd['src'][1], 'head', fwd['mri_head_t']) assert fwd['src'][0]['coord_frame'] == FIFF.FIFFV_COORD_HEAD src_rr = np.concatenate([s['rr'][v] for s, v in zip(fwd['src'], vertices)], axis=0) src_nn = np.concatenate([s['nn'][v] for s, v in zip(fwd['src'], vertices)], axis=0) # MNE-C skips the last "time" point :( out = dip.crop(dip_c.times[0], dip_c.times[-1]) assert (dip is out) src_rr, src_nn = src_rr[:-1], src_nn[:-1] # check that we did about as well corrs, dists, gc_dists, amp_errs, gofs = [], [], [], [], [] for d in (dip_c, dip): new = d.pos diffs = new - src_rr corrs += [np.corrcoef(src_rr.ravel(), new.ravel())[0, 1]] dists += [np.sqrt(np.mean(np.sum(diffs * diffs, axis=1)))] gc_dists += [ 180 / np.pi * np.mean(np.arccos(np.sum(src_nn * d.ori, axis=1))) ] amp_errs += [np.sqrt(np.mean((amp - d.amplitude)**2))] gofs += [np.mean(d.gof)] # XXX possibly some OpenBLAS numerical differences make # things slightly worse for us factor = 0.7 assert dists[0] / factor >= dists[1], 'dists: %s' % dists assert corrs[0] * factor <= corrs[1], 'corrs: %s' % corrs assert gc_dists[0] / factor >= gc_dists[1] * 0.8, \ 'gc-dists (ori): %s' % gc_dists assert amp_errs[0] / factor >= amp_errs[1],\ 'amplitude errors: %s' % amp_errs # This one is weird because our cov/sim/picking is weird assert gofs[0] * factor <= gofs[1] * 2, 'gof: %s' % gofs
def test_plot_alignment_basic(tmp_path, renderer, mixed_fwd_cov_evoked): """Test plotting of -trans.fif files and MEG sensor layouts.""" # generate fiducials file for testing tempdir = str(tmp_path) fiducials_path = op.join(tempdir, 'fiducials.fif') fid = [{ 'coord_frame': 5, 'ident': 1, 'kind': 1, 'r': [-0.08061612, -0.02908875, -0.04131077] }, { 'coord_frame': 5, 'ident': 2, 'kind': 1, 'r': [0.00146763, 0.08506715, -0.03483611] }, { 'coord_frame': 5, 'ident': 3, 'kind': 1, 'r': [0.08436285, -0.02850276, -0.04127743] }] write_dig(fiducials_path, fid, 5) evoked = read_evokeds(evoked_fname)[0] info = evoked.info sample_src = read_source_spaces(src_fname) pytest.raises(TypeError, plot_alignment, 'foo', trans_fname, subject='sample', subjects_dir=subjects_dir) pytest.raises(OSError, plot_alignment, info, trans_fname, subject='sample', subjects_dir=subjects_dir, src='foo') pytest.raises(ValueError, plot_alignment, info, trans_fname, subject='fsaverage', subjects_dir=subjects_dir, src=sample_src) sample_src.plot(subjects_dir=subjects_dir, head=True, skull=True, brain='white') # mixed source space mixed_src = mixed_fwd_cov_evoked[0]['src'] assert mixed_src.kind == 'mixed' fig = plot_alignment(info, meg=['helmet', 'sensors'], dig=True, coord_frame='head', trans=Path(trans_fname), subject='sample', mri_fiducials=fiducials_path, subjects_dir=subjects_dir, src=mixed_src) assert isinstance(fig, Figure3D) renderer.backend._close_all() # no-head version renderer.backend._close_all() # trans required with pytest.raises(ValueError, match='transformation matrix.*in head'): plot_alignment(info, trans=None, src=src_fname) with pytest.raises(ValueError, match='transformation matrix.*in head'): plot_alignment(info, trans=None, mri_fiducials=True) with pytest.raises(ValueError, match='transformation matrix.*in head'): plot_alignment(info, trans=None, surfaces=['brain']) assert mixed_src[0]['coord_frame'] == FIFF.FIFFV_COORD_HEAD with pytest.raises(ValueError, match='head-coordinate source space in mr'): plot_alignment(trans=None, src=mixed_src, coord_frame='mri') # all coord frames plot_alignment(info) # works: surfaces='auto' default for coord_frame in ('meg', 'head', 'mri'): plot_alignment(info, meg=['helmet', 'sensors'], dig=True, coord_frame=coord_frame, trans=Path(trans_fname), subject='sample', src=src_fname, mri_fiducials=fiducials_path, subjects_dir=subjects_dir) renderer.backend._close_all() # EEG only with strange options evoked_eeg_ecog_seeg = evoked.copy().pick_types(meg=False, eeg=True) with evoked_eeg_ecog_seeg.info._unlock(): evoked_eeg_ecog_seeg.info['projs'] = [] # "remove" avg proj evoked_eeg_ecog_seeg.set_channel_types({ 'EEG 001': 'ecog', 'EEG 002': 'seeg' }) with catch_logging() as log: plot_alignment(evoked_eeg_ecog_seeg.info, subject='sample', trans=trans_fname, subjects_dir=subjects_dir, surfaces=['white', 'outer_skin', 'outer_skull'], meg=['helmet', 'sensors'], eeg=['original', 'projected'], ecog=True, seeg=True, verbose=True) log = log.getvalue() assert 'ecog: 1' in log assert 'seeg: 1' in log renderer.backend._close_all() sphere = make_sphere_model(info=info, r0='auto', head_radius='auto') bem_sol = read_bem_solution( op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem-sol.fif')) bem_surfs = read_bem_surfaces( op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem.fif')) sample_src[0]['coord_frame'] = 4 # hack for coverage plot_alignment( info, trans_fname, subject='sample', eeg='projected', meg='helmet', bem=sphere, dig=True, surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin']) plot_alignment(info, trans_fname, subject='sample', meg='helmet', subjects_dir=subjects_dir, eeg='projected', bem=sphere, surfaces=['head', 'brain'], src=sample_src) # no trans okay, no mri surfaces plot_alignment(info, bem=sphere, surfaces=['brain']) with pytest.raises(ValueError, match='A head surface is required'): plot_alignment(info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, eeg='projected', surfaces=[]) with pytest.raises(RuntimeError, match='No brain surface found'): plot_alignment(info, trans=trans_fname, subject='foo', subjects_dir=subjects_dir, surfaces=['brain']) assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI for surf in bem_sol['surfs']) plot_alignment(info, trans_fname, subject='sample', meg=[], subjects_dir=subjects_dir, bem=bem_sol, eeg=True, surfaces=['head', 'inflated', 'outer_skull', 'inner_skull']) assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI for surf in bem_sol['surfs']) plot_alignment(info, trans_fname, subject='sample', meg=True, subjects_dir=subjects_dir, surfaces=['head', 'inner_skull'], bem=bem_surfs) # single-layer BEM can still plot head surface assert bem_surfs[-1]['id'] == FIFF.FIFFV_BEM_SURF_ID_BRAIN bem_sol_homog = read_bem_solution( op.join(subjects_dir, 'sample', 'bem', 'sample-1280-bem-sol.fif')) for use_bem in (bem_surfs[-1:], bem_sol_homog): with catch_logging() as log: plot_alignment(info, trans_fname, subject='sample', meg=True, subjects_dir=subjects_dir, surfaces=['head', 'inner_skull'], bem=use_bem, verbose=True) log = log.getvalue() assert 'not find the surface for head in the provided BEM model' in log # sphere model sphere = make_sphere_model('auto', 'auto', info) src = setup_volume_source_space(sphere=sphere) plot_alignment( info, trans=Transform('head', 'mri'), eeg='projected', meg='helmet', bem=sphere, src=src, dig=True, surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin']) sphere = make_sphere_model('auto', None, info) # one layer # if you ask for a brain surface with a 1-layer sphere model it's an error with pytest.raises(RuntimeError, match='Sphere model does not have'): plot_alignment(trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['brain'], bem=sphere) # but you can ask for a specific brain surface, and # no info is permitted plot_alignment(trans=trans_fname, subject='sample', meg=False, coord_frame='mri', subjects_dir=subjects_dir, surfaces=['white'], bem=sphere, show_axes=True) renderer.backend._close_all() # TODO: We need to make this class public and document it properly # assert isinstance(fig, some_public_class) # 3D coil with no defined draw (ConvexHull) info_cube = pick_info(info, np.arange(6)) with info._unlock(): info['dig'] = None info_cube['chs'][0]['coil_type'] = 9999 info_cube['chs'][1]['coil_type'] = 9998 with pytest.raises(RuntimeError, match='coil definition not found'): plot_alignment(info_cube, meg='sensors', surfaces=()) coil_def_fname = op.join(tempdir, 'temp') with open(coil_def_fname, 'w') as fid: fid.write(coil_3d) # make sure our other OPMs can be plotted, too for ii, kind in enumerate( ('QUSPIN_ZFOPM_MAG', 'QUSPIN_ZFOPM_MAG2', 'FIELDLINE_OPM_MAG_GEN1', 'KERNEL_OPM_MAG_GEN1'), 2): info_cube['chs'][ii]['coil_type'] = getattr(FIFF, f'FIFFV_COIL_{kind}') with use_coil_def(coil_def_fname): with catch_logging() as log: plot_alignment(info_cube, meg='sensors', surfaces=(), dig=True, verbose='debug') log = log.getvalue() assert 'planar geometry' in log # one layer bem with skull surfaces: with pytest.raises(RuntimeError, match='Sphere model does not.*boundary'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['brain', 'head', 'inner_skull'], bem=sphere) # wrong eeg value: with pytest.raises(ValueError, match='Invalid value for the .eeg'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, eeg='foo') # wrong meg value: with pytest.raises(ValueError, match='Invalid value for the .meg'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, meg='bar') # multiple brain surfaces: with pytest.raises(ValueError, match='Only one brain surface can be plot'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['white', 'pial']) with pytest.raises(TypeError, match='surfaces.*must be'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=[1]) with pytest.raises(ValueError, match='Unknown surface type'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['foo']) with pytest.raises(TypeError, match="must be an instance of "): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=dict(brain='super clear')) with pytest.raises(ValueError, match="must be between 0 and 1"): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=dict(brain=42)) fwd_fname = op.join(data_dir, 'MEG', 'sample', 'sample_audvis_trunc-meg-eeg-oct-4-fwd.fif') fwd = read_forward_solution(fwd_fname) plot_alignment(subject='sample', subjects_dir=subjects_dir, trans=trans_fname, fwd=fwd, surfaces='white', coord_frame='head') fwd = convert_forward_solution(fwd, force_fixed=True) plot_alignment(subject='sample', subjects_dir=subjects_dir, trans=trans_fname, fwd=fwd, surfaces='white', coord_frame='head') fwd['coord_frame'] = FIFF.FIFFV_COORD_MRI # check required to get to MRI with pytest.raises(ValueError, match='transformation matrix.*in head coo'): plot_alignment(info, trans=None, fwd=fwd) # surfaces as dict plot_alignment(subject='sample', coord_frame='head', trans=trans_fname, subjects_dir=subjects_dir, surfaces={ 'white': 0.4, 'outer_skull': 0.6, 'head': None })
def test_plot_alignment(tmpdir, renderer): """Test plotting of -trans.fif files and MEG sensor layouts.""" # generate fiducials file for testing tempdir = str(tmpdir) fiducials_path = op.join(tempdir, 'fiducials.fif') fid = [{ 'coord_frame': 5, 'ident': 1, 'kind': 1, 'r': [-0.08061612, -0.02908875, -0.04131077] }, { 'coord_frame': 5, 'ident': 2, 'kind': 1, 'r': [0.00146763, 0.08506715, -0.03483611] }, { 'coord_frame': 5, 'ident': 3, 'kind': 1, 'r': [0.08436285, -0.02850276, -0.04127743] }] write_dig(fiducials_path, fid, 5) renderer.backend._close_all() evoked = read_evokeds(evoked_fname)[0] sample_src = read_source_spaces(src_fname) bti = read_raw_bti(pdf_fname, config_fname, hs_fname, convert=True, preload=False).info infos = dict( Neuromag=evoked.info, CTF=read_raw_ctf(ctf_fname).info, BTi=bti, KIT=read_raw_kit(sqd_fname).info, ) for system, info in infos.items(): meg = ['helmet', 'sensors'] if system == 'KIT': meg.append('ref') fig = plot_alignment(info, read_trans(trans_fname), subject='sample', subjects_dir=subjects_dir, meg=meg) rend = renderer.backend._Renderer(fig=fig) rend.close() # KIT ref sensor coil def is defined renderer.backend._close_all() info = infos['Neuromag'] pytest.raises(TypeError, plot_alignment, 'foo', trans_fname, subject='sample', subjects_dir=subjects_dir) pytest.raises(OSError, plot_alignment, info, trans_fname, subject='sample', subjects_dir=subjects_dir, src='foo') pytest.raises(ValueError, plot_alignment, info, trans_fname, subject='fsaverage', subjects_dir=subjects_dir, src=sample_src) sample_src.plot(subjects_dir=subjects_dir, head=True, skull=True, brain='white') renderer.backend._close_all() # no-head version renderer.backend._close_all() # all coord frames plot_alignment(info) # works: surfaces='auto' default for coord_frame in ('meg', 'head', 'mri'): fig = plot_alignment(info, meg=['helmet', 'sensors'], dig=True, coord_frame=coord_frame, trans=Path(trans_fname), subject='sample', mri_fiducials=fiducials_path, subjects_dir=subjects_dir, src=src_fname) renderer.backend._close_all() # EEG only with strange options evoked_eeg_ecog_seeg = evoked.copy().pick_types(meg=False, eeg=True) evoked_eeg_ecog_seeg.info['projs'] = [] # "remove" avg proj evoked_eeg_ecog_seeg.set_channel_types({ 'EEG 001': 'ecog', 'EEG 002': 'seeg' }) with pytest.warns(RuntimeWarning, match='Cannot plot MEG'): plot_alignment(evoked_eeg_ecog_seeg.info, subject='sample', trans=trans_fname, subjects_dir=subjects_dir, surfaces=['white', 'outer_skin', 'outer_skull'], meg=['helmet', 'sensors'], eeg=['original', 'projected'], ecog=True, seeg=True) renderer.backend._close_all() sphere = make_sphere_model(info=evoked.info, r0='auto', head_radius='auto') bem_sol = read_bem_solution( op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem-sol.fif')) bem_surfs = read_bem_surfaces( op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem.fif')) sample_src[0]['coord_frame'] = 4 # hack for coverage plot_alignment( info, subject='sample', eeg='projected', meg='helmet', bem=sphere, dig=True, surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin']) plot_alignment(info, trans_fname, subject='sample', meg='helmet', subjects_dir=subjects_dir, eeg='projected', bem=sphere, surfaces=['head', 'brain'], src=sample_src) assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI for surf in bem_sol['surfs']) plot_alignment(info, trans_fname, subject='sample', meg=[], subjects_dir=subjects_dir, bem=bem_sol, eeg=True, surfaces=['head', 'inflated', 'outer_skull', 'inner_skull']) assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI for surf in bem_sol['surfs']) plot_alignment(info, trans_fname, subject='sample', meg=True, subjects_dir=subjects_dir, surfaces=['head', 'inner_skull'], bem=bem_surfs) # single-layer BEM can still plot head surface assert bem_surfs[-1]['id'] == FIFF.FIFFV_BEM_SURF_ID_BRAIN bem_sol_homog = read_bem_solution( op.join(subjects_dir, 'sample', 'bem', 'sample-1280-bem-sol.fif')) for use_bem in (bem_surfs[-1:], bem_sol_homog): with catch_logging() as log: plot_alignment(info, trans_fname, subject='sample', meg=True, subjects_dir=subjects_dir, surfaces=['head', 'inner_skull'], bem=use_bem, verbose=True) log = log.getvalue() assert 'not find the surface for head in the provided BEM model' in log # sphere model sphere = make_sphere_model('auto', 'auto', evoked.info) src = setup_volume_source_space(sphere=sphere) plot_alignment( info, eeg='projected', meg='helmet', bem=sphere, src=src, dig=True, surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin']) sphere = make_sphere_model('auto', None, evoked.info) # one layer # no info is permitted fig = plot_alignment(trans=trans_fname, subject='sample', meg=False, coord_frame='mri', subjects_dir=subjects_dir, surfaces=['brain'], bem=sphere, show_axes=True) renderer.backend._close_all() if renderer._get_3d_backend() == 'mayavi': import mayavi # noqa: F401 analysis:ignore assert isinstance(fig, mayavi.core.scene.Scene) # 3D coil with no defined draw (ConvexHull) info_cube = pick_info(info, [0]) info['dig'] = None info_cube['chs'][0]['coil_type'] = 9999 with pytest.raises(RuntimeError, match='coil definition not found'): plot_alignment(info_cube, meg='sensors', surfaces=()) coil_def_fname = op.join(tempdir, 'temp') with open(coil_def_fname, 'w') as fid: fid.write(coil_3d) with use_coil_def(coil_def_fname): plot_alignment(info_cube, meg='sensors', surfaces=(), dig=True) # one layer bem with skull surfaces: with pytest.raises(ValueError, match='sphere conductor model must have'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['brain', 'head', 'inner_skull'], bem=sphere) # wrong eeg value: with pytest.raises(ValueError, match='Invalid value for the .eeg'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, eeg='foo') # wrong meg value: with pytest.raises(ValueError, match='Invalid value for the .meg'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, meg='bar') # multiple brain surfaces: with pytest.raises(ValueError, match='Only one brain surface can be plot'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['white', 'pial']) with pytest.raises(TypeError, match='all entries in surfaces must be'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=[1]) with pytest.raises(ValueError, match='Unknown surface type'): plot_alignment(info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['foo']) fwd_fname = op.join(data_dir, 'MEG', 'sample', 'sample_audvis_trunc-meg-eeg-oct-4-fwd.fif') fwd = read_forward_solution(fwd_fname) plot_alignment(subject='sample', subjects_dir=subjects_dir, trans=trans_fname, fwd=fwd, surfaces='white', coord_frame='head') fwd = convert_forward_solution(fwd, force_fixed=True) plot_alignment(subject='sample', subjects_dir=subjects_dir, trans=trans_fname, fwd=fwd, surfaces='white', coord_frame='head') # fNIRS info = read_raw_nirx(nirx_fname).info with catch_logging() as log: plot_alignment(info, subject='fsaverage', surfaces=(), verbose=True) log = log.getvalue() assert '26 fnirs pairs' in log with catch_logging() as log: plot_alignment(info, subject='fsaverage', surfaces=(), verbose=True, fnirs='channels') log = log.getvalue() assert '26 fnirs locations' in log with catch_logging() as log: plot_alignment(info, subject='fsaverage', surfaces=(), verbose=True, fnirs='pairs') log = log.getvalue() assert '26 fnirs pairs' in log with catch_logging() as log: plot_alignment(info, subject='fsaverage', surfaces=(), verbose=True, fnirs='sources') log = log.getvalue() assert '26 fnirs sources' in log with catch_logging() as log: plot_alignment(info, subject='fsaverage', surfaces=(), verbose=True, fnirs='detectors') log = log.getvalue() assert '26 fnirs detectors' in log with catch_logging() as log: plot_alignment(info, subject='fsaverage', surfaces=(), verbose=True, fnirs=['channels', 'pairs']) log = log.getvalue() assert '26 fnirs pairs' in log assert '26 fnirs locations' in log with catch_logging() as log: plot_alignment(info, subject='fsaverage', surfaces=(), verbose=True, fnirs=['pairs', 'sources', 'detectors']) log = log.getvalue() assert '26 fnirs pairs' in log assert '26 fnirs sources' in log assert '26 fnirs detectors' in log with catch_logging() as log: plot_alignment(info, subject='fsaverage', surfaces=(), verbose=True, fnirs=['channels', 'pairs', 'sources', 'detectors']) log = log.getvalue() assert '26 fnirs pairs' in log assert '26 fnirs locations' in log assert '26 fnirs sources' in log assert '26 fnirs detectors' in log renderer.backend._close_all()
def test_make_forward_solution_sphere(tmpdir): """Test making a forward solution with a sphere model.""" fname_src_small = tmpdir.join('sample-oct-2-src.fif') src = setup_source_space('sample', 'oct2', subjects_dir=subjects_dir, add_dist=False) write_source_spaces(fname_src_small, src) # to enable working with MNE-C out_name = tmpdir.join('tmp-fwd.fif') run_subprocess([ 'mne_forward_solution', '--meg', '--eeg', '--meas', fname_raw, '--src', fname_src_small, '--mri', fname_trans, '--fwd', out_name ]) fwd = read_forward_solution(out_name) sphere = make_sphere_model(verbose=True) fwd_py = make_forward_solution(fname_raw, fname_trans, src, sphere, meg=True, eeg=True, verbose=True) _compare_forwards(fwd, fwd_py, 366, 108, meg_rtol=5e-1, meg_atol=1e-6, eeg_rtol=5e-1, eeg_atol=5e-1) # Since the above is pretty lax, let's check a different way for meg, eeg in zip([True, False], [False, True]): fwd_ = pick_types_forward(fwd, meg=meg, eeg=eeg) fwd_py_ = pick_types_forward(fwd, meg=meg, eeg=eeg) assert_allclose(np.corrcoef(fwd_['sol']['data'].ravel(), fwd_py_['sol']['data'].ravel())[0, 1], 1.0, rtol=1e-3) # Number of layers in the sphere model doesn't matter for MEG # (as long as no sources are omitted due to distance) assert len(sphere['layers']) == 4 fwd = make_forward_solution(fname_raw, fname_trans, src, sphere, meg=True, eeg=False) sphere_1 = make_sphere_model(head_radius=None) assert len(sphere_1['layers']) == 0 assert_array_equal(sphere['r0'], sphere_1['r0']) fwd_1 = make_forward_solution(fname_raw, fname_trans, src, sphere, meg=True, eeg=False) _compare_forwards(fwd, fwd_1, 306, 108, meg_rtol=1e-12, meg_atol=1e-12) # Homogeneous model sphere = make_sphere_model(head_radius=None) with pytest.raises(RuntimeError, match='zero shells.*EEG'): make_forward_solution(fname_raw, fname_trans, src, sphere)
def get_data(base_path, dipole_idx, dipole_amplitude, use_maxwell_filter, bads=[], show=False): if "phantom_aston" in base_path: if use_maxwell_filter is True: data_path = base_path + '/tSSS Data' # data_path += '/Amp%d_IASoff_movement/' % dipole_amplitude data_path = data_path + '/Amp%d_IASoff_tSSS/' % dipole_amplitude fname = 'Amp%d_Dip%d_IASoff_tsss.fif' % (dipole_amplitude, dipole_idx) else: data_path = base_path + '/Raw Data' data_path = data_path + '/Amp%d_IASoff/' % dipole_amplitude fname = 'Amp%d_Dip%d_IASoff.fif' % (dipole_amplitude, dipole_idx) stim_channel = 'SYS201' else: data_path = base_path + '/%dnAm/' % dipole_amplitude if use_maxwell_filter is True: fname = 'dip%02d_%dnAm_sss.fif' % (dipole_idx, dipole_amplitude) else: fname = 'dip%02d_%dnAm.fif' % (dipole_idx, dipole_amplitude) stim_channel = 'STI201' raw_fname = op.join(data_path, fname) raw = mne.io.read_raw_fif(raw_fname, preload=True, verbose='error') if use_maxwell_filter is not True: # ie 'mne' or False raw.info['bads'] = bads if "phantom_aston" in base_path: raw.crop(20, None) events = mne.find_events(raw, stim_channel=stim_channel) if show: raw.plot(events=events) if show: raw.plot_psd(tmax=np.inf, fmax=60, average=False) raw.fix_mag_coil_types() if use_maxwell_filter == 'mne': # Use Maxwell filtering from MNE raw = mne.preprocessing.maxwell_filter(raw, origin=(0., 0., 0.)) if show: raw.plot(events=events) ####################################################################### # We know our phantom produces sinusoidal bursts below 25 Hz, so let's # filter. raw.filter(None, 40., h_trans_bandwidth='auto', filter_length='auto', phase='zero') if show: raw.plot(events=events) ####################################################################### # Now we epoch our data, average it tmin, tmax = -0.5, 0.5 event_id = events[0, 2] # reject = dict(grad=4000e-13, mag=4e-12) reject = None epochs = mne.Epochs(raw, events, event_id, tmin, tmax, baseline=(None, -0.05), preload=True, reject=reject) evoked = epochs.average() if show: evoked.plot(spatial_colors=True) if show: evoked.plot_joint() evoked.crop(0, None) sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.08) cov = mne.compute_covariance(epochs, tmax=-0.05) print(fname + " nave=%d" % evoked.nave, end='') return epochs, evoked, cov, sphere
def test_simulate_calculate_chpi_positions(): """Test calculation of cHPI positions with simulated data.""" # Read info dict from raw FIF file info = read_info(raw_fname) # Tune the info structure chpi_channel = u'STI201' ncoil = len(info['hpi_results'][0]['order']) coil_freq = 10 + np.arange(ncoil) * 5 hpi_subsystem = { 'event_channel': chpi_channel, 'hpi_coils': [{ 'event_bits': np.array([256, 0, 256, 256], dtype=np.int32) }, { 'event_bits': np.array([512, 0, 512, 512], dtype=np.int32) }, { 'event_bits': np.array([1024, 0, 1024, 1024], dtype=np.int32) }, { 'event_bits': np.array([2048, 0, 2048, 2048], dtype=np.int32) }], 'ncoil': ncoil } info['hpi_subsystem'] = hpi_subsystem for l, freq in enumerate(coil_freq): info['hpi_meas'][0]['hpi_coils'][l]['coil_freq'] = freq picks = pick_types(info, meg=True, stim=True, eeg=False, exclude=[]) info['sfreq'] = 100. # this will speed it up a lot info = pick_info(info, picks) info['chs'][info['ch_names'].index('STI 001')]['ch_name'] = 'STI201' info._update_redundant() info['projs'] = [] info_trans = info['dev_head_t']['trans'].copy() dev_head_pos_ini = np.concatenate( [rot_to_quat(info_trans[:3, :3]), info_trans[:3, 3]]) ez = np.array([0, 0, 1]) # Unit vector in z-direction of head coordinates # Define some constants duration = 30 # Time / s # Quotient of head position sampling frequency # and raw sampling frequency head_pos_sfreq_quotient = 0.1 # Round number of head positions to the next integer S = int(duration / (info['sfreq'] * head_pos_sfreq_quotient)) dz = 0.001 # Shift in z-direction is 0.1mm for each step dev_head_pos = np.zeros((S, 10)) dev_head_pos[:, 0] = np.arange(S) * info['sfreq'] * head_pos_sfreq_quotient dev_head_pos[:, 1:4] = dev_head_pos_ini[:3] dev_head_pos[:, 4:7] = dev_head_pos_ini[3:] + \ np.outer(np.arange(S) * dz, ez) dev_head_pos[:, 7] = 1.0 # cm/s dev_head_pos[:, 9] = 100 * dz / (info['sfreq'] * head_pos_sfreq_quotient) # Round number of samples to the next integer raw_data = np.zeros((len(picks), int(duration * info['sfreq'] + 0.5))) raw = RawArray(raw_data, info) dip = Dipole(np.array([0.0, 0.1, 0.2]), np.array([[0.0, 0.0, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]]), np.array([1e-9, 1e-9, 1e-9]), np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]), np.array([1.0, 1.0, 1.0]), 'dip') sphere = make_sphere_model('auto', 'auto', info=info, relative_radii=(1.0, 0.9), sigmas=(0.33, 0.3)) fwd, stc = make_forward_dipole(dip, sphere, info) stc.resample(info['sfreq']) raw = simulate_raw(raw, stc, None, fwd['src'], sphere, cov=None, blink=False, ecg=False, chpi=True, head_pos=dev_head_pos, mindist=1.0, interp='zero', verbose=None, use_cps=True) quats = _calculate_chpi_positions( raw, t_step_min=raw.info['sfreq'] * head_pos_sfreq_quotient, t_step_max=raw.info['sfreq'] * head_pos_sfreq_quotient, t_window=1.0) _assert_quats(quats, dev_head_pos, dist_tol=0.001, angle_tol=1.)
# make room for title fig.subplots_adjust(top=0.9) fig.suptitle('{} reference'.format(title), size='xx-large', weight='bold') ############################################################################### # Using an infinite reference (REST) # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # # To use the "point at infinity" reference technique described in # :footcite:`Yao2001` requires a forward model, which we can create in a few # steps. Here we use a fairly large spacing of vertices (``pos`` = 15 mm) to # reduce computation time; a 5 mm spacing is more typical for real data # analysis: raw.del_proj() # remove our average reference projector first sphere = mne.make_sphere_model('auto', 'auto', raw.info) src = mne.setup_volume_source_space(sphere=sphere, exclude=30., pos=15.) forward = mne.make_forward_solution(raw.info, trans=None, src=src, bem=sphere) raw_rest = raw.copy().set_eeg_reference('REST', forward=forward) for title, _raw in zip(['Original', 'REST (∞)'], [raw, raw_rest]): fig = _raw.plot(n_channels=len(raw), scalings=dict(eeg=5e-5)) # make room for title fig.subplots_adjust(top=0.9) fig.suptitle('{} reference'.format(title), size='xx-large', weight='bold') ############################################################################### # EEG reference and source modeling # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # # If you plan to perform source modeling (either with EEG or combined EEG/MEG
def test_mxne_vol_sphere(): """Test (TF-)MxNE with a sphere forward and volumic source space.""" evoked = read_evokeds(fname_data, condition=0, baseline=(None, 0)) evoked.crop(tmin=-0.05, tmax=0.2) cov = read_cov(fname_cov) evoked_l21 = evoked.copy() evoked_l21.crop(tmin=0.081, tmax=0.1) info = evoked.info sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080) src = mne.setup_volume_source_space(subject=None, pos=15., mri=None, sphere=(0.0, 0.0, 0.0, 0.08), bem=None, mindist=5.0, exclude=2.0, sphere_units='m') fwd = mne.make_forward_solution(info, trans=None, src=src, bem=sphere, eeg=False, meg=True) alpha = 80. pytest.raises(ValueError, mixed_norm, evoked, fwd, cov, alpha, loose=0.0, return_residual=False, maxit=3, tol=1e-8, active_set_size=10) pytest.raises(ValueError, mixed_norm, evoked, fwd, cov, alpha, loose=0.2, return_residual=False, maxit=3, tol=1e-8, active_set_size=10) # irMxNE tests with catch_logging() as log: stc = mixed_norm(evoked_l21, fwd, cov, alpha, n_mxne_iter=1, maxit=30, tol=1e-8, active_set_size=10, verbose=True) assert isinstance(stc, VolSourceEstimate) assert_array_almost_equal(stc.times, evoked_l21.times, 5) assert_var_exp_log(log.getvalue(), 9, 11) # 10.2 # Compare orientation obtained using fit_dipole and gamma_map # for a simulated evoked containing a single dipole stc = mne.VolSourceEstimate(50e-9 * np.random.RandomState(42).randn(1, 4), vertices=[stc.vertices[0][:1]], tmin=stc.tmin, tstep=stc.tstep) evoked_dip = mne.simulation.simulate_evoked(fwd, stc, info, cov, nave=1e9, use_cps=True) dip_mxne = mixed_norm(evoked_dip, fwd, cov, alpha=80, n_mxne_iter=1, maxit=30, tol=1e-8, active_set_size=10, return_as_dipoles=True) amp_max = [np.max(d.amplitude) for d in dip_mxne] dip_mxne = dip_mxne[np.argmax(amp_max)] assert dip_mxne.pos[0] in src[0]['rr'][stc.vertices[0]] dip_fit = mne.fit_dipole(evoked_dip, cov, sphere)[0] assert np.abs(np.dot(dip_fit.ori[0], dip_mxne.ori[0])) > 0.99 dist = 1000 * np.linalg.norm(dip_fit.pos[0] - dip_mxne.pos[0]) assert dist < 4. # within 4 mm # Do with TF-MxNE for test memory savings alpha = 60. # overall regularization parameter l1_ratio = 0.01 # temporal regularization proportion stc, _ = tf_mixed_norm(evoked, fwd, cov, maxit=3, tol=1e-4, tstep=16, wsize=32, window=0.1, alpha=alpha, l1_ratio=l1_ratio, return_residual=True) assert isinstance(stc, VolSourceEstimate) assert_array_almost_equal(stc.times, evoked.times, 5)
def test_make_lcmv(tmpdir, reg, proj): """Test LCMV with evoked data and single trials.""" raw, epochs, evoked, data_cov, noise_cov, label, forward,\ forward_surf_ori, forward_fixed, forward_vol = _get_data(proj=proj) for fwd in [forward, forward_vol]: filters = make_lcmv(evoked.info, fwd, data_cov, reg=reg, noise_cov=noise_cov) stc = apply_lcmv(evoked, filters, max_ori_out='signed') stc.crop(0.02, None) stc_pow = np.sum(np.abs(stc.data), axis=1) idx = np.argmax(stc_pow) max_stc = stc.data[idx] tmax = stc.times[np.argmax(max_stc)] assert 0.09 < tmax < 0.12, tmax assert 0.9 < np.max(max_stc) < 3., np.max(max_stc) if fwd is forward: # Test picking normal orientation (surface source space only). filters = make_lcmv(evoked.info, forward_surf_ori, data_cov, reg=reg, noise_cov=noise_cov, pick_ori='normal', weight_norm=None) stc_normal = apply_lcmv(evoked, filters, max_ori_out='signed') stc_normal.crop(0.02, None) stc_pow = np.sum(np.abs(stc_normal.data), axis=1) idx = np.argmax(stc_pow) max_stc = stc_normal.data[idx] tmax = stc_normal.times[np.argmax(max_stc)] lower = 0.04 if proj else 0.025 assert lower < tmax < 0.13, tmax lower = 3e-7 if proj else 2e-7 assert lower < np.max(max_stc) < 5e-7, np.max(max_stc) # No weight normalization was applied, so the amplitude of normal # orientation results should always be smaller than free # orientation results. assert (np.abs(stc_normal.data) <= stc.data).all() # Test picking source orientation maximizing output source power filters = make_lcmv(evoked.info, fwd, data_cov, reg=reg, noise_cov=noise_cov, pick_ori='max-power') stc_max_power = apply_lcmv(evoked, filters, max_ori_out='signed') stc_max_power.crop(0.02, None) stc_pow = np.sum(np.abs(stc_max_power.data), axis=1) idx = np.argmax(stc_pow) max_stc = np.abs(stc_max_power.data[idx]) tmax = stc.times[np.argmax(max_stc)] lower = 0.08 if proj else 0.04 assert lower < tmax < 0.12, tmax assert 0.8 < np.max(max_stc) < 3., np.max(max_stc) stc_max_power.data[:, :] = np.abs(stc_max_power.data) if fwd is forward: # Maximum output source power orientation results should be # similar to free orientation results in areas with channel # coverage label = mne.read_label(fname_label) mean_stc = stc.extract_label_time_course(label, fwd['src'], mode='mean') mean_stc_max_pow = \ stc_max_power.extract_label_time_course(label, fwd['src'], mode='mean') assert_array_less(np.abs(mean_stc - mean_stc_max_pow), 0.6) # Test NAI weight normalization: filters = make_lcmv(evoked.info, fwd, data_cov, reg=reg, noise_cov=noise_cov, pick_ori='max-power', weight_norm='nai') stc_nai = apply_lcmv(evoked, filters, max_ori_out='signed') stc_nai.crop(0.02, None) # Test whether unit-noise-gain solution is a scaled version of NAI pearsoncorr = np.corrcoef(np.concatenate(np.abs(stc_nai.data)), np.concatenate(stc_max_power.data)) assert_almost_equal(pearsoncorr[0, 1], 1.) # Test sphere head model with unit-noise gain beamformer and orientation # selection and rank reduction of the leadfield sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080) src = mne.setup_volume_source_space(subject=None, pos=15., mri=None, sphere=(0.0, 0.0, 0.0, 80.0), bem=None, mindist=5.0, exclude=2.0) fwd_sphere = mne.make_forward_solution(evoked.info, trans=None, src=src, bem=sphere, eeg=False, meg=True) # Test that we get an error if not reducing rank with pytest.raises(ValueError): # Singular matrix or complex spectrum make_lcmv( evoked.info, fwd_sphere, data_cov, reg=0.1, noise_cov=noise_cov, weight_norm='unit-noise-gain', pick_ori='max-power', reduce_rank=False, rank='full') # Now let's reduce it filters = make_lcmv(evoked.info, fwd_sphere, data_cov, reg=0.1, noise_cov=noise_cov, weight_norm='unit-noise-gain', pick_ori='max-power', reduce_rank=True) stc_sphere = apply_lcmv(evoked, filters, max_ori_out='signed') stc_sphere = np.abs(stc_sphere) stc_sphere.crop(0.02, None) stc_pow = np.sum(stc_sphere.data, axis=1) idx = np.argmax(stc_pow) max_stc = stc_sphere.data[idx] tmax = stc_sphere.times[np.argmax(max_stc)] lower = 0.08 if proj else 0.04 assert lower < tmax < 0.15, tmax assert 0.4 < np.max(max_stc) < 2., np.max(max_stc) # Test if spatial filter contains src_type assert 'src_type' in filters # __repr__ assert len(evoked.ch_names) == 22 assert len(evoked.info['projs']) == (4 if proj else 0) assert len(evoked.info['bads']) == 2 rank = 17 if proj else 20 assert 'LCMV' in repr(filters) assert 'unknown subject' not in repr(filters) assert '484' in repr(filters) assert '20' in repr(filters) assert 'rank %s' % rank in repr(filters) # I/O fname = op.join(str(tmpdir), 'filters.h5') with pytest.warns(RuntimeWarning, match='-lcmv.h5'): filters.save(fname) filters_read = read_beamformer(fname) assert isinstance(filters, Beamformer) assert isinstance(filters_read, Beamformer) # deal with object_diff strictness filters_read['rank'] = int(filters_read['rank']) filters['rank'] = int(filters['rank']) assert object_diff(filters, filters_read) == '' # Test if fixed forward operator is detected when picking normal or # max-power orientation pytest.raises(ValueError, make_lcmv, evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') pytest.raises(ValueError, make_lcmv, evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='max-power') # Test if non-surface oriented forward operator is detected when picking # normal orientation pytest.raises(ValueError, make_lcmv, evoked.info, forward, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') # Test if volume forward operator is detected when picking normal # orientation pytest.raises(ValueError, make_lcmv, evoked.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') # Test if missing of noise covariance matrix is detected when more than # one channel type is present in the data pytest.raises(ValueError, make_lcmv, evoked.info, forward_vol, data_cov=data_cov, reg=0.01, noise_cov=None, pick_ori='max-power') # Test if wrong channel selection is detected in application of filter evoked_ch = deepcopy(evoked) evoked_ch.pick_channels(evoked_ch.ch_names[1:]) filters = make_lcmv(evoked.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov) pytest.raises(ValueError, apply_lcmv, evoked_ch, filters, max_ori_out='signed') # Test if discrepancies in channel selection of data and fwd model are # handled correctly in apply_lcmv # make filter with data where first channel was removed filters = make_lcmv(evoked_ch.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov) # applying that filter to the full data set should automatically exclude # this channel from the data # also test here that no warnings are thrown - implemented to check whether # src should not be None warning occurs with pytest.warns(None) as w: stc = apply_lcmv(evoked, filters, max_ori_out='signed') assert len(w) == 0 # the result should be equal to applying this filter to a dataset without # this channel: stc_ch = apply_lcmv(evoked_ch, filters, max_ori_out='signed') assert_array_almost_equal(stc.data, stc_ch.data) # Test if non-matching SSP projection is detected in application of filter if proj: raw_proj = deepcopy(raw) raw_proj.del_proj() with pytest.raises(ValueError, match='do not match the projections'): apply_lcmv_raw(raw_proj, filters, max_ori_out='signed') # Test if setting reduce_rank to True returns a NotImplementedError # when no orientation selection is done or pick_ori='normal' pytest.raises(NotImplementedError, make_lcmv, evoked.info, forward_vol, data_cov, noise_cov=noise_cov, pick_ori=None, weight_norm='nai', reduce_rank=True) pytest.raises(NotImplementedError, make_lcmv, evoked.info, forward_surf_ori, data_cov, noise_cov=noise_cov, pick_ori='normal', weight_norm='nai', reduce_rank=True) # Test if spatial filter contains src_type assert 'src_type' in filters # check whether a filters object without src_type throws expected warning del filters['src_type'] # emulate 0.16 behaviour to cause warning with pytest.warns(RuntimeWarning, match='spatial filter does not contain ' 'src_type'): apply_lcmv(evoked, filters, max_ori_out='signed') # Now test single trial using fixed orientation forward solution # so we can compare it to the evoked solution filters = make_lcmv(epochs.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov) stcs = apply_lcmv_epochs(epochs, filters, max_ori_out='signed') stcs_ = apply_lcmv_epochs(epochs, filters, return_generator=True, max_ori_out='signed') assert_array_equal(stcs[0].data, next(stcs_).data) epochs.drop_bad() assert (len(epochs.events) == len(stcs)) # average the single trial estimates stc_avg = np.zeros_like(stcs[0].data) for this_stc in stcs: stc_avg += this_stc.data stc_avg /= len(stcs) # compare it to the solution using evoked with fixed orientation filters = make_lcmv(evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov) stc_fixed = apply_lcmv(evoked, filters, max_ori_out='signed') assert_array_almost_equal(stc_avg, stc_fixed.data) # use a label so we have few source vertices and delayed computation is # not used filters = make_lcmv(epochs.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, label=label) stcs_label = apply_lcmv_epochs(epochs, filters, max_ori_out='signed') assert_array_almost_equal(stcs_label[0].data, stcs[0].in_label(label).data) # Test condition where the filters weights are zero. There should not be # any divide-by-zero errors zero_cov = data_cov.copy() zero_cov['data'][:] = 0 filters = make_lcmv(epochs.info, forward_fixed, zero_cov, reg=0.01, noise_cov=noise_cov) assert_array_equal(filters['weights'], 0)
def test_lcmv(): """Test LCMV with evoked data and single trials.""" raw, epochs, evoked, data_cov, noise_cov, label, forward,\ forward_surf_ori, forward_fixed, forward_vol = _get_data() for fwd in [forward, forward_vol]: filters = make_lcmv(evoked.info, fwd, data_cov, reg=0.01, noise_cov=noise_cov) stc = apply_lcmv(evoked, filters, max_ori_out='signed') stc.crop(0.02, None) stc_pow = np.sum(np.abs(stc.data), axis=1) idx = np.argmax(stc_pow) max_stc = stc.data[idx] tmax = stc.times[np.argmax(max_stc)] assert_true(0.09 < tmax < 0.105, tmax) assert_true(0.9 < np.max(max_stc) < 3., np.max(max_stc)) if fwd is forward: # Test picking normal orientation (surface source space only) filters = make_lcmv(evoked.info, forward_surf_ori, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') stc_normal = apply_lcmv(evoked, filters, max_ori_out='signed') stc_normal.crop(0.02, None) stc_pow = np.sum(np.abs(stc_normal.data), axis=1) idx = np.argmax(stc_pow) max_stc = stc_normal.data[idx] tmax = stc_normal.times[np.argmax(max_stc)] assert_true(0.04 < tmax < 0.11, tmax) assert_true(0.4 < np.max(max_stc) < 2., np.max(max_stc)) # The amplitude of normal orientation results should always be # smaller than free orientation results assert_true((np.abs(stc_normal.data) <= stc.data).all()) # Test picking source orientation maximizing output source power filters = make_lcmv(evoked.info, fwd, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='max-power') stc_max_power = apply_lcmv(evoked, filters, max_ori_out='signed') stc_max_power.crop(0.02, None) stc_pow = np.sum(np.abs(stc_max_power.data), axis=1) idx = np.argmax(stc_pow) max_stc = np.abs(stc_max_power.data[idx]) tmax = stc.times[np.argmax(max_stc)] assert_true(0.08 < tmax < 0.11, tmax) assert_true(0.8 < np.max(max_stc) < 3., np.max(max_stc)) stc_max_power.data[:, :] = np.abs(stc_max_power.data) if fwd is forward: # Maximum output source power orientation results should be # similar to free orientation results in areas with channel # coverage label = mne.read_label(fname_label) mean_stc = stc.extract_label_time_course(label, fwd['src'], mode='mean') mean_stc_max_pow = \ stc_max_power.extract_label_time_course(label, fwd['src'], mode='mean') assert_true((np.abs(mean_stc - mean_stc_max_pow) < 0.5).all()) # Test NAI weight normalization: filters = make_lcmv(evoked.info, fwd, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='max-power', weight_norm='nai') stc_nai = apply_lcmv(evoked, filters, max_ori_out='signed') stc_nai.crop(0.02, None) # Test whether unit-noise-gain solution is a scaled version of NAI pearsoncorr = np.corrcoef(np.concatenate(np.abs(stc_nai.data)), np.concatenate(stc_max_power.data)) assert_almost_equal(pearsoncorr[0, 1], 1.) # Test sphere head model with unit-noise gain beamformer and orientation # selection and rank reduction of the leadfield sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080) src = mne.setup_volume_source_space(subject=None, pos=15., mri=None, sphere=(0.0, 0.0, 0.0, 80.0), bem=None, mindist=5.0, exclude=2.0) fwd_sphere = mne.make_forward_solution(evoked.info, trans=None, src=src, bem=sphere, eeg=False, meg=True) # Test that we get an error if not reducing rank assert_raises(ValueError, make_lcmv, evoked.info, fwd_sphere, data_cov, reg=0.1, noise_cov=noise_cov, weight_norm='unit-noise-gain', pick_ori='max-power', reduce_rank=False) # Now let's reduce it filters = make_lcmv(evoked.info, fwd_sphere, data_cov, reg=0.1, noise_cov=noise_cov, weight_norm='unit-noise-gain', pick_ori='max-power', reduce_rank=True) stc_sphere = apply_lcmv(evoked, filters, max_ori_out='signed') stc_sphere = np.abs(stc_sphere) stc_sphere.crop(0.02, None) stc_pow = np.sum(stc_sphere.data, axis=1) idx = np.argmax(stc_pow) max_stc = stc_sphere.data[idx] tmax = stc_sphere.times[np.argmax(max_stc)] assert_true(0.08 < tmax < 0.11, tmax) assert_true(0.4 < np.max(max_stc) < 2., np.max(max_stc)) # Test if fixed forward operator is detected when picking normal or # max-power orientation assert_raises(ValueError, make_lcmv, evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') assert_raises(ValueError, make_lcmv, evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='max-power') # Test if non-surface oriented forward operator is detected when picking # normal orientation assert_raises(ValueError, make_lcmv, evoked.info, forward, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') # Test if volume forward operator is detected when picking normal # orientation assert_raises(ValueError, make_lcmv, evoked.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal') # Test if missing of noise covariance matrix is detected when more than # one channel type is present in the data assert_raises(ValueError, make_lcmv, evoked.info, forward_vol, data_cov=data_cov, reg=0.01, noise_cov=None, pick_ori='max-power') # Test if not-yet-implemented orientation selections raise error with # neural activity index assert_raises(NotImplementedError, make_lcmv, evoked.info, forward_surf_ori, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='normal', weight_norm='nai') assert_raises(NotImplementedError, make_lcmv, evoked.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori=None, weight_norm='nai') # Test if no weight-normalization and max-power source orientation throws # an error assert_raises(NotImplementedError, make_lcmv, evoked.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov, pick_ori='max-power', weight_norm=None) # Test if wrong channel selection is detected in application of filter evoked_ch = deepcopy(evoked) evoked_ch.pick_channels(evoked_ch.ch_names[1:]) filters = make_lcmv(evoked.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov) assert_raises(ValueError, apply_lcmv, evoked_ch, filters, max_ori_out='signed') # Test if discrepancies in channel selection of data and fwd model are # handled correctly in apply_lcmv # make filter with data where first channel was removed filters = make_lcmv(evoked_ch.info, forward_vol, data_cov, reg=0.01, noise_cov=noise_cov) # applying that filter to the full data set should automatically exclude # this channel from the data stc = apply_lcmv(evoked, filters, max_ori_out='signed') # the result should be equal to applying this filter to a dataset without # this channel: stc_ch = apply_lcmv(evoked_ch, filters, max_ori_out='signed') assert_array_almost_equal(stc.data, stc_ch.data) # Test if non-matching SSP projection is detected in application of filter raw_proj = deepcopy(raw) raw_proj.del_proj() assert_raises(ValueError, apply_lcmv_raw, raw_proj, filters, max_ori_out='signed') # Test if setting reduce_rank to True returns a NotImplementedError # when no orientation selection is done or pick_ori='normal' assert_raises(NotImplementedError, make_lcmv, evoked.info, forward_vol, data_cov, noise_cov=noise_cov, pick_ori=None, weight_norm='nai', reduce_rank=True) assert_raises(NotImplementedError, make_lcmv, evoked.info, forward_surf_ori, data_cov, noise_cov=noise_cov, pick_ori='normal', weight_norm='nai', reduce_rank=True) # Now test single trial using fixed orientation forward solution # so we can compare it to the evoked solution filters = make_lcmv(epochs.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov) stcs = apply_lcmv_epochs(epochs, filters, max_ori_out='signed') stcs_ = apply_lcmv_epochs(epochs, filters, return_generator=True, max_ori_out='signed') assert_array_equal(stcs[0].data, advance_iterator(stcs_).data) epochs.drop_bad() assert_true(len(epochs.events) == len(stcs)) # average the single trial estimates stc_avg = np.zeros_like(stcs[0].data) for this_stc in stcs: stc_avg += this_stc.data stc_avg /= len(stcs) # compare it to the solution using evoked with fixed orientation filters = make_lcmv(evoked.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov) stc_fixed = apply_lcmv(evoked, filters, max_ori_out='signed') assert_array_almost_equal(stc_avg, stc_fixed.data) # use a label so we have few source vertices and delayed computation is # not used filters = make_lcmv(epochs.info, forward_fixed, data_cov, reg=0.01, noise_cov=noise_cov, label=label) stcs_label = apply_lcmv_epochs(epochs, filters, max_ori_out='signed') assert_array_almost_equal(stcs_label[0].data, stcs[0].in_label(label).data)
def test_dipole_fitting(): """Test dipole fitting""" amp = 10e-9 tempdir = _TempDir() rng = np.random.RandomState(0) fname_dtemp = op.join(tempdir, 'test.dip') fname_sim = op.join(tempdir, 'test-ave.fif') fwd = convert_forward_solution(read_forward_solution(fname_fwd), surf_ori=False, force_fixed=True) evoked = read_evokeds(fname_evo)[0] cov = read_cov(fname_cov) n_per_hemi = 5 vertices = [ np.sort(rng.permutation(s['vertno'])[:n_per_hemi]) for s in fwd['src'] ] nv = sum(len(v) for v in vertices) stc = SourceEstimate(amp * np.eye(nv), vertices, 0, 0.001) evoked = simulate_evoked(fwd, stc, evoked.info, cov, snr=20, random_state=rng) # For speed, let's use a subset of channels (strange but works) picks = np.sort( np.concatenate([ pick_types(evoked.info, meg=True, eeg=False)[::2], pick_types(evoked.info, meg=False, eeg=True)[::2] ])) evoked.pick_channels([evoked.ch_names[p] for p in picks]) evoked.add_proj(make_eeg_average_ref_proj(evoked.info)) write_evokeds(fname_sim, evoked) # Run MNE-C version run_subprocess([ 'mne_dipole_fit', '--meas', fname_sim, '--meg', '--eeg', '--noise', fname_cov, '--dip', fname_dtemp, '--mri', fname_fwd, '--reg', '0', '--tmin', '0', ]) dip_c = read_dipole(fname_dtemp) # Run mne-python version sphere = make_sphere_model(head_radius=0.1) dip, residuals = fit_dipole(evoked, fname_cov, sphere, fname_fwd) # Sanity check: do our residuals have less power than orig data? data_rms = np.sqrt(np.sum(evoked.data**2, axis=0)) resi_rms = np.sqrt(np.sum(residuals**2, axis=0)) factor = 1. # XXX weird, inexplicable differenc for 3.5 build we'll assume is due to # Anaconda bug for now... if os.getenv('TRAVIS', 'false') == 'true' and \ sys.version[:3] in ('3.5', '2.7'): factor = 0.8 assert_true((data_rms > factor * resi_rms).all(), msg='%s (factor: %s)' % ((data_rms / resi_rms).min(), factor)) # Compare to original points transform_surface_to(fwd['src'][0], 'head', fwd['mri_head_t']) transform_surface_to(fwd['src'][1], 'head', fwd['mri_head_t']) src_rr = np.concatenate([s['rr'][v] for s, v in zip(fwd['src'], vertices)], axis=0) src_nn = np.concatenate([s['nn'][v] for s, v in zip(fwd['src'], vertices)], axis=0) # MNE-C skips the last "time" point :( dip.crop(dip_c.times[0], dip_c.times[-1]) src_rr, src_nn = src_rr[:-1], src_nn[:-1] # check that we did at least as well corrs, dists, gc_dists, amp_errs, gofs = [], [], [], [], [] for d in (dip_c, dip): new = d.pos diffs = new - src_rr corrs += [np.corrcoef(src_rr.ravel(), new.ravel())[0, 1]] dists += [np.sqrt(np.mean(np.sum(diffs * diffs, axis=1)))] gc_dists += [ 180 / np.pi * np.mean(np.arccos(np.sum(src_nn * d.ori, axis=1))) ] amp_errs += [np.sqrt(np.mean((amp - d.amplitude)**2))] gofs += [np.mean(d.gof)] assert_true(dists[0] >= dists[1] * factor, 'dists: %s' % dists) assert_true(corrs[0] <= corrs[1] / factor, 'corrs: %s' % corrs) assert_true(gc_dists[0] >= gc_dists[1] * factor, 'gc-dists (ori): %s' % gc_dists) assert_true(amp_errs[0] >= amp_errs[1] * factor, 'amplitude errors: %s' % amp_errs) assert_true(gofs[0] <= gofs[1] / factor, 'gof: %s' % gofs)
reject = dict(mag=5000e-15, grad=300000e-15) eventID = dipnum epochs = mne.Epochs(raw, events, eventID, -0.5, 0.5, baseline=(None,0), picks=None, #reject=reject, preload=True, flat=None, proj=False, decim=1,reject_tmin=None, reject_tmax=None, detrend= None, on_missing='error', reject_by_annotation=True, verbose=True) epochs.drop(badtrial, badreason) #%% Find trial variance > index outliers> remove beyond plow and phigh percentile plow, phigh = 2.0, 98.0 bad_trials=my_var_cut_fn(epochs, plow, phigh, to_plot=True) print('\n%d trial to remove from total %d trials...\nNo. of remaining trials = %d\n'%(len(bad_trials), len(epochs), len(epochs)-len(bad_trials))) epochs.drop(bad_trials, reason='eye_blink and high variance', verbose=True) #%% Compute forward solution/leadfield bem=mne.make_sphere_model(r0=(0.0, 0.0, 0.0), head_radius=None, info=None, verbose=True) if not 'src_vol' in locals(): src_vol = mne.setup_volume_source_space(subject=subject, pos=5.0, mri=mrifile, bem=None, surface=surffile, mindist=5.0, exclude=10.0, subjects_dir=subjects_dir, volume_label=None, add_interpolator=True, verbose=True) if more_plots: mne.viz.plot_bem(subject=subject, subjects_dir=subjects_dir, orientation='coronal', slices=range(73,193,5), brain_surfaces=None, src=src_vol, show=True) mne.viz.plot_alignment(epochs.info, trans=transfile, subject=subject, subjects_dir=subjects_dir, fig=None, surfaces=['head-dense', 'inner_skull'], coord_frame='head', show_axes=True, meg=False, eeg='original', dig=True, ecog=True, bem=None, seeg=True, src=src_vol, mri_fiducials=False, verbose=True) if not 'fwd' in locals(): fwd = mne.make_forward_solution(epochs.info, trans=transfile, src=src_vol, bem=bem,
raw_filt = raw_sss_pca.copy().filter(h_freq=4., l_freq=None, filter_length='30s', n_jobs=n_jobs, fir_design='firwin2', phase='zero-double') # Pick the channels of interest raw_filt.pick_types(meg='grad') # Re-normalize projectors after subselection raw_filt.info.normalize_proj() # regularized data covariance data_cov = mne.compute_raw_covariance(raw_filt, n_jobs=n_jobs) # beamformer requirements bem = op.join(subjects_dir, subject, 'bem', 'genz501_17a-5120-bem-sol.fif') sphere = mne.make_sphere_model(r0='auto', head_radius='auto', info=raw_filt.info) src = mne.setup_volume_source_space(subject='fsaverage', bem=bem, mri=op.join(subjects_dir, 'fsaverage', 'mri', 'T1.mgz') subjects_dir=subjects_dir) fwd = mne.make_forward_solution(raw_filt.info, trans=None, src=src, bem=bem, n_jobs=n_jobs) filters = make_lcmv(raw_filt.info, fwd, data_cov, reg=0.05, pick_ori='max-power', weight_norm='nai', reduce_rank=True) t0 = time.time() stc = apply_lcmv_raw(raw_filt, filters) print(' Time: %s mns' % round((time.time() - t0) / 60, 2)) # Save result in stc files stc.save(op.join(datapath, subject, 'lcmv-vol'))
def test_simulate_raw_sphere(raw_data, tmpdir): """Test simulation of raw data with sphere model.""" seed = 42 raw, src, stc, trans, sphere = raw_data assert len(pick_types(raw.info, meg=False, ecg=True)) == 1 tempdir = str(tmpdir) # head pos head_pos_sim = _get_head_pos_sim(raw) # # Test raw simulation with basic parameters # raw.info.normalize_proj() cov = read_cov(cov_fname) cov['projs'] = raw.info['projs'] raw.info['bads'] = raw.ch_names[:1] with pytest.deprecated_call(match='cov is deprecated'): raw_sim = simulate_raw(raw, stc, trans, src, sphere, cov, head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed, verbose=True) with pytest.warns(RuntimeWarning, match='applying projector with'): raw_sim_2 = simulate_raw(raw, stc, trans_fname, src_fname, sphere, cov_fname, head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed) with pytest.raises(RuntimeError, match='Maximum number of STC iterations'): simulate_raw(raw.info, [stc] * 5, trans_fname, src_fname, sphere, cov=None, max_iter=1) assert_array_equal(raw_sim_2[:][0], raw_sim[:][0]) std = dict(grad=2e-13, mag=10e-15, eeg=0.1e-6) with pytest.deprecated_call(): raw_sim = simulate_raw(raw, stc, trans, src, sphere, make_ad_hoc_cov(raw.info, std=std), head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed) with pytest.deprecated_call(): raw_sim_2 = simulate_raw(raw, stc, trans_fname, src_fname, sphere, cov=std, head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed) assert_array_equal(raw_sim_2[:][0], raw_sim[:][0]) sphere_norad = make_sphere_model('auto', None, raw.info) raw_meg = raw.copy().pick_types() with pytest.deprecated_call(): raw_sim = simulate_raw(raw_meg, stc, trans, src, sphere_norad, cov=None, head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed) with pytest.deprecated_call(): raw_sim_2 = simulate_raw(raw_meg, stc, trans_fname, src_fname, sphere_norad, cov=None, head_pos=head_pos_sim, blink=True, ecg=True, random_state=seed) assert_array_equal(raw_sim_2[:][0], raw_sim[:][0]) # Test IO on processed data test_outname = op.join(tempdir, 'sim_test_raw.fif') raw_sim.save(test_outname) raw_sim_loaded = read_raw_fif(test_outname, preload=True) assert_allclose(raw_sim_loaded[:][0], raw_sim[:][0], rtol=1e-6, atol=1e-20) del raw_sim, raw_sim_2 # with no cov (no noise) but with artifacts, most time periods should match # but the EOG/ECG channels should not for ecg, eog in ((True, False), (False, True), (True, True)): with pytest.deprecated_call(): raw_sim_3 = simulate_raw(raw, stc, trans, src, sphere, cov=None, head_pos=head_pos_sim, blink=eog, ecg=ecg, random_state=seed) with pytest.deprecated_call(): raw_sim_4 = simulate_raw(raw, stc, trans, src, sphere, cov=None, head_pos=head_pos_sim, blink=False, ecg=False, random_state=seed) picks = np.arange(len(raw.ch_names)) diff_picks = pick_types(raw.info, meg=False, ecg=ecg, eog=eog) these_picks = np.setdiff1d(picks, diff_picks) close = np.isclose(raw_sim_3[these_picks][0], raw_sim_4[these_picks][0], atol=1e-20) assert np.mean(close) > 0.7 far = ~np.isclose( raw_sim_3[diff_picks][0], raw_sim_4[diff_picks][0], atol=1e-20) assert np.mean(far) > 0.99 del raw_sim_3, raw_sim_4 # make sure it works with EEG-only and MEG-only with pytest.deprecated_call(): raw_sim_meg = simulate_raw(raw.copy().pick_types(meg=True, eeg=False), stc, trans, src, sphere, cov=None) raw_sim_eeg = simulate_raw(raw.copy().pick_types(meg=False, eeg=True), stc, trans, src, sphere, cov=None) raw_sim_meeg = simulate_raw(raw.copy().pick_types(meg=True, eeg=True), stc, trans, src, sphere, cov=None) for this_raw in (raw_sim_meg, raw_sim_eeg, raw_sim_meeg): add_eog(this_raw, random_state=seed) for this_raw in (raw_sim_meg, raw_sim_meeg): add_ecg(this_raw, random_state=seed) with pytest.raises(RuntimeError, match='only add ECG artifacts if MEG'): add_ecg(raw_sim_eeg) assert_allclose(np.concatenate((raw_sim_meg[:][0], raw_sim_eeg[:][0])), raw_sim_meeg[:][0], rtol=1e-7, atol=1e-20) del raw_sim_meg, raw_sim_eeg, raw_sim_meeg # check that raw-as-info is supported n_samp = len(stc.times) raw_crop = raw.copy().crop(0., (n_samp - 1.) / raw.info['sfreq']) assert len(raw_crop.times) == len(stc.times) with pytest.deprecated_call(): raw_sim = simulate_raw(raw_crop, stc, trans, src, sphere, cov=None) with catch_logging() as log: raw_sim_2 = simulate_raw(raw_crop.info, stc, trans, src, sphere, cov=None, verbose=True) log = log.getvalue() assert '1 STC iteration provided' in log assert len(raw_sim_2.times) == n_samp assert_allclose(raw_sim[:, :n_samp][0], raw_sim_2[:, :n_samp][0], rtol=1e-5, atol=1e-30) del raw_sim, raw_sim_2 # check that different interpolations are similar given small movements with pytest.deprecated_call(): raw_sim = simulate_raw(raw, stc, trans, src, sphere, cov=None, head_pos=head_pos_sim, interp='linear') with pytest.deprecated_call(): raw_sim_hann = simulate_raw(raw, stc, trans, src, sphere, cov=None, head_pos=head_pos_sim, interp='hann') assert_allclose(raw_sim[:][0], raw_sim_hann[:][0], rtol=1e-1, atol=1e-14) del raw_sim_hann # check that new Generator objects can be used if check_version('numpy', '1.17'): random_state = np.random.default_rng(seed) add_ecg(raw_sim, random_state=random_state) add_eog(raw_sim, random_state=random_state)
def test_make_forward_dipole(tmpdir): """Test forward-projecting dipoles.""" rng = np.random.RandomState(0) evoked = read_evokeds(fname_evo)[0] cov = read_cov(fname_cov) cov['projs'] = [] # avoid proj warning dip_c = read_dipole(fname_dip) # Only use magnetometers for speed! picks = pick_types(evoked.info, meg='mag', eeg=False)[::8] evoked.pick_channels([evoked.ch_names[p] for p in picks]) evoked.info.normalize_proj() info = evoked.info # Make new Dipole object with n_test_dipoles picked from the dipoles # in the test dataset. n_test_dipoles = 3 # minimum 3 needed to get uneven sampling in time dipsel = np.sort(rng.permutation(np.arange(len(dip_c)))[:n_test_dipoles]) dip_test = Dipole(times=dip_c.times[dipsel], pos=dip_c.pos[dipsel], amplitude=dip_c.amplitude[dipsel], ori=dip_c.ori[dipsel], gof=dip_c.gof[dipsel]) sphere = make_sphere_model(head_radius=0.1) # Warning emitted due to uneven sampling in time with pytest.warns(RuntimeWarning, match='unevenly spaced'): fwd, stc = make_forward_dipole(dip_test, sphere, info, trans=fname_trans) # stc is list of VolSourceEstimate's assert isinstance(stc, list) for n_dip in range(n_test_dipoles): assert isinstance(stc[n_dip], VolSourceEstimate) # Now simulate evoked responses for each of the test dipoles, # and fit dipoles to them (sphere model, MEG and EEG) times, pos, amplitude, ori, gof = [], [], [], [], [] nave = 200 # add a tiny amount of noise to the simulated evokeds for s in stc: evo_test = simulate_evoked(fwd, s, info, cov, nave=nave, random_state=rng) # evo_test.add_proj(make_eeg_average_ref_proj(evo_test.info)) dfit, resid = fit_dipole(evo_test, cov, sphere, None) times += dfit.times.tolist() pos += dfit.pos.tolist() amplitude += dfit.amplitude.tolist() ori += dfit.ori.tolist() gof += dfit.gof.tolist() # Create a new Dipole object with the dipole fits dip_fit = Dipole(times, pos, amplitude, ori, gof) # check that true (test) dipoles and fits are "close" # cf. mne/tests/test_dipole.py diff = dip_test.pos - dip_fit.pos corr = np.corrcoef(dip_test.pos.ravel(), dip_fit.pos.ravel())[0, 1] dist = np.sqrt(np.mean(np.sum(diff * diff, axis=1))) gc_dist = 180 / np.pi * \ np.mean(np.arccos(np.sum(dip_test.ori * dip_fit.ori, axis=1))) amp_err = np.sqrt(np.mean((dip_test.amplitude - dip_fit.amplitude) ** 2)) # Make sure each coordinate is close to reference # NB tolerance should be set relative to snr of simulated evoked! assert_allclose(dip_fit.pos, dip_test.pos, rtol=0, atol=1e-2, err_msg='position mismatch') assert dist < 1e-2 # within 1 cm assert corr > 0.985 assert gc_dist < 20 # less than 20 degrees assert amp_err < 10e-9 # within 10 nAm # Make sure rejection works with BEM: one dipole at z=1m # NB _make_forward.py:_prepare_for_forward will raise a RuntimeError # if no points are left after min_dist exclusions, hence 2 dips here! dip_outside = Dipole(times=[0., 0.001], pos=[[0., 0., 1.0], [0., 0., 0.040]], amplitude=[100e-9, 100e-9], ori=[[1., 0., 0.], [1., 0., 0.]], gof=1) with pytest.raises(ValueError, match='outside the inner skull'): make_forward_dipole(dip_outside, fname_bem, info, fname_trans) # if we get this far, can safely assume the code works with BEMs too # -> use sphere again below for speed # Now make an evenly sampled set of dipoles, some simultaneous, # should return a VolSourceEstimate regardless times = [0., 0., 0., 0.001, 0.001, 0.002] pos = np.random.rand(6, 3) * 0.020 + \ np.array([0., 0., 0.040])[np.newaxis, :] amplitude = np.random.rand(6) * 100e-9 ori = np.eye(6, 3) + np.eye(6, 3, -3) gof = np.arange(len(times)) / len(times) # arbitrary dip_even_samp = Dipole(times, pos, amplitude, ori, gof) # I/O round-trip fname = str(tmpdir.join('test-fwd.fif')) with pytest.warns(RuntimeWarning, match='free orientation'): write_forward_solution(fname, fwd) fwd_read = convert_forward_solution( read_forward_solution(fname), force_fixed=True) assert_forward_allclose(fwd, fwd_read, rtol=1e-6) fwd, stc = make_forward_dipole(dip_even_samp, sphere, info, trans=fname_trans) assert isinstance(stc, VolSourceEstimate) assert_allclose(stc.times, np.arange(0., 0.003, 0.001))
def test_gamma_map_vol_sphere(): """Gamma MAP with a sphere forward and volumic source space.""" evoked = read_evokeds(fname_evoked, condition=0, baseline=(None, 0), proj=False) evoked.resample(50, npad=100) evoked.crop(tmin=0.1, tmax=0.16) # crop to window around peak cov = read_cov(fname_cov) cov = regularize(cov, evoked.info, rank=None) info = evoked.info sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080) src = mne.setup_volume_source_space(subject=None, pos=30., mri=None, sphere=(0.0, 0.0, 0.0, 0.08), bem=None, mindist=5.0, exclude=2.0, sphere_units='m') fwd = mne.make_forward_solution(info, trans=None, src=src, bem=sphere, eeg=False, meg=True) alpha = 0.5 pytest.raises(ValueError, gamma_map, evoked, fwd, cov, alpha, loose=0, return_residual=False) pytest.raises(ValueError, gamma_map, evoked, fwd, cov, alpha, loose=0.2, return_residual=False) stc = gamma_map(evoked, fwd, cov, alpha, tol=1e-4, xyz_same_gamma=False, update_mode=2, return_residual=False) assert_array_almost_equal(stc.times, evoked.times, 5) # Compare orientation obtained using fit_dipole and gamma_map # for a simulated evoked containing a single dipole stc = mne.VolSourceEstimate(50e-9 * np.random.RandomState(42).randn(1, 4), vertices=[stc.vertices[0][:1]], tmin=stc.tmin, tstep=stc.tstep) evoked_dip = mne.simulation.simulate_evoked(fwd, stc, info, cov, nave=1e9, use_cps=True) dip_gmap = gamma_map(evoked_dip, fwd, cov, 0.1, return_as_dipoles=True) amp_max = [np.max(d.amplitude) for d in dip_gmap] dip_gmap = dip_gmap[np.argmax(amp_max)] assert (dip_gmap[0].pos[0] in src[0]['rr'][stc.vertices[0]]) dip_fit = mne.fit_dipole(evoked_dip, cov, sphere)[0] assert (np.abs(np.dot(dip_fit.ori[0], dip_gmap.ori[0])) > 0.99)
# # License: BSD (3-clause) import os.path as op import numpy as np from mne.datasets import phantom_4dbti import mne ############################################################################### # Read data and compute a dipole fit at the peak of the evoked response data_path = phantom_4dbti.data_path() raw_fname = op.join(data_path, '%d/e,rfhp1.0Hz') dipoles = list() sphere = mne.make_sphere_model(r0=(0., 0., 0.), head_radius=0.080) t0 = 0.07 # peak of the response pos = np.empty((4, 3)) ori = np.empty((4, 3)) for ii in range(4): raw = mne.io.read_raw_bti(raw_fname % (ii + 1,), rename_channels=False, preload=True) raw.info['bads'] = ['A173', 'A213', 'A232'] events = mne.find_events(raw, 'TRIGGER', mask=4350, mask_type='not_and') epochs = mne.Epochs(raw, events=events, event_id=8192, tmin=-0.2, tmax=0.4, preload=True) evoked = epochs.average() evoked.plot(time_unit='s')
def test_channel_name_limit(tmpdir, monkeypatch, fname): """Test that our remapping works properly.""" # # raw # if fname.endswith('fif'): raw = read_raw_fif(fname) raw.pick_channels(raw.ch_names[:3]) ref_names = [] data_names = raw.ch_names else: assert fname.endswith('.ds') raw = read_raw_ctf(fname) ref_names = [ raw.ch_names[pick] for pick in pick_types(raw.info, meg=False, ref_meg=True) ] data_names = raw.ch_names[32:35] proj = dict(data=np.ones((1, len(data_names))), col_names=data_names[:2].copy(), row_names=None, nrow=1) proj = Projection(data=proj, active=False, desc='test', kind=0, explained_var=0.) raw.add_proj(proj, remove_existing=True) raw.info.normalize_proj() raw.pick_channels(data_names + ref_names).crop(0, 2) long_names = ['123456789abcdefg' + name for name in raw.ch_names] fname = tmpdir.join('test-raw.fif') with catch_logging() as log: raw.save(fname) log = log.getvalue() assert 'truncated' not in log rename = dict(zip(raw.ch_names, long_names)) long_data_names = [rename[name] for name in data_names] long_proj_names = long_data_names[:2] raw.rename_channels(rename) for comp in raw.info['comps']: for key in ('row_names', 'col_names'): for name in comp['data'][key]: assert name in raw.ch_names if raw.info['comps']: assert raw.compensation_grade == 0 raw.apply_gradient_compensation(3) assert raw.compensation_grade == 3 assert len(raw.info['projs']) == 1 assert raw.info['projs'][0]['data']['col_names'] == long_proj_names raw.info['bads'] = bads = long_data_names[2:3] good_long_data_names = [ name for name in long_data_names if name not in bads ] with catch_logging() as log: raw.save(fname, overwrite=True, verbose=True) log = log.getvalue() assert 'truncated to 15' in log for name in raw.ch_names: assert len(name) > 15 # first read the full way with catch_logging() as log: raw_read = read_raw_fif(fname, verbose=True) log = log.getvalue() assert 'Reading extended channel information' in log for ra in (raw, raw_read): assert ra.ch_names == long_names assert raw_read.info['projs'][0]['data']['col_names'] == long_proj_names del raw_read # next read as if no longer names could be read monkeypatch.setattr(meas_info, '_read_extended_ch_info', lambda x, y, z: None) with catch_logging() as log: raw_read = read_raw_fif(fname, verbose=True) log = log.getvalue() assert 'extended' not in log if raw.info['comps']: assert raw_read.compensation_grade == 3 raw_read.apply_gradient_compensation(0) assert raw_read.compensation_grade == 0 monkeypatch.setattr( # restore meas_info, '_read_extended_ch_info', _read_extended_ch_info) short_proj_names = [ f'{name[:13 - bool(len(ref_names))]}-{len(ref_names) + ni}' for ni, name in enumerate(long_data_names[:2]) ] assert raw_read.info['projs'][0]['data']['col_names'] == short_proj_names # # epochs # epochs = Epochs(raw, make_fixed_length_events(raw)) fname = tmpdir.join('test-epo.fif') epochs.save(fname) epochs_read = read_epochs(fname) for ep in (epochs, epochs_read): assert ep.info['ch_names'] == long_names assert ep.ch_names == long_names del raw, epochs_read # cov epochs.info['bads'] = [] cov = compute_covariance(epochs, verbose='error') fname = tmpdir.join('test-cov.fif') write_cov(fname, cov) cov_read = read_cov(fname) for co in (cov, cov_read): assert co['names'] == long_data_names assert co['bads'] == [] del cov_read # # evoked # evoked = epochs.average() evoked.info['bads'] = bads assert evoked.nave == 1 fname = tmpdir.join('test-ave.fif') evoked.save(fname) evoked_read = read_evokeds(fname)[0] for ev in (evoked, evoked_read): assert ev.ch_names == long_names assert ev.info['bads'] == bads del evoked_read, epochs # # forward # with pytest.warns(None): # not enough points for CTF sphere = make_sphere_model('auto', 'auto', evoked.info) src = setup_volume_source_space( pos=dict(rr=[[0, 0, 0.04]], nn=[[0, 1., 0.]])) fwd = make_forward_solution(evoked.info, None, src, sphere) fname = tmpdir.join('temp-fwd.fif') write_forward_solution(fname, fwd) fwd_read = read_forward_solution(fname) for fw in (fwd, fwd_read): assert fw['sol']['row_names'] == long_data_names assert fw['info']['ch_names'] == long_data_names assert fw['info']['bads'] == bads del fwd_read # # inv # inv = make_inverse_operator(evoked.info, fwd, cov) fname = tmpdir.join('test-inv.fif') write_inverse_operator(fname, inv) inv_read = read_inverse_operator(fname) for iv in (inv, inv_read): assert iv['info']['ch_names'] == good_long_data_names apply_inverse(evoked, inv) # smoke test
def dipolarity(mixing, inst, picks, fname_bem=None, fname_trans=None, min_dist=5, n_jobs=1, verbose=None): n_channels = inst.info['nchan'] ch_names = inst.info['ch_names'] cov = mne.Covariance(np.eye(n_channels), ch_names, bads=[], projs=[], nfree=1) if fname_bem is None: head_radius = 0.085 pos = np.array([c['loc'][:3] for c in inst.info['chs']]) pos /= np.sqrt(np.sum(pos**2, axis=1))[:, None] pos *= head_radius kind = "eeglab" selection = np.arange(n_channels) montage = mne.channels.Montage(pos, ch_names, kind, selection) inst.set_montage(montage) inst.set_channel_types({'LEYE': 'eog', 'REYE': 'eog'}) fname_bem =\ mne.make_sphere_model(r0=(0.0, 0.0, 0.0), head_radius=head_radius, relative_radii=[0.8353, 0.847, 0.93, 1], sigmas=(0.33, 1.0, 0.0042, 0.33)) picks = mne.pick_types(inst.info, eeg=True, eog=False) info = mne.pick_info(inst.info, sel=picks) evoked = mne.EvokedArray(mixing, info, tmin=0, comment='ICA components') info['projs'] = [] # get rid of SSP projections if 'eeg' in evoked: evoked = evoked.copy() avg_proj = mne.io.make_eeg_average_ref_proj(evoked.info) evoked.add_proj([avg_proj]) evoked.apply_proj() dip, residual = mne.fit_dipole(evoked, cov, fname_bem, fname_trans, min_dist=min_dist, verbose=verbose, n_jobs=n_jobs) gof = (1. - np.sum(residual.data**2, axis=0) / np.sum(evoked.data**2, axis=0)) gof = 100. * gof # Scale the gof between 0 and 100 # if some gof is NaN, raise an Error if np.sum(np.isnan(gof)) > 0: raise ValueError('ERROR!, some gof are NaN. This usually happens ' 'because some dipoles position resulting to be too ' 'close to the inner sphere. To solve this issue, ' 'consider using a different value for the min_dist ' 'parameter.') # Do not sort the columns of A, neither the gof, this way is easier to # mantain the one-to-one correspondence between the columns of A and the # the measures associated to them (gof, depth, radiality, etc) # idx_sort_desc = np.argsort(gof)[::-1] # evoked.data = evoked.data[:, idx_sort_desc] # gof = gof[idx_sort_desc] return gof, dip, evoked
# Uncomment the following line to align the data yourself. # mne.gui.coregistration(subject='sample', subjects_dir=subjects_dir) ############################################################################### # .. _plot_source_alignment_without_mri: # # Alignment without MRI # --------------------- # The surface alignments above are possible if you have the surfaces available # from Freesurfer. :func:`mne.viz.plot_alignment` automatically searches for # the correct surfaces from the provided ``subjects_dir``. Another option is # to use a :ref:`spherical conductor model <ch_forward_spherical_model>`. It is # passed through ``bem`` parameter. sphere = mne.make_sphere_model(info=raw.info, r0='auto', head_radius='auto') src = mne.setup_volume_source_space(sphere=sphere, pos=10.) mne.viz.plot_alignment(raw.info, eeg='projected', bem=sphere, src=src, dig=True, surfaces=['brain', 'outer_skin'], coord_frame='meg', show_axes=True) ############################################################################### # It is also possible to use :func:`mne.gui.coregistration` # to warp a subject (usually ``fsaverage``) to subject digitization data, see # `these slides # <https://www.slideshare.net/mne-python/mnepython-scale-mri>`_.
'{}_ann_MEGartif_flt.txt'.format(fname_noext))) if len(anns_MEG_artif_flt) > 0: print('Artif found in filtered {}, maxlen {:.3f} totlen {:.3f}'. format(anns_MEG_artif_flt, np.max(anns_MEG_artif_flt.duration), np.sum(anns_MEG_artif_flt.duration))) else: print('Artif found in filtered {} is NONE'.format( anns_MEG_artif_flt)) if not do_removeMEG and not do_ICA_only: mod_info, infos = upre.readInfo(fname_noext, f) radius, origin, _ = mne.bem.fit_sphere_to_headshape( mod_info, dig_kinds=('cardinal', 'hpi')) sphere = mne.make_sphere_model(info=mod_info, r0=origin, head_radius=radius) src = mne.setup_volume_source_space(sphere=sphere, pos=10.) if do_plot_helmet: import mayavi mne.viz.plot_alignment(mod_info, eeg='projected', bem=sphere, src=src, dig=True, surfaces=['brain', 'outer_skin'], coord_frame='meg', show_axes=True) mayavi.mlab.savefig( os.path.join(dir_fig,
def test_simulate_raw_sphere(raw_data, tmpdir): """Test simulation of raw data with sphere model.""" seed = 42 raw, src, stc, trans, sphere = raw_data assert len(pick_types(raw.info, meg=False, ecg=True)) == 1 tempdir = str(tmpdir) # head pos head_pos_sim = _get_head_pos_sim(raw) # # Test raw simulation with basic parameters # raw.info.normalize_proj() cov = read_cov(cov_fname) cov['projs'] = raw.info['projs'] raw.info['bads'] = raw.ch_names[:1] sphere_norad = make_sphere_model('auto', None, raw.info) raw_meg = raw.copy().pick_types() raw_sim = simulate_raw(raw_meg.info, stc, trans, src, sphere_norad, head_pos=head_pos_sim) # Test IO on processed data test_outname = op.join(tempdir, 'sim_test_raw.fif') raw_sim.save(test_outname) raw_sim_loaded = read_raw_fif(test_outname, preload=True) assert_allclose(raw_sim_loaded[:][0], raw_sim[:][0], rtol=1e-6, atol=1e-20) del raw_sim # make sure it works with EEG-only and MEG-only raw_sim_meg = simulate_raw( raw.copy().pick_types(meg=True, eeg=False).info, stc, trans, src, sphere) raw_sim_eeg = simulate_raw( raw.copy().pick_types(meg=False, eeg=True).info, stc, trans, src, sphere) raw_sim_meeg = simulate_raw( raw.copy().pick_types(meg=True, eeg=True).info, stc, trans, src, sphere) for this_raw in (raw_sim_meg, raw_sim_eeg, raw_sim_meeg): add_eog(this_raw, random_state=seed) for this_raw in (raw_sim_meg, raw_sim_meeg): add_ecg(this_raw, random_state=seed) with pytest.raises(RuntimeError, match='only add ECG artifacts if MEG'): add_ecg(raw_sim_eeg) assert_allclose(np.concatenate((raw_sim_meg[:][0], raw_sim_eeg[:][0])), raw_sim_meeg[:][0], rtol=1e-7, atol=1e-20) del raw_sim_meg, raw_sim_eeg, raw_sim_meeg # check that raw-as-info is supported n_samp = len(stc.times) raw_crop = raw.copy().crop(0., (n_samp - 1.) / raw.info['sfreq']) assert len(raw_crop.times) == len(stc.times) raw_sim = simulate_raw(raw_crop.info, stc, trans, src, sphere) with catch_logging() as log: raw_sim_2 = simulate_raw(raw_crop.info, stc, trans, src, sphere, verbose=True) log = log.getvalue() assert '1 STC iteration provided' in log assert len(raw_sim_2.times) == n_samp assert_allclose(raw_sim[:, :n_samp][0], raw_sim_2[:, :n_samp][0], rtol=1e-5, atol=1e-30) del raw_sim, raw_sim_2 # check that different interpolations are similar given small movements raw_sim = simulate_raw(raw.info, stc, trans, src, sphere, head_pos=head_pos_sim, interp='linear') raw_sim_hann = simulate_raw(raw.info, stc, trans, src, sphere, head_pos=head_pos_sim, interp='hann') assert_allclose(raw_sim[:][0], raw_sim_hann[:][0], rtol=1e-1, atol=1e-14) del raw_sim_hann # check that new Generator objects can be used if check_version('numpy', '1.17'): random_state = np.random.default_rng(seed) add_ecg(raw_sim, random_state=random_state) add_eog(raw_sim, random_state=random_state)
def test_dipole_fitting_fixed(tmpdir): """Test dipole fitting with a fixed position.""" tpeak = 0.073 sphere = make_sphere_model(head_radius=0.1) evoked = read_evokeds(fname_evo, baseline=(None, 0))[0] evoked.pick_types(meg=True) t_idx = np.argmin(np.abs(tpeak - evoked.times)) evoked_crop = evoked.copy().crop(tpeak, tpeak) assert len(evoked_crop.times) == 1 cov = read_cov(fname_cov) dip_seq, resid = fit_dipole(evoked_crop, cov, sphere) assert isinstance(dip_seq, Dipole) assert isinstance(resid, Evoked) assert len(dip_seq.times) == 1 pos, ori, gof = dip_seq.pos[0], dip_seq.ori[0], dip_seq.gof[0] amp = dip_seq.amplitude[0] # Fix position, allow orientation to change dip_free, resid_free = fit_dipole(evoked, cov, sphere, pos=pos) assert isinstance(dip_free, Dipole) assert isinstance(resid_free, Evoked) assert_allclose(dip_free.times, evoked.times) assert_allclose(np.tile(pos[np.newaxis], (len(evoked.times), 1)), dip_free.pos) assert_allclose(ori, dip_free.ori[t_idx]) # should find same ori assert (np.dot(dip_free.ori, ori).mean() < 0.9) # but few the same assert_allclose(gof, dip_free.gof[t_idx]) # ... same gof assert_allclose(amp, dip_free.amplitude[t_idx]) # and same amp assert_allclose(resid.data, resid_free.data[:, [t_idx]]) # Fix position and orientation dip_fixed, resid_fixed = fit_dipole(evoked, cov, sphere, pos=pos, ori=ori) assert (isinstance(dip_fixed, DipoleFixed)) assert_allclose(dip_fixed.times, evoked.times) assert_allclose(dip_fixed.info['chs'][0]['loc'][:3], pos) assert_allclose(dip_fixed.info['chs'][0]['loc'][3:6], ori) assert_allclose(dip_fixed.data[1, t_idx], gof) assert_allclose(resid.data, resid_fixed.data[:, [t_idx]]) _check_roundtrip_fixed(dip_fixed, tmpdir) # bad resetting evoked.info['bads'] = [evoked.ch_names[3]] dip_fixed, resid_fixed = fit_dipole(evoked, cov, sphere, pos=pos, ori=ori) # Degenerate conditions evoked_nan = evoked.copy().crop(0, 0) evoked_nan.data[0, 0] = None pytest.raises(ValueError, fit_dipole, evoked_nan, cov, sphere) pytest.raises(ValueError, fit_dipole, evoked, cov, sphere, ori=[1, 0, 0]) pytest.raises(ValueError, fit_dipole, evoked, cov, sphere, pos=[0, 0, 0], ori=[2, 0, 0]) pytest.raises(ValueError, fit_dipole, evoked, cov, sphere, pos=[0.1, 0, 0]) # copying dip_fixed_2 = dip_fixed.copy() dip_fixed_2.data[:] = 0. assert not np.isclose(dip_fixed.data, 0., atol=1e-20).any() # plotting plt.close('all') dip_fixed.plot() plt.close('all') orig_times = np.array(dip_fixed.times) shift_times = dip_fixed.shift_time(1.).times assert_allclose(shift_times, orig_times + 1)
def test_plot_alignment(tmpdir): """Test plotting of -trans.fif files and MEG sensor layouts.""" # generate fiducials file for testing tempdir = str(tmpdir) fiducials_path = op.join(tempdir, 'fiducials.fif') fid = [{'coord_frame': 5, 'ident': 1, 'kind': 1, 'r': [-0.08061612, -0.02908875, -0.04131077]}, {'coord_frame': 5, 'ident': 2, 'kind': 1, 'r': [0.00146763, 0.08506715, -0.03483611]}, {'coord_frame': 5, 'ident': 3, 'kind': 1, 'r': [0.08436285, -0.02850276, -0.04127743]}] write_dig(fiducials_path, fid, 5) mlab = _import_mlab() evoked = read_evokeds(evoked_fname)[0] sample_src = read_source_spaces(src_fname) bti = read_raw_bti(pdf_fname, config_fname, hs_fname, convert=True, preload=False).info infos = dict( Neuromag=evoked.info, CTF=read_raw_ctf(ctf_fname).info, BTi=bti, KIT=read_raw_kit(sqd_fname).info, ) for system, info in infos.items(): meg = ['helmet', 'sensors'] if system == 'KIT': meg.append('ref') plot_alignment(info, trans_fname, subject='sample', subjects_dir=subjects_dir, meg=meg) mlab.close(all=True) # KIT ref sensor coil def is defined mlab.close(all=True) info = infos['Neuromag'] pytest.raises(TypeError, plot_alignment, 'foo', trans_fname, subject='sample', subjects_dir=subjects_dir) pytest.raises(TypeError, plot_alignment, info, trans_fname, subject='sample', subjects_dir=subjects_dir, src='foo') pytest.raises(ValueError, plot_alignment, info, trans_fname, subject='fsaverage', subjects_dir=subjects_dir, src=sample_src) sample_src.plot(subjects_dir=subjects_dir, head=True, skull=True, brain='white') mlab.close(all=True) # no-head version mlab.close(all=True) # all coord frames pytest.raises(ValueError, plot_alignment, info) plot_alignment(info, surfaces=[]) for coord_frame in ('meg', 'head', 'mri'): plot_alignment(info, meg=['helmet', 'sensors'], dig=True, coord_frame=coord_frame, trans=trans_fname, subject='sample', mri_fiducials=fiducials_path, subjects_dir=subjects_dir, src=sample_src) mlab.close(all=True) # EEG only with strange options evoked_eeg_ecog_seeg = evoked.copy().pick_types(meg=False, eeg=True) evoked_eeg_ecog_seeg.info['projs'] = [] # "remove" avg proj evoked_eeg_ecog_seeg.set_channel_types({'EEG 001': 'ecog', 'EEG 002': 'seeg'}) with pytest.warns(RuntimeWarning, match='Cannot plot MEG'): plot_alignment(evoked_eeg_ecog_seeg.info, subject='sample', trans=trans_fname, subjects_dir=subjects_dir, surfaces=['white', 'outer_skin', 'outer_skull'], meg=['helmet', 'sensors'], eeg=['original', 'projected'], ecog=True, seeg=True) mlab.close(all=True) sphere = make_sphere_model(info=evoked.info, r0='auto', head_radius='auto') bem_sol = read_bem_solution(op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem-sol.fif')) bem_surfs = read_bem_surfaces(op.join(subjects_dir, 'sample', 'bem', 'sample-1280-1280-1280-bem.fif')) sample_src[0]['coord_frame'] = 4 # hack for coverage plot_alignment(info, subject='sample', eeg='projected', meg='helmet', bem=sphere, dig=True, surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin']) plot_alignment(info, trans_fname, subject='sample', meg='helmet', subjects_dir=subjects_dir, eeg='projected', bem=sphere, surfaces=['head', 'brain'], src=sample_src) assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI for surf in bem_sol['surfs']) plot_alignment(info, trans_fname, subject='sample', meg=[], subjects_dir=subjects_dir, bem=bem_sol, eeg=True, surfaces=['head', 'inflated', 'outer_skull', 'inner_skull']) assert all(surf['coord_frame'] == FIFF.FIFFV_COORD_MRI for surf in bem_sol['surfs']) plot_alignment(info, trans_fname, subject='sample', meg=True, subjects_dir=subjects_dir, surfaces=['head', 'inner_skull'], bem=bem_surfs) sphere = make_sphere_model('auto', 'auto', evoked.info) src = setup_volume_source_space(sphere=sphere) plot_alignment(info, eeg='projected', meg='helmet', bem=sphere, src=src, dig=True, surfaces=['brain', 'inner_skull', 'outer_skull', 'outer_skin']) sphere = make_sphere_model('auto', None, evoked.info) # one layer plot_alignment(info, trans_fname, subject='sample', meg=False, coord_frame='mri', subjects_dir=subjects_dir, surfaces=['brain'], bem=sphere, show_axes=True) # 3D coil with no defined draw (ConvexHull) info_cube = pick_info(info, [0]) info['dig'] = None info_cube['chs'][0]['coil_type'] = 9999 with pytest.raises(RuntimeError, match='coil definition not found'): plot_alignment(info_cube, meg='sensors', surfaces=()) coil_def_fname = op.join(tempdir, 'temp') with open(coil_def_fname, 'w') as fid: fid.write(coil_3d) with use_coil_def(coil_def_fname): plot_alignment(info_cube, meg='sensors', surfaces=(), dig=True) # one layer bem with skull surfaces: pytest.raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['brain', 'head', 'inner_skull'], bem=sphere) # wrong eeg value: pytest.raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, eeg='foo') # wrong meg value: pytest.raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, meg='bar') # multiple brain surfaces: pytest.raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['white', 'pial']) pytest.raises(TypeError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=[1]) pytest.raises(ValueError, plot_alignment, info=info, trans=trans_fname, subject='sample', subjects_dir=subjects_dir, surfaces=['foo']) mlab.close(all=True)