def _compare_forwards(fwd, fwd_py, n_sensors, n_src): """Helper to test forwards""" # check source spaces assert_equal(len(fwd['src']), len(fwd_py['src'])) _compare_source_spaces(fwd['src'], fwd_py['src'], mode='approx') for surf_ori in [False, True]: if surf_ori: fwd = convert_forward_solution(fwd, surf_ori, copy=False) fwd_py = convert_forward_solution(fwd, surf_ori, copy=False) for key in ['nchan', 'source_nn', 'source_rr', 'source_ori', 'surf_ori', 'coord_frame', 'nsource']: print key assert_allclose(fwd_py[key], fwd[key], rtol=1e-4, atol=1e-7) assert_allclose(fwd_py['mri_head_t']['trans'], fwd['mri_head_t']['trans'], rtol=1e-5, atol=1e-8) # check MEG assert_allclose(fwd['sol']['data'][:306], fwd_py['sol']['data'][:306], rtol=1e-4, atol=1e-9) # check EEG if fwd['sol']['data'].shape[0] > 306: assert_allclose(fwd['sol']['data'][306:], fwd_py['sol']['data'][306:], rtol=1e-3, atol=1e-3) assert_equal(fwd_py['sol']['data'].shape, (n_sensors, n_src)) assert_equal(len(fwd['sol']['row_names']), n_sensors) assert_equal(len(fwd_py['sol']['row_names']), n_sensors)
def test_priors(): """Test prior computations.""" # Depth prior fwd = read_forward_solution(fname_meeg) assert not is_fixed_orient(fwd) n_sources = fwd['nsource'] info = read_info(fname_evoked) depth_prior = compute_depth_prior(fwd, info, exp=0.8) assert depth_prior.shape == (3 * n_sources,) depth_prior = compute_depth_prior(fwd, info, exp=0.) assert_array_equal(depth_prior, 1.) with pytest.raises(ValueError, match='must be "whiten"'): compute_depth_prior(fwd, info, limit_depth_chs='foo') with pytest.raises(ValueError, match='noise_cov must be a Covariance'): compute_depth_prior(fwd, info, limit_depth_chs='whiten') fwd_fixed = convert_forward_solution(fwd, force_fixed=True) with pytest.deprecated_call(): depth_prior = compute_depth_prior( fwd_fixed['sol']['data'], info, is_fixed_ori=True) assert depth_prior.shape == (n_sources,) # Orientation prior orient_prior = compute_orient_prior(fwd, 1.) assert_array_equal(orient_prior, 1.) orient_prior = compute_orient_prior(fwd_fixed, 0.) assert_array_equal(orient_prior, 1.) with pytest.raises(ValueError, match='oriented in surface coordinates'): compute_orient_prior(fwd, 0.5) fwd_surf_ori = convert_forward_solution(fwd, surf_ori=True) orient_prior = compute_orient_prior(fwd_surf_ori, 0.5) assert all(np.in1d(orient_prior, (0.5, 1.))) with pytest.raises(ValueError, match='between 0 and 1'): compute_orient_prior(fwd_surf_ori, -0.5) with pytest.raises(ValueError, match='with fixed orientation'): compute_orient_prior(fwd_fixed, 0.5)
def _compare_forwards(fwd, fwd_py, n_sensors, n_src, meg_rtol=1e-4, meg_atol=1e-9): """Helper to test forwards""" # check source spaces assert_equal(len(fwd["src"]), len(fwd_py["src"])) _compare_source_spaces(fwd["src"], fwd_py["src"], mode="approx") for surf_ori in [False, True]: if surf_ori: # use copy here to leave our originals unmodified fwd = convert_forward_solution(fwd, surf_ori, copy=True) fwd_py = convert_forward_solution(fwd, surf_ori, copy=True) for key in ["nchan", "source_nn", "source_rr", "source_ori", "surf_ori", "coord_frame", "nsource"]: print(key) assert_allclose(fwd_py[key], fwd[key], rtol=1e-4, atol=1e-7) assert_allclose(fwd_py["mri_head_t"]["trans"], fwd["mri_head_t"]["trans"], rtol=1e-5, atol=1e-8) assert_equal(fwd_py["sol"]["data"].shape, (n_sensors, n_src)) assert_equal(len(fwd["sol"]["row_names"]), n_sensors) assert_equal(len(fwd_py["sol"]["row_names"]), n_sensors) # check MEG print("check MEG") assert_allclose(fwd["sol"]["data"][:306], fwd_py["sol"]["data"][:306], rtol=meg_rtol, atol=meg_atol) # check EEG if fwd["sol"]["data"].shape[0] > 306: print("check EEG") assert_allclose(fwd["sol"]["data"][306:], fwd_py["sol"]["data"][306:], rtol=1e-3, atol=1e-3)
def test_convert_forward(): """Test converting forward solution between different representations """ fwd = read_forward_solution(fname_meeg_grad) fwd_repr = repr(fwd) assert_true('306' in fwd_repr) assert_true('60' in fwd_repr) assert_true(fwd_repr) assert_true(isinstance(fwd, Forward)) # look at surface orientation fwd_surf = convert_forward_solution(fwd, surf_ori=True) # go back fwd_new = convert_forward_solution(fwd_surf, surf_ori=False) assert_true(repr(fwd_new)) assert_true(isinstance(fwd_new, Forward)) compare_forwards(fwd, fwd_new) del fwd_new gc.collect() # now go to fixed fwd_fixed = convert_forward_solution(fwd_surf, surf_ori=True, force_fixed=True, use_cps=False) del fwd_surf gc.collect() assert_true(repr(fwd_fixed)) assert_true(isinstance(fwd_fixed, Forward)) assert_true(is_fixed_orient(fwd_fixed)) # now go back to cartesian (original condition) fwd_new = convert_forward_solution(fwd_fixed, surf_ori=False, force_fixed=False) assert_true(repr(fwd_new)) assert_true(isinstance(fwd_new, Forward)) compare_forwards(fwd, fwd_new) del fwd, fwd_new, fwd_fixed gc.collect()
def _compare_forwards(fwd, fwd_py, n_sensors, n_src, meg_rtol=1e-4, meg_atol=1e-9, eeg_rtol=1e-3, eeg_atol=1e-3): """Helper to test forwards""" # check source spaces assert_equal(len(fwd['src']), len(fwd_py['src'])) _compare_source_spaces(fwd['src'], fwd_py['src'], mode='approx') for surf_ori in [False, True]: if surf_ori: # use copy here to leave our originals unmodified fwd = convert_forward_solution(fwd, surf_ori, copy=True) fwd_py = convert_forward_solution(fwd, surf_ori, copy=True) for key in ['nchan', 'source_nn', 'source_rr', 'source_ori', 'surf_ori', 'coord_frame', 'nsource']: print(key) assert_allclose(fwd_py[key], fwd[key], rtol=1e-4, atol=1e-7) assert_allclose(fwd_py['mri_head_t']['trans'], fwd['mri_head_t']['trans'], rtol=1e-5, atol=1e-8) assert_equal(fwd_py['sol']['data'].shape, (n_sensors, n_src)) assert_equal(len(fwd['sol']['row_names']), n_sensors) assert_equal(len(fwd_py['sol']['row_names']), n_sensors) # check MEG assert_allclose(fwd['sol']['data'][:306], fwd_py['sol']['data'][:306], rtol=meg_rtol, atol=meg_atol, err_msg='MEG mismatch') # check EEG if fwd['sol']['data'].shape[0] > 306: assert_allclose(fwd['sol']['data'][306:], fwd_py['sol']['data'][306:], rtol=eeg_rtol, atol=eeg_atol, err_msg='EEG mismatch')
def test_convert_forward(): """Test converting forward solution between different representations """ fwd = read_forward_solution(fname_meeg) print(fwd) # __repr__ assert_true(isinstance(fwd, Forward)) # look at surface orientation fwd_surf = convert_forward_solution(fwd, surf_ori=True) fwd_surf_io = read_forward_solution(fname_meeg, surf_ori=True) compare_forwards(fwd_surf, fwd_surf_io) # go back fwd_new = convert_forward_solution(fwd_surf, surf_ori=False) print(fwd_new) assert_true(isinstance(fwd, Forward)) compare_forwards(fwd, fwd_new) # now go to fixed fwd_fixed = convert_forward_solution(fwd_surf, surf_ori=False, force_fixed=True) print(fwd_fixed) assert_true(isinstance(fwd_fixed, Forward)) fwd_fixed_io = read_forward_solution(fname_meeg, surf_ori=False, force_fixed=True) compare_forwards(fwd_fixed, fwd_fixed_io) # now go back to cartesian (original condition) fwd_new = convert_forward_solution(fwd_fixed) print(fwd_new) assert_true(isinstance(fwd_new, Forward)) compare_forwards(fwd, fwd_new)
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_restrict_forward_to_stc(): """Test restriction of source space to source SourceEstimate """ start = 0 stop = 5 n_times = stop - start - 1 sfreq = 10.0 t_start = 0.123 fwd = read_forward_solution(fname_meeg) fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=True, use_cps=True) fwd = pick_types_forward(fwd, meg=True) vertno = [fwd['src'][0]['vertno'][0:15], fwd['src'][1]['vertno'][0:5]] stc_data = np.ones((len(vertno[0]) + len(vertno[1]), n_times)) stc = SourceEstimate(stc_data, vertno, tmin=t_start, tstep=1.0 / sfreq) fwd_out = restrict_forward_to_stc(fwd, stc) assert_true(isinstance(fwd_out, Forward)) assert_equal(fwd_out['sol']['ncol'], 20) assert_equal(fwd_out['src'][0]['nuse'], 15) assert_equal(fwd_out['src'][1]['nuse'], 5) assert_equal(fwd_out['src'][0]['vertno'], fwd['src'][0]['vertno'][0:15]) assert_equal(fwd_out['src'][1]['vertno'], fwd['src'][1]['vertno'][0:5]) fwd = read_forward_solution(fname_meeg) fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=False) fwd = pick_types_forward(fwd, meg=True) vertno = [fwd['src'][0]['vertno'][0:15], fwd['src'][1]['vertno'][0:5]] stc_data = np.ones((len(vertno[0]) + len(vertno[1]), n_times)) stc = SourceEstimate(stc_data, vertno, tmin=t_start, tstep=1.0 / sfreq) fwd_out = restrict_forward_to_stc(fwd, stc) assert_equal(fwd_out['sol']['ncol'], 60) assert_equal(fwd_out['src'][0]['nuse'], 15) assert_equal(fwd_out['src'][1]['nuse'], 5) assert_equal(fwd_out['src'][0]['vertno'], fwd['src'][0]['vertno'][0:15]) assert_equal(fwd_out['src'][1]['vertno'], fwd['src'][1]['vertno'][0:5]) # Test saving the restricted forward object. This only works if all fields # are properly accounted for. temp_dir = _TempDir() fname_copy = op.join(temp_dir, 'copy-fwd.fif') with warnings.catch_warnings(record=True): warnings.simplefilter('always') write_forward_solution(fname_copy, fwd_out, overwrite=True) fwd_out_read = read_forward_solution(fname_copy) fwd_out_read = convert_forward_solution(fwd_out_read, surf_ori=True, force_fixed=False) compare_forwards(fwd_out, fwd_out_read)
def test_inverse_operator_channel_ordering(): """Test MNE inverse computation is immune to channel reorderings """ # These are with original ordering evoked = _get_evoked() noise_cov = read_cov(fname_cov) fwd_orig = make_forward_solution(evoked.info, fname_trans, src_fname, fname_bem, eeg=True, mindist=5.0) fwd_orig = convert_forward_solution(fwd_orig, surf_ori=True) inv_orig = make_inverse_operator(evoked.info, fwd_orig, noise_cov, loose=0.2, depth=0.8, limit_depth_chs=False) stc_1 = apply_inverse(evoked, inv_orig, lambda2, "dSPM") # Assume that a raw reordering applies to both evoked and noise_cov, # so we don't need to create those from scratch. Just reorder them, # then try to apply the original inverse operator new_order = np.arange(len(evoked.info['ch_names'])) randomiser = np.random.RandomState(42) randomiser.shuffle(new_order) evoked.data = evoked.data[new_order] evoked.info['chs'] = [evoked.info['chs'][n] for n in new_order] evoked.info._update_redundant() evoked.info._check_consistency() cov_ch_reorder = [c for c in evoked.info['ch_names'] if (c in noise_cov.ch_names)] new_order_cov = [noise_cov.ch_names.index(name) for name in cov_ch_reorder] noise_cov['data'] = noise_cov.data[np.ix_(new_order_cov, new_order_cov)] noise_cov['names'] = [noise_cov['names'][idx] for idx in new_order_cov] fwd_reorder = make_forward_solution(evoked.info, fname_trans, src_fname, fname_bem, eeg=True, mindist=5.0) fwd_reorder = convert_forward_solution(fwd_reorder, surf_ori=True) inv_reorder = make_inverse_operator(evoked.info, fwd_reorder, noise_cov, loose=0.2, depth=0.8, limit_depth_chs=False) stc_2 = apply_inverse(evoked, inv_reorder, lambda2, "dSPM") assert_equal(stc_1.subject, stc_2.subject) assert_array_equal(stc_1.times, stc_2.times) assert_allclose(stc_1.data, stc_2.data, rtol=1e-5, atol=1e-5) assert_true(inv_orig['units'] == inv_reorder['units']) # Reload with original ordering & apply reordered inverse evoked = _get_evoked() noise_cov = read_cov(fname_cov) stc_3 = apply_inverse(evoked, inv_reorder, lambda2, "dSPM") assert_allclose(stc_1.data, stc_3.data, rtol=1e-5, atol=1e-5)
def _load_forward(): """Load forward models.""" fwd_free = mne.read_forward_solution(fname_fwd) fwd_free = mne.pick_types_forward(fwd_free, meg=True, eeg=False) fwd_free = mne.convert_forward_solution(fwd_free, surf_ori=False) fwd_surf = mne.convert_forward_solution(fwd_free, surf_ori=True, use_cps=False) fwd_fixed = mne.convert_forward_solution(fwd_free, force_fixed=True, use_cps=False) fwd_vol = mne.read_forward_solution(fname_fwd_vol) label = mne.read_label(fname_label) return fwd_free, fwd_surf, fwd_fixed, fwd_vol, label
def test_make_inverse_operator(): """Test MNE inverse computation (precomputed and non-precomputed).""" # Test old version of inverse computation starting from forward operator evoked = _get_evoked() noise_cov = read_cov(fname_cov) inverse_operator = read_inverse_operator(fname_inv) fwd_op = convert_forward_solution(read_forward_solution_meg(fname_fwd), surf_ori=True, copy=False) with catch_logging() as log: my_inv_op = make_inverse_operator(evoked.info, fwd_op, noise_cov, loose=0.2, depth=0.8, limit_depth_chs=False, verbose=True) log = log.getvalue() assert 'rank 302 (3 small eigenvalues omitted)' in log _compare_io(my_inv_op) assert_equal(inverse_operator['units'], 'Am') _compare_inverses_approx(my_inv_op, inverse_operator, evoked, rtol=1e-2, atol=1e-5, depth_atol=1e-3) # Test MNE inverse computation starting from forward operator with catch_logging() as log: my_inv_op = make_inverse_operator(evoked.info, fwd_op, noise_cov, loose=0.2, depth=0.8, verbose=True) log = log.getvalue() assert 'rank 302 (3 small eigenvalues omitted)' in log _compare_io(my_inv_op) _compare_inverses_approx(my_inv_op, inverse_operator, evoked, rtol=1e-3, atol=1e-5) assert ('dev_head_t' in my_inv_op['info']) assert ('mri_head_t' in my_inv_op)
def test_simulate_round_trip(): """Test simulate_raw round trip calculations.""" # Check a diagonal round-trip raw, src, stc, trans, sphere = _get_data() raw.pick_types(meg=True, stim=True) bem = read_bem_solution(bem_1_fname) old_bem = bem.copy() old_src = src.copy() old_trans = trans.copy() fwd = make_forward_solution(raw.info, trans, src, bem) # no omissions assert (sum(len(s['vertno']) for s in src) == sum(len(s['vertno']) for s in fwd['src']) == 36) # make sure things were not modified assert (old_bem['surfs'][0]['coord_frame'] == bem['surfs'][0]['coord_frame']) assert trans == old_trans _compare_source_spaces(src, old_src) data = np.eye(fwd['nsource']) raw.crop(0, (len(data) - 1) / raw.info['sfreq']) stc = SourceEstimate(data, [s['vertno'] for s in fwd['src']], 0, 1. / raw.info['sfreq']) for use_cps in (False, True): this_raw = simulate_raw(raw, stc, trans, src, bem, cov=None, use_cps=use_cps) this_raw.pick_types(meg=True, eeg=True) assert (old_bem['surfs'][0]['coord_frame'] == bem['surfs'][0]['coord_frame']) assert trans == old_trans _compare_source_spaces(src, old_src) this_fwd = convert_forward_solution(fwd, force_fixed=True, use_cps=use_cps) assert_allclose(this_raw[:][0], this_fwd['sol']['data'], atol=1e-12, rtol=1e-6)
def _get_fwd_labels(): fwd = read_forward_solution(fname_fwd) fwd = convert_forward_solution(fwd, force_fixed=True, use_cps=True) fwd = pick_types_forward(fwd, meg=True, eeg=False) labels = [read_label(op.join(data_path, 'MEG', 'sample', 'labels', '%s.label' % label)) for label in label_names] return fwd, labels
def run_forward(subject_id): subject = "sub%03d" % subject_id print("processing subject: %s" % subject) data_path = op.join(meg_dir, subject) fname_ave = op.join(data_path, '%s-ave.fif' % subject) fname_fwd = op.join(data_path, '%s-meg-%s-fwd.fif' % (subject, spacing)) fname_trans = op.join(study_path, 'ds117', subject, 'MEG', '%s-trans.fif' % subject) src = mne.setup_source_space(subject, spacing=spacing, subjects_dir=subjects_dir, overwrite=True, n_jobs=1, add_dist=False) src_fname = op.join(subjects_dir, subject, '%s-src.fif' % spacing) mne.write_source_spaces(src_fname, src) bem_model = mne.make_bem_model(subject, ico=4, subjects_dir=subjects_dir, conductivity=(0.3,)) bem = mne.make_bem_solution(bem_model) info = mne.read_evokeds(fname_ave, condition=0).info fwd = mne.make_forward_solution(info, trans=fname_trans, src=src, bem=bem, fname=None, meg=True, eeg=False, mindist=mindist, n_jobs=1, overwrite=True) fwd = mne.convert_forward_solution(fwd, surf_ori=True) mne.write_forward_solution(fname_fwd, fwd, overwrite=True)
def test_make_inverse_operator_loose(evoked): """Test MNE inverse computation (precomputed and non-precomputed).""" # Test old version of inverse computation starting from forward operator noise_cov = read_cov(fname_cov) inverse_operator = read_inverse_operator(fname_inv) fwd_op = convert_forward_solution(read_forward_solution_meg(fname_fwd), surf_ori=True, copy=False) with catch_logging() as log: with pytest.deprecated_call(): # limit_depth_chs my_inv_op = make_inverse_operator( evoked.info, fwd_op, noise_cov, loose=0.2, depth=0.8, limit_depth_chs=False, verbose=True) log = log.getvalue() assert 'MEG: rank 302 computed' in log assert 'limit = 1/%d' % fwd_op['nsource'] in log _compare_io(my_inv_op) assert_equal(inverse_operator['units'], 'Am') _compare_inverses_approx(my_inv_op, inverse_operator, evoked, rtol=1e-2, atol=1e-5, depth_atol=1e-3) # Test MNE inverse computation starting from forward operator with catch_logging() as log: my_inv_op = make_inverse_operator(evoked.info, fwd_op, noise_cov, loose='auto', depth=0.8, fixed=False, verbose=True) log = log.getvalue() assert 'MEG: rank 302 computed from 305' in log _compare_io(my_inv_op) _compare_inverses_approx(my_inv_op, inverse_operator, evoked, rtol=1e-3, atol=1e-5) assert ('dev_head_t' in my_inv_op['info']) assert ('mri_head_t' in my_inv_op)
def test_gamma_map(): """Test Gamma MAP inverse""" forward = read_forward_solution(fname_fwd) forward = convert_forward_solution(forward, surf_ori=True) forward = pick_types_forward(forward, meg=False, eeg=True) 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) alpha = 0.5 stc = gamma_map(evoked, forward, cov, alpha, tol=1e-4, xyz_same_gamma=True, update_mode=1) _check_stc(stc, evoked, 68477) stc = gamma_map(evoked, forward, cov, alpha, tol=1e-4, xyz_same_gamma=False, update_mode=1) _check_stc(stc, evoked, 82010) dips = gamma_map(evoked, forward, cov, alpha, tol=1e-4, xyz_same_gamma=False, update_mode=1, return_as_dipoles=True) assert_true(isinstance(dips[0], Dipole)) stc_dip = make_stc_from_dipoles(dips, forward['src']) _check_stcs(stc, stc_dip) # force fixed orientation stc = gamma_map(evoked, forward, cov, alpha, tol=1e-4, xyz_same_gamma=False, update_mode=2, loose=0, return_residual=False) _check_stc(stc, evoked, 85739, 20)
def apply_inverse(fnevo, method='dSPM', snr=3.0, event='LLst', baseline=False, btmin=-0.3, btmax=-0.1, min_subject='fsaverage'): ''' Parameter --------- fnevo: string or list The evoked file with ECG, EOG and environmental noise free. method: inverse method, 'MNE' or 'dSPM' event: string The event name related with epochs. min_subject: string The subject name as the common brain. snr: signal to noise ratio for inverse solution. ''' #Get the default subjects_dir from mne.minimum_norm import apply_inverse fnlist = get_files_from_list(fnevo) # loop across all filenames for fname in fnlist: fn_path = os.path.split(fname)[0] name = os.path.basename(fname) stc_name = name[:name.rfind('-ave.fif')] subject = name.split('_')[0] subject_path = subjects_dir + '/%s' %subject min_dir = subjects_dir + '/%s' %min_subject fn_trans = fn_path + '/%s-trans.fif' % subject fn_cov = fn_path + '/%s_empty,nr-cov.fif' % subject fn_src = subject_path + '/bem/%s-ico-5-src.fif' % subject fn_bem = subject_path + '/bem/%s-5120-5120-5120-bem-sol.fif' % subject snr = snr lambda2 = 1.0 / snr ** 2 #noise_cov = mne.read_cov(fn_cov) [evoked] = mne.read_evokeds(fname) noise_cov = mne.read_cov(fn_cov) # this path used for ROI definition stc_path = min_dir + '/%s_ROIs/%s' %(method,subject) #fn_cov = meg_path + '/%s_empty,fibp1-45,nr-cov.fif' % subject set_directory(stc_path) noise_cov = mne.cov.regularize(noise_cov, evoked.info, mag=0.05, grad=0.05, proj=True) fwd_ev = mne.make_forward_solution(evoked.info, trans=fn_trans, src=fn_src, bem=fn_bem, fname=None, meg=True, eeg=False, mindist=5.0, n_jobs=2, overwrite=True) fwd_ev = mne.convert_forward_solution(fwd_ev, surf_ori=True) forward_meg_ev = mne.pick_types_forward(fwd_ev, meg=True, eeg=False) inverse_operator_ev = mne.minimum_norm.make_inverse_operator( evoked.info, forward_meg_ev, noise_cov, loose=0.2, depth=0.8) # Compute inverse solution stc = apply_inverse(evoked, inverse_operator_ev, lambda2, method, pick_ori=None) # Morph STC stc_morph = mne.morph_data(subject, min_subject, stc, grade=5, smooth=5) stc_morph.save(stc_path + '/%s' % (stc_name), ftype='stc') if baseline == True: stc_base = stc_morph.crop(btmin, btmax) stc_base.save(stc_path + '/%s_%s_baseline' % (subject, event), ftype='stc')
def test_simulate_round_trip(raw_data): """Test simulate_raw round trip calculations.""" # Check a diagonal round-trip raw, src, stc, trans, sphere = raw_data raw.pick_types(meg=True, stim=True) bem = read_bem_solution(bem_1_fname) old_bem = bem.copy() old_src = src.copy() old_trans = trans.copy() fwd = make_forward_solution(raw.info, trans, src, bem) # no omissions assert (sum(len(s['vertno']) for s in src) == sum(len(s['vertno']) for s in fwd['src']) == 36) # make sure things were not modified assert (old_bem['surfs'][0]['coord_frame'] == bem['surfs'][0]['coord_frame']) assert trans == old_trans _compare_source_spaces(src, old_src) data = np.eye(fwd['nsource']) raw.crop(0, (len(data) - 1) / raw.info['sfreq']) stc = SourceEstimate(data, [s['vertno'] for s in fwd['src']], 0, 1. / raw.info['sfreq']) for use_fwd in (None, fwd): if use_fwd is None: use_trans, use_src, use_bem = trans, src, bem else: use_trans = use_src = use_bem = None with pytest.deprecated_call(): this_raw = simulate_raw(raw, stc, use_trans, use_src, use_bem, cov=None, forward=use_fwd) this_raw.pick_types(meg=True, eeg=True) assert (old_bem['surfs'][0]['coord_frame'] == bem['surfs'][0]['coord_frame']) assert trans == old_trans _compare_source_spaces(src, old_src) this_fwd = convert_forward_solution(fwd, force_fixed=True) assert_allclose(this_raw[:][0], this_fwd['sol']['data'], atol=1e-12, rtol=1e-6) with pytest.raises(ValueError, match='If forward is not None then'): simulate_raw(raw.info, stc, trans, src, bem, forward=fwd) # Not iterable with pytest.raises(TypeError, match='SourceEstimate, tuple, or iterable'): simulate_raw(raw.info, 0., trans, src, bem, None) # STC with a source that `src` does not have assert 0 not in src[0]['vertno'] vertices = [[0, fwd['src'][0]['vertno'][0]], []] stc_bad = SourceEstimate(data[:2], vertices, 0, 1. / raw.info['sfreq']) with pytest.warns(RuntimeWarning, match='1 of 2 SourceEstimate vertices'): simulate_raw(raw.info, stc_bad, trans, src, bem) assert 0 not in fwd['src'][0]['vertno'] with pytest.warns(RuntimeWarning, match='1 of 2 SourceEstimate vertices'): simulate_raw(raw.info, stc_bad, None, None, None, forward=fwd) # dev_head_t mismatch fwd['info']['dev_head_t']['trans'][0, 0] = 1. with pytest.raises(ValueError, match='dev_head_t.*does not match'): simulate_raw(raw.info, stc, None, None, None, forward=fwd)
def test_make_inverse_operator_fixed(): """Test MNE inverse computation (fixed orientation).""" fwd = read_forward_solution_meg(fname_fwd) evoked = _get_evoked() noise_cov = read_cov(fname_cov) # can't make fixed inv with depth weighting without free ori fwd fwd_fixed = convert_forward_solution(fwd, force_fixed=True, use_cps=True) pytest.raises(ValueError, make_inverse_operator, evoked.info, fwd_fixed, noise_cov, depth=0.8, fixed=True) # now compare to C solution # note that the forward solution must not be surface-oriented # to get equivalency (surf_ori=True changes the normals) with catch_logging() as log: inv_op = make_inverse_operator( # test depth=0. alias for depth=None evoked.info, fwd, noise_cov, depth=0., fixed=True, use_cps=False, verbose=True) log = log.getvalue() assert 'rank 302 (3 small eigenvalues omitted)' in log assert 'EEG channels: 0' in repr(inv_op) assert 'MEG channels: 305' in repr(inv_op) del fwd_fixed inverse_operator_nodepth = read_inverse_operator(fname_inv_fixed_nodepth) # XXX We should have this but we don't (MNE-C doesn't restrict info): # assert 'EEG channels: 0' in repr(inverse_operator_nodepth) assert 'MEG channels: 305' in repr(inverse_operator_nodepth) _compare_inverses_approx(inverse_operator_nodepth, inv_op, evoked, rtol=1e-5, atol=1e-4) # Inverse has 306 channels - 6 proj = 302 assert (compute_rank_inverse(inverse_operator_nodepth) == 302) # Now with depth fwd_surf = convert_forward_solution(fwd, surf_ori=True) # not fixed for kwargs, use_fwd in zip([dict(fixed=True), dict(loose=0.)], [fwd, fwd_surf]): # Should be equiv. inv_op_depth = make_inverse_operator( evoked.info, use_fwd, noise_cov, depth=0.8, use_cps=True, **kwargs) inverse_operator_depth = read_inverse_operator(fname_inv_fixed_depth) # Normals should be the adjusted ones assert_allclose(inverse_operator_depth['source_nn'], fwd_surf['source_nn'][2::3], atol=1e-5) _compare_inverses_approx(inverse_operator_depth, inv_op_depth, evoked, rtol=1e-3, atol=1e-4)
def test_warn_inverse_operator(evoked, noise_cov): """Test MNE inverse warning without average EEG projection.""" bad_info = evoked.info bad_info['projs'] = list() fwd_op = convert_forward_solution(read_forward_solution(fname_fwd), surf_ori=True, copy=False) noise_cov['projs'].pop(-1) # get rid of avg EEG ref proj with pytest.warns(RuntimeWarning, match='reference'): make_inverse_operator(bad_info, fwd_op, noise_cov)
def test_make_inverse_operator_free(evoked, noise_cov): """Test MNE inverse computation (free orientation).""" fwd = read_forward_solution_meg(fname_fwd) fwd_surf = convert_forward_solution(fwd, surf_ori=True) fwd_fixed = convert_forward_solution(fwd, force_fixed=True, use_cps=True) # can't make free inv with fixed fwd pytest.raises(ValueError, make_inverse_operator, evoked.info, fwd_fixed, noise_cov, depth=None) # for depth=None, surf_ori of the fwd should not matter inv_3 = make_inverse_operator(evoked.info, fwd_surf, noise_cov, depth=None, loose=1.) inv_4 = make_inverse_operator(evoked.info, fwd, noise_cov, depth=None, loose=1.) _compare_inverses_approx(inv_3, inv_4, evoked, rtol=1e-5, atol=1e-8, check_nn=False, check_K=False)
def _compare_forwards(fwd, fwd_py, n_sensors, n_src, meg_rtol=1e-4, meg_atol=1e-9, eeg_rtol=1e-3, eeg_atol=1e-3): """Test forwards.""" # check source spaces assert_equal(len(fwd['src']), len(fwd_py['src'])) _compare_source_spaces(fwd['src'], fwd_py['src'], mode='approx') for surf_ori, force_fixed in product([False, True], [False, True]): # use copy here to leave our originals unmodified fwd = convert_forward_solution(fwd, surf_ori, force_fixed, copy=True, use_cps=True) fwd_py = convert_forward_solution(fwd_py, surf_ori, force_fixed, copy=True, use_cps=True) check_src = n_src // 3 if force_fixed else n_src for key in ('nchan', 'source_rr', 'source_ori', 'surf_ori', 'coord_frame', 'nsource'): assert_allclose(fwd_py[key], fwd[key], rtol=1e-4, atol=1e-7, err_msg=key) # In surf_ori=True only Z matters for source_nn if surf_ori and not force_fixed: ori_sl = slice(2, None, 3) else: ori_sl = slice(None) assert_allclose(fwd_py['source_nn'][ori_sl], fwd['source_nn'][ori_sl], rtol=1e-4, atol=1e-6) assert_allclose(fwd_py['mri_head_t']['trans'], fwd['mri_head_t']['trans'], rtol=1e-5, atol=1e-8) assert_equal(fwd_py['sol']['data'].shape, (n_sensors, check_src)) assert_equal(len(fwd['sol']['row_names']), n_sensors) assert_equal(len(fwd_py['sol']['row_names']), n_sensors) # check MEG assert_allclose(fwd['sol']['data'][:306, ori_sl], fwd_py['sol']['data'][:306, ori_sl], rtol=meg_rtol, atol=meg_atol, err_msg='MEG mismatch') # check EEG if fwd['sol']['data'].shape[0] > 306: assert_allclose(fwd['sol']['data'][306:, ori_sl], fwd_py['sol']['data'][306:, ori_sl], rtol=eeg_rtol, atol=eeg_atol, err_msg='EEG mismatch')
def test_simulate_evoked(): """Test simulation of evoked data.""" raw = read_raw_fif(raw_fname) fwd = read_forward_solution(fwd_fname) fwd = convert_forward_solution(fwd, force_fixed=True, use_cps=False) fwd = pick_types_forward(fwd, meg=True, eeg=True, exclude=raw.info['bads']) cov = read_cov(cov_fname) evoked_template = read_evokeds(ave_fname, condition=0, baseline=None) evoked_template.pick_types(meg=True, eeg=True, exclude=raw.info['bads']) cov = regularize(cov, evoked_template.info) nave = evoked_template.nave tmin = -0.1 sfreq = 1000. # Hz tstep = 1. / sfreq n_samples = 600 times = np.linspace(tmin, tmin + n_samples * tstep, n_samples) # Generate times series for 2 dipoles stc = simulate_sparse_stc(fwd['src'], n_dipoles=2, times=times, random_state=42) # Generate noisy evoked data iir_filter = [1, -0.9] evoked = simulate_evoked(fwd, stc, evoked_template.info, cov, iir_filter=iir_filter, nave=nave) assert_array_almost_equal(evoked.times, stc.times) assert_true(len(evoked.data) == len(fwd['sol']['data'])) assert_equal(evoked.nave, nave) # make a vertex that doesn't exist in fwd, should throw error stc_bad = stc.copy() mv = np.max(fwd['src'][0]['vertno'][fwd['src'][0]['inuse']]) stc_bad.vertices[0][0] = mv + 1 assert_raises(RuntimeError, simulate_evoked, fwd, stc_bad, evoked_template.info, cov) evoked_1 = simulate_evoked(fwd, stc, evoked_template.info, cov, nave=np.inf) evoked_2 = simulate_evoked(fwd, stc, evoked_template.info, cov, nave=np.inf) assert_array_equal(evoked_1.data, evoked_2.data) # Test the equivalence snr to nave with warnings.catch_warnings(record=True): # deprecation evoked = simulate_evoked(fwd, stc, evoked_template.info, cov, snr=6, random_state=42) assert_allclose(np.linalg.norm(evoked.data, ord='fro'), 0.00078346820226502716) cov['names'] = cov.ch_names[:-2] # Error channels are different. assert_raises(ValueError, simulate_evoked, fwd, stc, evoked_template.info, cov, nave=nave, iir_filter=None)
def forward_operator(fwd, src, subjects_dir=None, parc='aparc', name=None): """Load forward operator as :class:`NDVar` Parameters ---------- fwd : str | mne Forward MNE Forward solution, or path to forward solution. src : str Tag describing the source space (e.g., "ico-4"). subjects_dir : str Location of the MRI subjects directory. parc : str Parcellation to load (corresponding to existing annot files; default 'aparc'). name : str Name the NDVar (default is the filename if a path is provided, otherwise "fwd"). Returns ------- fwd : NDVar (sensor, source) NDVar containing the gain matrix. """ is_vol = src.startswith('vol') if isinstance(fwd, str): if name is None: name = os.path.basename(fwd) fwd = mne.read_forward_solution(fwd) mne.convert_forward_solution(fwd, force_fixed=not is_vol, use_cps=True, copy=False) elif name is None: name = 'fwd' sensor = sensor_dim(fwd['info']) assert np.all(sensor.names == fwd['sol']['row_names']) if is_vol: source = VolumeSourceSpace.from_mne_source_spaces(fwd['src'], src, subjects_dir, parc) x = fwd['sol']['data'].reshape(((len(sensor), len(source), 3))) dims = (sensor, source, Space('RAS')) else: source = SourceSpace.from_mne_source_spaces(fwd['src'], src, subjects_dir, parc) x = fwd['sol']['data'] dims = (sensor, source) return NDVar(x, dims, {}, name)
def _compare_forwards(fwd, fwd_py, n_sensors, n_src, meg_rtol=1e-4, meg_atol=1e-9, eeg_rtol=1e-3, eeg_atol=1e-3): """Helper to test forwards""" # check source spaces assert_equal(len(fwd["src"]), len(fwd_py["src"])) _compare_source_spaces(fwd["src"], fwd_py["src"], mode="approx") for surf_ori, force_fixed in product([False, True], [False, True]): # use copy here to leave our originals unmodified fwd = convert_forward_solution(fwd, surf_ori, force_fixed, copy=True) fwd_py = convert_forward_solution(fwd_py, surf_ori, force_fixed, copy=True) check_src = n_src // 3 if force_fixed else n_src for key in ("nchan", "source_rr", "source_ori", "surf_ori", "coord_frame", "nsource"): assert_allclose(fwd_py[key], fwd[key], rtol=1e-4, atol=1e-7, err_msg=key) # In surf_ori=True only Z matters for source_nn if surf_ori and not force_fixed: ori_sl = slice(2, None, 3) else: ori_sl = slice(None) assert_allclose(fwd_py["source_nn"][ori_sl], fwd["source_nn"][ori_sl], rtol=1e-4, atol=1e-6) assert_allclose(fwd_py["mri_head_t"]["trans"], fwd["mri_head_t"]["trans"], rtol=1e-5, atol=1e-8) assert_equal(fwd_py["sol"]["data"].shape, (n_sensors, check_src)) assert_equal(len(fwd["sol"]["row_names"]), n_sensors) assert_equal(len(fwd_py["sol"]["row_names"]), n_sensors) # check MEG assert_allclose( fwd["sol"]["data"][:306, ori_sl], fwd_py["sol"]["data"][:306, ori_sl], rtol=meg_rtol, atol=meg_atol, err_msg="MEG mismatch", ) # check EEG if fwd["sol"]["data"].shape[0] > 306: assert_allclose( fwd["sol"]["data"][306:, ori_sl], fwd_py["sol"]["data"][306:, ori_sl], rtol=eeg_rtol, atol=eeg_atol, err_msg="EEG mismatch", )
def test_warn_inverse_operator(): """Test MNE inverse warning without average EEG projection.""" bad_info = copy.deepcopy(_get_evoked().info) bad_info['projs'] = list() fwd_op = convert_forward_solution(read_forward_solution(fname_fwd), surf_ori=True, copy=False) noise_cov = read_cov(fname_cov) noise_cov['projs'].pop(-1) # get rid of avg EEG ref proj with warnings.catch_warnings(record=True) as w: make_inverse_operator(bad_info, fwd_op, noise_cov) assert_equal(len(w), 1)
def test_localization_bias_fixed(bias_params_fixed, method, lower, upper, depth): """Test inverse localization bias for fixed minimum-norm solvers.""" evoked, fwd, noise_cov, _, want = bias_params_fixed fwd_use = convert_forward_solution(fwd, force_fixed=False) inv_fixed = make_inverse_operator(evoked.info, fwd_use, noise_cov, loose=0., depth=depth) loc = np.abs(apply_inverse(evoked, inv_fixed, lambda2, method).data) # Compute the percentage of sources for which there is no loc bias: perc = (want == np.argmax(loc, axis=0)).mean() * 100 assert lower <= perc <= upper, method
def forward_pipeline(raw_fname, subject, fwd_fname=None, trans_fname=None, subjects_dir=None, overwrite=False, ignore_ref=True): import os.path as op from mne.utils import get_config if subjects_dir is None: subjects_dir = get_config('SUBJECTS_DIR') # Setup paths save_dir = raw_fname.split('/') save_dir = ('/'.join(save_dir[:-1]) if isinstance(save_dir, list) else save_dir) bem_dir = op.join(subjects_dir, subject, 'bem') bem_sol_fname = op.join(subjects_dir, subject, 'bem', subject + '-5120-bem-sol.fif') oct_fname = op.join(subjects_dir, subject, 'bem', subject + '-oct-6-src.fif') src_fname = op.join(bem_dir, subject + '-oct-6-src.fif') bem_sol_fname = op.join(bem_dir, subject + '-5120-bem-sol.fif') if trans_fname is None: trans_fname = op.join(save_dir, subject + '-trans.fif') if fwd_fname is None: fwd_fname = op.join(save_dir, subject + '-meg-fwd.fif') # 0. Checks Freesurfer segmentation and compute watershed bem miss_anatomy = not op.isfile(src_fname) or not op.exists(bem_sol_fname) for fname in [bem_sol_fname, oct_fname]: if not op.isfile(op.join(subjects_dir, subject, 'bem', fname)): miss_anatomy = True if miss_anatomy: raise RuntimeError('Could not find BEM (%s, %s), relaunch ' 'pipeline_anatomy()' % (bem_sol_fname, oct_fname)) # 1. Manual coregisteration head markers with coils if not op.isfile(trans_fname): raise RuntimeError('Could not find trans (%s), launch' 'coregistration.' % trans_fname) # 2. Forward solution if overwrite or not op.isfile(fwd_fname): from mne import (make_forward_solution, convert_forward_solution, write_forward_solution) fwd = make_forward_solution( info=raw_fname, trans=trans_fname, src=oct_fname, bem=bem_sol_fname, fname=None, meg=True, eeg=False, mindist=5.0, overwrite=True, ignore_ref=ignore_ref) # Convert to surface orientation for better visualization fwd = convert_forward_solution(fwd, surf_ori=True) # save write_forward_solution(fwd_fname, fwd, overwrite=True) return
def test_localization_bias_loose(bias_params_fixed, method, lower, upper, depth): """Test inverse localization bias for loose minimum-norm solvers.""" evoked, fwd, noise_cov, _, want = bias_params_fixed fwd = convert_forward_solution(fwd, surf_ori=False, force_fixed=False) assert not is_fixed_orient(fwd) inv_loose = make_inverse_operator(evoked.info, fwd, noise_cov, loose=0.2, depth=depth) loc = apply_inverse(evoked, inv_loose, lambda2, method).data assert (loc >= 0).all() # Compute the percentage of sources for which there is no loc bias: perc = (want == np.argmax(loc, axis=0)).mean() * 100 assert lower <= perc <= upper, method
def test_simulate_evoked(): """Test simulation of evoked data.""" raw = read_raw_fif(raw_fname) fwd = read_forward_solution(fwd_fname) fwd = convert_forward_solution(fwd, force_fixed=True, use_cps=False) fwd = pick_types_forward(fwd, meg=True, eeg=True, exclude=raw.info['bads']) cov = read_cov(cov_fname) evoked_template = read_evokeds(ave_fname, condition=0, baseline=None) evoked_template.pick_types(meg=True, eeg=True, exclude=raw.info['bads']) cov = regularize(cov, evoked_template.info) nave = evoked_template.nave tmin = -0.1 sfreq = 1000. # Hz tstep = 1. / sfreq n_samples = 600 times = np.linspace(tmin, tmin + n_samples * tstep, n_samples) # Generate times series for 2 dipoles stc = simulate_sparse_stc(fwd['src'], n_dipoles=2, times=times, random_state=42) # Generate noisy evoked data iir_filter = [1, -0.9] evoked = simulate_evoked(fwd, stc, evoked_template.info, cov, iir_filter=iir_filter, nave=nave) assert_array_almost_equal(evoked.times, stc.times) assert len(evoked.data) == len(fwd['sol']['data']) assert_equal(evoked.nave, nave) assert len(evoked.info['projs']) == len(cov['projs']) evoked_white = whiten_evoked(evoked, cov) assert abs(evoked_white.data[:, 0].std() - 1.) < 0.1 # make a vertex that doesn't exist in fwd, should throw error stc_bad = stc.copy() mv = np.max(fwd['src'][0]['vertno'][fwd['src'][0]['inuse']]) stc_bad.vertices[0][0] = mv + 1 pytest.raises(RuntimeError, simulate_evoked, fwd, stc_bad, evoked_template.info, cov) evoked_1 = simulate_evoked(fwd, stc, evoked_template.info, cov, nave=np.inf) evoked_2 = simulate_evoked(fwd, stc, evoked_template.info, cov, nave=np.inf) assert_array_equal(evoked_1.data, evoked_2.data) cov['names'] = cov.ch_names[:-2] # Error channels are different. with pytest.raises(RuntimeError, match='Not all channels present'): simulate_evoked(fwd, stc, evoked_template.info, cov)
def test_mxne_inverse(): """Test (TF-)MxNE inverse computation.""" # Read noise covariance matrix cov = read_cov(fname_cov) # Handling average file loose = 0.0 depth = 0.9 evoked = read_evokeds(fname_data, condition=0, baseline=(None, 0)) evoked.crop(tmin=-0.05, tmax=0.2) evoked_l21 = evoked.copy() evoked_l21.crop(tmin=0.081, tmax=0.1) label = read_label(fname_label) forward = read_forward_solution(fname_fwd) forward = convert_forward_solution(forward, surf_ori=True) # Reduce source space to make test computation faster inverse_operator = make_inverse_operator(evoked_l21.info, forward, cov, loose=loose, depth=depth, fixed=True, use_cps=True) stc_dspm = apply_inverse(evoked_l21, inverse_operator, lambda2=1. / 9., method='dSPM') stc_dspm.data[np.abs(stc_dspm.data) < 12] = 0.0 stc_dspm.data[np.abs(stc_dspm.data) >= 12] = 1. weights_min = 0.5 # MxNE tests alpha = 70 # spatial regularization parameter stc_prox = mixed_norm(evoked_l21, forward, cov, alpha, loose=loose, depth=depth, maxit=300, tol=1e-8, active_set_size=10, weights=stc_dspm, weights_min=weights_min, solver='prox') with pytest.warns(None): # CD stc_cd = mixed_norm(evoked_l21, forward, cov, alpha, loose=loose, depth=depth, maxit=300, tol=1e-8, active_set_size=10, weights=stc_dspm, weights_min=weights_min, solver='cd') stc_bcd = mixed_norm(evoked_l21, forward, cov, alpha, loose=loose, depth=depth, maxit=300, tol=1e-8, active_set_size=10, weights=stc_dspm, weights_min=weights_min, solver='bcd') assert_array_almost_equal(stc_prox.times, evoked_l21.times, 5) assert_array_almost_equal(stc_cd.times, evoked_l21.times, 5) assert_array_almost_equal(stc_bcd.times, evoked_l21.times, 5) assert_allclose(stc_prox.data, stc_cd.data, rtol=1e-3, atol=0.0) assert_allclose(stc_prox.data, stc_bcd.data, rtol=1e-3, atol=0.0) assert_allclose(stc_cd.data, stc_bcd.data, rtol=1e-3, atol=0.0) assert stc_prox.vertices[1][0] in label.vertices assert stc_cd.vertices[1][0] in label.vertices assert stc_bcd.vertices[1][0] in label.vertices with pytest.warns(None): # CD dips = mixed_norm(evoked_l21, forward, cov, alpha, loose=loose, depth=depth, maxit=300, tol=1e-8, active_set_size=10, weights=stc_dspm, weights_min=weights_min, solver='cd', return_as_dipoles=True) stc_dip = make_stc_from_dipoles(dips, forward['src']) assert isinstance(dips[0], Dipole) _check_stcs(stc_cd, stc_dip) with pytest.warns(None): # CD stc, _ = mixed_norm(evoked_l21, forward, cov, alpha, loose=loose, depth=depth, maxit=300, tol=1e-8, active_set_size=10, return_residual=True, solver='cd') assert_array_almost_equal(stc.times, evoked_l21.times, 5) assert stc.vertices[1][0] in label.vertices # irMxNE tests with pytest.warns(None): # CD stc = mixed_norm(evoked_l21, forward, cov, alpha, n_mxne_iter=5, loose=loose, depth=depth, maxit=300, tol=1e-8, active_set_size=10, solver='cd') assert_array_almost_equal(stc.times, evoked_l21.times, 5) assert stc.vertices[1][0] in label.vertices assert stc.vertices == [[63152], [79017]] # 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, forward, cov, loose=loose, depth=depth, maxit=100, tol=1e-4, tstep=4, wsize=16, window=0.1, weights=stc_dspm, weights_min=weights_min, return_residual=True, alpha=alpha, l1_ratio=l1_ratio) assert_array_almost_equal(stc.times, evoked.times, 5) assert stc.vertices[1][0] in label.vertices pytest.raises(ValueError, tf_mixed_norm, evoked, forward, cov, alpha=101, l1_ratio=0.03) pytest.raises(ValueError, tf_mixed_norm, evoked, forward, cov, alpha=50., l1_ratio=1.01)
def test_inverse_operator_channel_ordering(evoked, noise_cov): """Test MNE inverse computation is immune to channel reorderings.""" # These are with original ordering evoked_orig = evoked.copy() fwd_orig = make_forward_solution(evoked.info, fname_trans, src_fname, fname_bem, eeg=True, mindist=5.0) fwd_orig = convert_forward_solution(fwd_orig, surf_ori=True) depth = dict(exp=0.8, limit_depth_chs=False) with catch_logging() as log: inv_orig = make_inverse_operator(evoked.info, fwd_orig, noise_cov, loose=0.2, depth=depth, verbose=True) log = log.getvalue() assert 'limit = 1/%s' % fwd_orig['nsource'] in log stc_1 = apply_inverse(evoked, inv_orig, lambda2, "dSPM") # Assume that a raw reordering applies to both evoked and noise_cov, # so we don't need to create those from scratch. Just reorder them, # then try to apply the original inverse operator new_order = np.arange(len(evoked.info['ch_names'])) randomiser = np.random.RandomState(42) randomiser.shuffle(new_order) evoked.data = evoked.data[new_order] evoked.info['chs'] = [evoked.info['chs'][n] for n in new_order] evoked.info._update_redundant() evoked.info._check_consistency() cov_ch_reorder = [ c for c in evoked.info['ch_names'] if (c in noise_cov.ch_names) ] new_order_cov = [noise_cov.ch_names.index(name) for name in cov_ch_reorder] noise_cov['data'] = noise_cov.data[np.ix_(new_order_cov, new_order_cov)] noise_cov['names'] = [noise_cov['names'][idx] for idx in new_order_cov] fwd_reorder = make_forward_solution(evoked.info, fname_trans, src_fname, fname_bem, eeg=True, mindist=5.0) fwd_reorder = convert_forward_solution(fwd_reorder, surf_ori=True) inv_reorder = make_inverse_operator(evoked.info, fwd_reorder, noise_cov, loose=0.2, depth=depth) stc_2 = apply_inverse(evoked, inv_reorder, lambda2, "dSPM") assert_equal(stc_1.subject, stc_2.subject) assert_array_equal(stc_1.times, stc_2.times) assert_allclose(stc_1.data, stc_2.data, rtol=1e-5, atol=1e-5) assert (inv_orig['units'] == inv_reorder['units']) # Reload with original ordering & apply reordered inverse evoked = evoked_orig noise_cov = read_cov(fname_cov) stc_3 = apply_inverse(evoked, inv_reorder, lambda2, "dSPM") assert_allclose(stc_1.data, stc_3.data, rtol=1e-5, atol=1e-5)
print('###\nWorking hard on %s.\n###' % (subject)) fname_stc = C.fname_STC(C, 'ResolutionMetrics', subject, '') # create output path if necessary if not os.path.exists(fname_stc): os.mkdir(fname_stc) fwd_fname = C.fname_ForwardSolution(C, subject, 'EEGMEG') print('###\nReading EEGMEG forward solutions: %s .\n###' % (fwd_fname)) fwd = mne.read_forward_solution(fwd_fname) fwd = mne.convert_forward_solution(fwd, surf_ori=True, force_fixed=True) # used vertex numbers, later assumed to be the same as for invop vertno_0 = fwd['src'][0]['vertno'] vertno_1 = fwd['src'][1]['vertno'] vertno = [vertno_0, vertno_1] # locations of used vertices in forward (and inverse) solution locations_0 = fwd['src'][0]['rr'][vertno_0, :] locations_1 = fwd['src'][1]['rr'][vertno_1, :] locations = np.vstack([locations_0, locations_1]) # covariance matrix (filter with wildcard) fname_cov = C.fname_cov(C, subject, st_duration, origin, C.res_cov_latwin, C.inv_cov_method, '*')
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) with warnings.catch_warnings(record=True): # semi-def cov evoked = generate_evoked(fwd, stc, evoked, 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)) assert_true((data_rms > resi_rms).all()) # 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], 'dists: %s' % dists) assert_true(corrs[0] <= corrs[1], 'corrs: %s' % corrs) assert_true(gc_dists[0] >= gc_dists[1], 'gc-dists (ori): %s' % gc_dists) assert_true(amp_errs[0] >= amp_errs[1], 'amplitude errors: %s' % amp_errs)
trans = op.join(study_path, 'source_stim', subj, 'source_files', 'orig', '%s_fid-trans.fif' % subj) epo_path = op.join(study_path, 'source_stim', subj, 'epochs', 'fif') conds = glob.glob(epo_path + '/*-epo.fif') cond_fname = conds[0] epochs = mne.read_epochs(cond_fname) epochs.interpolate_bads(reset_bads=True) epochs = epochs_fine_alignment(epochs) cond = epochs.info['description'] stim_coords = find_stim_coords(cond, subj, study_path) fwd = mne.read_forward_solution(fwd_fname) fwd1 = mne.convert_forward_solution(fwd, force_fixed=True) cov = mne.compute_covariance(epochs, method='shrunk', tmin=-0.5, tmax=-0.3) # use method='auto' for final computation evoked = epochs.average() info = evoked.info from nibabel.freesurfer.io import read_geometry fname_surf = op.join(subjects_dir, subj, 'surf', 'lh.pial') surf = read_geometry(fname_surf) def closest_nodes(node, all_nodes, used_nodes): nodes = np.asarray(all_nodes[used_nodes]) dist_2 = np.sum((nodes - node)**2, axis=1) used_vertnos = dist_2.argsort()[:1]
def _initialize(self): InverseModel._initialize(self) self.fwd = mne.convert_forward_solution( self.fwd, force_fixed=True, surf_ori=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
from mne.datasets import sample from mne.minimum_norm.resolution_matrix import make_inverse_resolution_matrix from mne.minimum_norm.spatial_resolution import resolution_metrics print(__doc__) data_path = sample.data_path() subjects_dir = data_path + '/subjects/' fname_fwd_emeg = data_path + '/MEG/sample/sample_audvis-meg-eeg-oct-6-fwd.fif' fname_cov = data_path + '/MEG/sample/sample_audvis-cov.fif' fname_evo = data_path + '/MEG/sample/sample_audvis-ave.fif' # read forward solution with EEG and MEG forward_emeg = mne.read_forward_solution(fname_fwd_emeg) # forward operator with fixed source orientations forward_emeg = mne.convert_forward_solution(forward_emeg, surf_ori=True, force_fixed=True) # create a forward solution with MEG only forward_meg = mne.pick_types_forward(forward_emeg, meg=True, eeg=False) # noise covariance matrix noise_cov = mne.read_cov(fname_cov) # evoked data for info evoked = mne.read_evokeds(fname_evo, 0) # make inverse operator from forward solution for MEG and EEGMEG inv_emeg = mne.minimum_norm.make_inverse_operator( info=evoked.info, forward=forward_emeg, noise_cov=noise_cov, loose=0., depth=None)
def test_resolution_matrix_lcmv(): """Test computation of resolution matrix for LCMV beamformers.""" # read forward solution forward = mne.read_forward_solution(fname_fwd) # remove bad channels forward = mne.pick_channels_forward(forward, exclude='bads') # forward operator with fixed source orientations forward_fxd = mne.convert_forward_solution(forward, surf_ori=True, force_fixed=True) # evoked info info = mne.io.read_info(fname_evoked) mne.pick_info(info, mne.pick_types(info, meg=True), copy=False) # good MEG # noise covariance matrix # ad-hoc to avoid discrepancies due to regularisation of real noise # covariance matrix noise_cov = mne.make_ad_hoc_cov(info) # Resolution matrix for Beamformer data_cov = noise_cov.copy() # to test a property of LCMV # compute beamformer filters # reg=0. to make sure noise_cov and data_cov are as similar as possible filters = make_lcmv(info, forward_fxd, data_cov, reg=0., noise_cov=noise_cov, pick_ori=None, rank=None, weight_norm=None, reduce_rank=False, verbose=False) # Compute resolution matrix for beamformer resmat_lcmv = make_lcmv_resolution_matrix(filters, forward_fxd, info) # for noise_cov==data_cov and whitening, the filter weights should be the # transpose of leadfield # create filters with transposed whitened leadfield as weights forward_fxd = mne.pick_channels_forward(forward_fxd, info['ch_names']) filters_lfd = deepcopy(filters) filters_lfd['weights'][:] = forward_fxd['sol']['data'].T # compute resolution matrix for filters with transposed leadfield resmat_fwd = make_lcmv_resolution_matrix(filters_lfd, forward_fxd, info) # pairwise correlation for rows (CTFs) of resolution matrices for whitened # LCMV beamformer and transposed leadfield should be 1 # Some rows are off by about 0.1 - not yet clear why corr = [] for (f, l) in zip(resmat_fwd, resmat_lcmv): corr.append(np.corrcoef(f, l)[0, 1]) # all row correlations should at least be above ~0.8 assert_allclose(corr, 1., atol=0.2) # Maximum row correlation should at least be close to 1 assert_allclose(np.max(corr), 1., atol=0.01)
def read_forward_solution_eeg(fname, **kwargs): """Read EEG forward.""" fwd = convert_forward_solution(read_forward_solution(fname), copy=False, **kwargs) fwd = pick_types_forward(fwd, meg=False, eeg=True) return fwd
data_path = sample.data_path() subjects_dir = op.join(data_path, 'subjects') fname_fwd = op.join(data_path, 'MEG', 'sample', 'sample_audvis-meg-oct-6-fwd.fif') fname_inv = op.join(data_path, 'MEG', 'sample', 'sample_audvis-meg-oct-6-meg-fixed-inv.fif') fname_evoked = op.join(data_path, 'MEG', 'sample', 'sample_audvis-ave.fif') ############################################################################### # Load the MEG data # ----------------- fwd = mne.read_forward_solution(fname_fwd) fwd = mne.convert_forward_solution(fwd, force_fixed=True, surf_ori=True, use_cps=False) fwd['info']['bads'] = [] inv_op = read_inverse_operator(fname_inv) raw = mne.io.read_raw_fif( op.join(data_path, 'MEG', 'sample', 'sample_audvis_raw.fif')) raw.set_eeg_reference(projection=True) events = mne.find_events(raw) event_id = {'Auditory/Left': 1, 'Auditory/Right': 2} epochs = mne.Epochs(raw, events, event_id, baseline=(None, 0), preload=True) epochs.info['bads'] = [] evoked = epochs.average() labels = mne.read_labels_from_annot('sample', subjects_dir=subjects_dir) label_names = [l.name for l in labels]
def test_lcmv_vector(): """Test vector LCMV solutions.""" info = mne.io.read_raw_fif(fname_raw).info # For speed and for rank-deficiency calculation simplicity, # just use grads info = mne.pick_info(info, mne.pick_types(info, meg='grad', exclude=())) info.update(bads=[], projs=[]) forward = mne.read_forward_solution(fname_fwd) forward = mne.pick_channels_forward(forward, info['ch_names']) vertices = [s['vertno'][::100] for s in forward['src']] n_vertices = sum(len(v) for v in vertices) assert 5 < n_vertices < 20 amplitude = 100e-9 stc = mne.SourceEstimate(amplitude * np.eye(n_vertices), vertices, 0, 1. / info['sfreq']) forward_sim = mne.convert_forward_solution(forward, force_fixed=True, use_cps=True, copy=True) forward_sim = mne.forward.restrict_forward_to_stc(forward_sim, stc) noise_cov = mne.make_ad_hoc_cov(info) noise_cov.update(data=np.diag(noise_cov['data']), diag=False) evoked = simulate_evoked(forward_sim, stc, info, noise_cov, nave=1) source_nn = forward_sim['source_nn'] source_rr = forward_sim['source_rr'] # Figure out our indices mask = np.concatenate( [np.in1d(s['vertno'], v) for s, v in zip(forward['src'], vertices)]) mapping = np.where(mask)[0] assert_array_equal(source_rr, forward['source_rr'][mapping]) # Don't check NN because we didn't rotate to surf ori del forward_sim # Let's do minimum norm as a sanity check (dipole_fit is slower) inv = make_inverse_operator(info, forward, noise_cov, loose=1.) stc_vector_mne = apply_inverse(evoked, inv, pick_ori='vector') mne_ori = stc_vector_mne.data[mapping, :, np.arange(n_vertices)] mne_ori /= np.linalg.norm(mne_ori, axis=-1)[:, np.newaxis] mne_angles = np.rad2deg(np.arccos(np.sum(mne_ori * source_nn, axis=-1))) assert np.mean(mne_angles) < 35 # Now let's do LCMV data_cov = mne.make_ad_hoc_cov(info) # just a stub for later with pytest.raises(ValueError, match="pick_ori"): make_lcmv(info, forward, data_cov, 0.05, noise_cov, pick_ori='bad') lcmv_ori = list() for ti in range(n_vertices): this_evoked = evoked.copy().crop(evoked.times[ti], evoked.times[ti]) data_cov['diag'] = False data_cov['data'] = (np.outer(this_evoked.data, this_evoked.data) + noise_cov['data']) vals = linalg.svdvals(data_cov['data']) assert vals[0] / vals[-1] < 1e5 # not rank deficient with catch_logging() as log: filters = make_lcmv(info, forward, data_cov, 0.05, noise_cov, verbose=True) log = log.getvalue() assert '498 sources' in log with catch_logging() as log: filters_vector = make_lcmv(info, forward, data_cov, 0.05, noise_cov, pick_ori='vector', verbose=True) log = log.getvalue() assert '498 sources' in log stc = apply_lcmv(this_evoked, filters) stc_vector = apply_lcmv(this_evoked, filters_vector) assert isinstance(stc, mne.SourceEstimate) assert isinstance(stc_vector, mne.VectorSourceEstimate) assert_allclose(stc.data, stc_vector.magnitude().data) # Check the orientation by pooling across some neighbors, as LCMV can # have some "holes" at the points of interest idx = np.where(cdist(forward['source_rr'], source_rr[[ti]]) < 0.02)[0] lcmv_ori.append(np.mean(stc_vector.data[idx, :, 0], axis=0)) lcmv_ori[-1] /= np.linalg.norm(lcmv_ori[-1]) lcmv_angles = np.rad2deg(np.arccos(np.sum(lcmv_ori * source_nn, axis=-1))) assert np.mean(lcmv_angles) < 55
def _read_forward_solution_meg(*args, **kwargs): fwd = read_forward_solution(*args) fwd = convert_forward_solution(fwd, **kwargs) return mne.pick_types_forward(fwd, meg=True, eeg=False)
def test_localization_bias(): """Test inverse localization bias for minimum-norm solvers.""" # Identity input evoked = _get_evoked() evoked.pick_types(meg=True, eeg=True, exclude=()) evoked = EvokedArray(np.eye(len(evoked.data)), evoked.info) noise_cov = read_cov(fname_cov) # restrict to limited set of verts (small src here) and one hemi for speed fwd_orig = read_forward_solution(fname_fwd) vertices = [fwd_orig['src'][0]['vertno'].copy(), []] stc = SourceEstimate(np.zeros((sum(len(v) for v in vertices), 1)), vertices, 0., 1.) fwd_orig = restrict_forward_to_stc(fwd_orig, stc) # # Fixed orientation (not very different) # fwd = fwd_orig.copy() inv_fixed = make_inverse_operator(evoked.info, fwd, noise_cov, loose=0., depth=0.8) fwd = convert_forward_solution(fwd, force_fixed=True, surf_ori=True) fwd = fwd['sol']['data'] want = np.arange(fwd.shape[1]) for method, lower, upper in (('MNE', 83, 87), ('dSPM', 96, 98), ('sLORETA', 100, 100), ('eLORETA', 100, 100)): inv_op = apply_inverse(evoked, inv_fixed, lambda2, method).data loc = np.abs(np.dot(inv_op, fwd)) # Compute the percentage of sources for which there is no localization # bias: perc = (want == np.argmax(loc, axis=0)).mean() * 100 assert lower <= perc <= upper, method # # Loose orientation # fwd = fwd_orig.copy() inv_free = make_inverse_operator(evoked.info, fwd, noise_cov, loose=0.2, depth=0.8) fwd = fwd['sol']['data'] want = np.arange(fwd.shape[1]) // 3 for method, lower, upper in (('MNE', 25, 35), ('dSPM', 25, 35), ('sLORETA', 35, 40), ('eLORETA', 40, 45)): inv_op = apply_inverse(evoked, inv_free, lambda2, method, pick_ori='vector').data loc = np.linalg.norm(np.einsum('vos,sx->vxo', inv_op, fwd), axis=-1) # Compute the percentage of sources for which there is no localization # bias: perc = (want == np.argmax(loc, axis=0)).mean() * 100 assert lower <= perc <= upper, method # # Free orientation # fwd = fwd_orig.copy() inv_free = make_inverse_operator(evoked.info, fwd, noise_cov, loose=1., depth=0.8) fwd = fwd['sol']['data'] want = np.arange(fwd.shape[1]) // 3 force_kwargs = dict(method_params=dict(force_equal=True)) for method, lower, upper, kwargs in (('MNE', 45, 55, {}), ('dSPM', 40, 45, {}), ('sLORETA', 90, 95, {}), ('eLORETA', 90, 95, force_kwargs), ('eLORETA', 100, 100, {}), ): inv_op = apply_inverse(evoked, inv_free, lambda2, method, pick_ori='vector', **kwargs).data loc = np.linalg.norm(np.einsum('vos,sx->vxo', inv_op, fwd), axis=-1) # Compute the percentage of sources for which there is no localization # bias: perc = (want == np.argmax(loc, axis=0)).mean() * 100 assert lower <= perc <= upper, method
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_simulate_evoked(): """Test simulation of evoked data.""" raw = read_raw_fif(raw_fname) fwd = read_forward_solution(fwd_fname) fwd = convert_forward_solution(fwd, force_fixed=True, use_cps=False) fwd = pick_types_forward(fwd, meg=True, eeg=True, exclude=raw.info['bads']) cov = read_cov(cov_fname) evoked_template = read_evokeds(ave_fname, condition=0, baseline=None) evoked_template.pick_types(meg=True, eeg=True, exclude=raw.info['bads']) with pytest.deprecated_call(match='full'): # this won't depend on rank cov = regularize(cov, evoked_template.info) nave = evoked_template.nave tmin = -0.1 sfreq = 1000. # Hz tstep = 1. / sfreq n_samples = 600 times = np.linspace(tmin, tmin + n_samples * tstep, n_samples) # Generate times series for 2 dipoles stc = simulate_sparse_stc(fwd['src'], n_dipoles=2, times=times, random_state=42) # Generate noisy evoked data iir_filter = [1, -0.9] evoked = simulate_evoked(fwd, stc, evoked_template.info, cov, iir_filter=iir_filter, nave=nave) assert_array_almost_equal(evoked.times, stc.times) assert len(evoked.data) == len(fwd['sol']['data']) assert_equal(evoked.nave, nave) # make a vertex that doesn't exist in fwd, should throw error stc_bad = stc.copy() mv = np.max(fwd['src'][0]['vertno'][fwd['src'][0]['inuse']]) stc_bad.vertices[0][0] = mv + 1 pytest.raises(RuntimeError, simulate_evoked, fwd, stc_bad, evoked_template.info, cov) evoked_1 = simulate_evoked(fwd, stc, evoked_template.info, cov, nave=np.inf) evoked_2 = simulate_evoked(fwd, stc, evoked_template.info, cov, nave=np.inf) assert_array_equal(evoked_1.data, evoked_2.data) cov['names'] = cov.ch_names[:-2] # Error channels are different. pytest.raises(ValueError, simulate_evoked, fwd, stc, evoked_template.info, cov, nave=nave, iir_filter=None)
import mne from mne.datasets import sample from mne.source_space import compute_distance_to_sensors from mne.source_estimate import SourceEstimate import matplotlib.pyplot as plt print(__doc__) data_path = sample.data_path() meg_path = data_path / 'MEG' / 'sample' fwd_fname = meg_path / 'sample_audvis-meg-eeg-oct-6-fwd.fif' subjects_dir = data_path / 'subjects' # Read the forward solutions with surface orientation fwd = mne.read_forward_solution(fwd_fname) mne.convert_forward_solution(fwd, surf_ori=True, copy=False) leadfield = fwd['sol']['data'] print("Leadfield size : %d x %d" % leadfield.shape) # %% # Compute sensitivity maps grad_map = mne.sensitivity_map(fwd, ch_type='grad', mode='fixed') mag_map = mne.sensitivity_map(fwd, ch_type='mag', mode='fixed') eeg_map = mne.sensitivity_map(fwd, ch_type='eeg', mode='fixed') # %% # Show gain matrix a.k.a. leadfield matrix with sensitivity map picks_meg = mne.pick_types(fwd['info'], meg=True, eeg=False) picks_eeg = mne.pick_types(fwd['info'], meg=False, eeg=True)
def test_simulate_round_trip(raw_data): """Test simulate_raw round trip calculations.""" # Check a diagonal round-trip raw, src, stc, trans, sphere = raw_data raw.pick_types(meg=True, stim=True) bem = read_bem_solution(bem_1_fname) old_bem = bem.copy() old_src = src.copy() old_trans = trans.copy() fwd = make_forward_solution(raw.info, trans, src, bem) # no omissions assert (sum(len(s['vertno']) for s in src) == sum(len(s['vertno']) for s in fwd['src']) == 36) # make sure things were not modified assert ( old_bem['surfs'][0]['coord_frame'] == bem['surfs'][0]['coord_frame']) assert trans == old_trans _compare_source_spaces(src, old_src) data = np.eye(fwd['nsource']) raw.crop(0, len(data) / raw.info['sfreq'], include_tmax=False) stc = SourceEstimate(data, [s['vertno'] for s in fwd['src']], 0, 1. / raw.info['sfreq']) for use_fwd in (None, fwd): if use_fwd is None: use_trans, use_src, use_bem = trans, src, bem else: use_trans = use_src = use_bem = None this_raw = simulate_raw(raw.info, stc, use_trans, use_src, use_bem, forward=use_fwd) this_raw.pick_types(meg=True, eeg=True) assert (old_bem['surfs'][0]['coord_frame'] == bem['surfs'][0] ['coord_frame']) assert trans == old_trans _compare_source_spaces(src, old_src) this_fwd = convert_forward_solution(fwd, force_fixed=True) assert_allclose(this_raw[:][0], this_fwd['sol']['data'], atol=1e-12, rtol=1e-6) with pytest.raises(ValueError, match='If forward is not None then'): simulate_raw(raw.info, stc, trans, src, bem, forward=fwd) # Not iterable with pytest.raises(TypeError, match='SourceEstimate, tuple, or iterable'): simulate_raw(raw.info, 0., trans, src, bem, None) # STC with a source that `src` does not have assert 0 not in src[0]['vertno'] vertices = [[0, fwd['src'][0]['vertno'][0]], []] stc_bad = SourceEstimate(data[:2], vertices, 0, 1. / raw.info['sfreq']) with pytest.warns(RuntimeWarning, match='1 of 2 SourceEstimate vertices'): simulate_raw(raw.info, stc_bad, trans, src, bem) assert 0 not in fwd['src'][0]['vertno'] with pytest.warns(RuntimeWarning, match='1 of 2 SourceEstimate vertices'): simulate_raw(raw.info, stc_bad, None, None, None, forward=fwd) # dev_head_t mismatch fwd['info']['dev_head_t']['trans'][0, 0] = 1. with pytest.raises(ValueError, match='dev_head_t.*does not match'): simulate_raw(raw.info, stc, None, None, None, forward=fwd)
# but should be fine for these analyses. bem = mne.read_bem_solution(bem_fname) trans = None # To compute the forward solution, we must # provide our temporary/custom coil definitions, which can be done as:: # # with mne.use_coil_def(coil_def_fname): # fwd = mne.make_forward_solution( # raw.info, trans, src, bem, eeg=False, mindist=5.0, # n_jobs=1, verbose=True) fwd = mne.read_forward_solution(fwd_fname) # use fixed orientation here just to save memory later mne.convert_forward_solution(fwd, force_fixed=True, copy=False) with mne.use_coil_def(coil_def_fname): fig = mne.viz.plot_alignment(evoked.info, trans=trans, subject=subject, subjects_dir=subjects_dir, surfaces=('head', 'pial'), bem=bem) mne.viz.set_3d_view(figure=fig, azimuth=45, elevation=60, distance=0.4, focalpoint=(0.02, 0, 0.04)) ############################################################################### # Perform dipole fitting # ---------------------- # Fit dipoles on a subset of time points with mne.use_coil_def(coil_def_fname):
############################################################################### # Compute forward model # Make source space src_fname = data_path + '/subjects/spm/bem/spm-oct-6-src.fif' if not op.isfile(src_fname): src = mne.setup_source_space('spm', spacing='oct6', subjects_dir=subjects_dir) mne.write_source_spaces(src_fname, src) else: src = mne.read_source_spaces(src_fname) bem = data_path + '/subjects/spm/bem/spm-5120-5120-5120-bem-sol.fif' forward = mne.make_forward_solution(contrast.info, trans_fname, src, bem) forward = mne.convert_forward_solution(forward, surf_ori=True) ############################################################################### # Compute inverse solution snr = 3.0 lambda2 = 1.0 / snr**2 method = 'dSPM' inverse_operator = make_inverse_operator(contrast.info, forward, noise_cov, loose=0.2, depth=0.8) # Compute inverse solution on contrast
get_point_spread) print(__doc__) data_path = sample.data_path() subjects_dir = data_path / 'subjects' meg_path = data_path / 'MEG' / 'sample' fname_fwd = meg_path / 'sample_audvis-meg-eeg-oct-6-fwd.fif' fname_cov = meg_path / 'sample_audvis-cov.fif' fname_evo = meg_path / 'sample_audvis-ave.fif' # read forward solution forward = mne.read_forward_solution(fname_fwd) # forward operator with fixed source orientations mne.convert_forward_solution(forward, surf_ori=True, force_fixed=True, copy=False) # noise covariance matrix noise_cov = mne.read_cov(fname_cov) # evoked data for info evoked = mne.read_evokeds(fname_evo, 0) # make inverse operator from forward solution # free source orientation inverse_operator = mne.minimum_norm.make_inverse_operator(info=evoked.info, forward=forward, noise_cov=noise_cov, loose=0., depth=None)
def test_make_inverse_operator_fixed(evoked, noise_cov): """Test MNE inverse computation (fixed orientation).""" fwd = read_forward_solution_meg(fname_fwd) # can't make fixed inv with depth weighting without free ori fwd fwd_fixed = convert_forward_solution(fwd, force_fixed=True, use_cps=True) pytest.raises(ValueError, make_inverse_operator, evoked.info, fwd_fixed, noise_cov, depth=0.8, fixed=True) # now compare to C solution # note that the forward solution must not be surface-oriented # to get equivalence (surf_ori=True changes the normals) with catch_logging() as log: inv_op = make_inverse_operator( # test depth=0. alias for depth=None evoked.info, fwd, noise_cov, depth=0., fixed=True, use_cps=False, verbose=True) log = log.getvalue() assert 'MEG: rank 302 computed from 305' in log assert 'EEG channels: 0' in repr(inv_op) assert 'MEG channels: 305' in repr(inv_op) del fwd_fixed inverse_operator_nodepth = read_inverse_operator(fname_inv_fixed_nodepth) # XXX We should have this but we don't (MNE-C doesn't restrict info): # assert 'EEG channels: 0' in repr(inverse_operator_nodepth) assert 'MEG channels: 305' in repr(inverse_operator_nodepth) _compare_inverses_approx(inverse_operator_nodepth, inv_op, evoked, rtol=1e-5, atol=1e-4) # Inverse has 306 channels - 6 proj = 302 assert (compute_rank_inverse(inverse_operator_nodepth) == 302) # Now with depth fwd_surf = convert_forward_solution(fwd, surf_ori=True) # not fixed for kwargs, use_fwd in zip( [dict(fixed=True), dict(loose=0.)], [fwd, fwd_surf]): # Should be equiv. inv_op_depth = make_inverse_operator(evoked.info, use_fwd, noise_cov, depth=0.8, use_cps=True, **kwargs) inverse_operator_depth = read_inverse_operator(fname_inv_fixed_depth) # Normals should be the adjusted ones assert_allclose(inverse_operator_depth['source_nn'], fwd_surf['source_nn'][2::3], atol=1e-5) _compare_inverses_approx(inverse_operator_depth, inv_op_depth, evoked, rtol=1e-3, atol=1e-4)
) + '/ses-meg/meg/' + 'sub-' + subject + '_ses-meg_task-facerecognition_run-01_proc-sss_meg.fif' raw = mne.io.Raw(raw_fname, preload=True) raw.info['bads'] = ["EEG061", "EEG062", "EEG063"] raw.pick_types(meg=False, eeg=True, exclude='bads') src = mne.read_source_spaces(fname + 'sub-' + subject + '_free-src.fif', patch_stats=False, verbose=None) model = mne.make_bem_model(subject='sub-' + subject + '_free', ico=4, conductivity=conductivity, subjects_dir=subject_dir) bem = mne.make_bem_solution(model) fwd = mne.convert_forward_solution(mne.make_forward_solution(raw.info, trans=trans, src=src, bem=bem, meg=False, eeg=True, mindist=5.0, n_jobs=2), force_fixed=True) gain = fwd['sol']['data'] np.save( subject_dir + '/data/Sourceest/pinv/sub-' + subject + '/est_normal.npy', (np.linalg.pinv(gain) @ subjects_normal_dict[subject][:, b, :])) np.save( subject_dir + '/data/Sourceest/pinv/sub-' + subject + '/est_scrambled.npy', (np.linalg.pinv(gain) @ subjects_scrambled_dict[subject][:, b, :]))
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 pytest.raises(ValueError, plot_alignment, info) plot_alignment(info, surfaces=[]) 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()