def test_equalize_channels(): """Test equalization of channels for instances of Covariance.""" cov1 = make_ad_hoc_cov( create_info(['CH1', 'CH2', 'CH3', 'CH4'], sfreq=1.0, ch_types='eeg')) cov2 = make_ad_hoc_cov( create_info(['CH5', 'CH1', 'CH2'], sfreq=1.0, ch_types='eeg')) cov1, cov2 = equalize_channels([cov1, cov2]) assert cov1.ch_names == ['CH1', 'CH2'] assert cov2.ch_names == ['CH1', 'CH2']
def test_ad_hoc_cov(tmpdir): """Test ad hoc cov creation and I/O.""" out_fname = op.join(str(tmpdir), 'test-cov.fif') evoked = read_evokeds(ave_fname)[0] cov = make_ad_hoc_cov(evoked.info) cov.save(out_fname) assert 'Covariance' in repr(cov) cov2 = read_cov(out_fname) assert_array_almost_equal(cov['data'], cov2['data']) std = dict(grad=2e-13, mag=10e-15, eeg=0.1e-6) cov = make_ad_hoc_cov(evoked.info, std) cov.save(out_fname) assert 'Covariance' in repr(cov) cov2 = read_cov(out_fname) assert_array_almost_equal(cov['data'], cov2['data'])
def test_ad_hoc_cov(tmpdir): """Test ad hoc cov creation and I/O.""" out_fname = op.join(str(tmpdir), 'test-cov.fif') evoked = read_evokeds(ave_fname)[0] cov = make_ad_hoc_cov(evoked.info) cov.save(out_fname) assert 'Covariance' in repr(cov) cov2 = read_cov(out_fname) assert_array_almost_equal(cov['data'], cov2['data']) std = dict(grad=2e-13, mag=10e-15, eeg=0.1e-6) cov = make_ad_hoc_cov(evoked.info, std) cov.save(out_fname) assert 'Covariance' in repr(cov) cov2 = read_cov(out_fname) assert_array_almost_equal(cov['data'], cov2['data'])
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_compute_whitener_rank(): """Test risky rank options.""" info = read_info(ave_fname) info = pick_info(info, pick_types(info, meg=True)) with info._unlock(): info['projs'] = [] # need a square version because the diag one takes shortcuts in # compute_whitener (users shouldn't even need this function so it's # private) cov = make_ad_hoc_cov(info)._as_square() assert len(cov['names']) == 306 _, _, rank = compute_whitener(cov, info, rank=None, return_rank=True) assert rank == 306 assert compute_rank(cov, info=info, verbose=True) == dict(meg=rank) cov['data'][-1] *= 1e-14 # trivially rank-deficient _, _, rank = compute_whitener(cov, info, rank=None, return_rank=True) assert rank == 305 assert compute_rank(cov, info=info, verbose=True) == dict(meg=rank) # this should emit a warning with pytest.warns(RuntimeWarning, match='exceeds the estimated'): _, _, rank = compute_whitener(cov, info, rank=dict(meg=306), return_rank=True) assert rank == 306
def test_simulation_cascade(): """Test that cascading operations do not overwrite data.""" # Create 10 second raw dataset with zeros in the data matrix raw_null = read_raw_fif(raw_chpi_fname, allow_maxshield='yes') raw_null.crop(0, 1).pick_types(meg=True).load_data() raw_null.apply_function(lambda x: np.zeros_like(x)) assert_array_equal(raw_null.get_data(), 0.) # Calculate independent signal additions raw_eog = raw_null.copy() add_eog(raw_eog, random_state=0) raw_ecg = raw_null.copy() add_ecg(raw_ecg, random_state=0) raw_noise = raw_null.copy() cov = make_ad_hoc_cov(raw_null.info) add_noise(raw_noise, cov, random_state=0) raw_chpi = raw_null.copy() add_chpi(raw_chpi) # Calculate Cascading signal additions raw_cascade = raw_null.copy() add_eog(raw_cascade, random_state=0) add_ecg(raw_cascade, random_state=0) add_chpi(raw_cascade) add_noise(raw_cascade, cov, random_state=0) cascade_data = raw_cascade.get_data() serial_data = 0. for raw_other in (raw_eog, raw_ecg, raw_noise, raw_chpi): serial_data += raw_other.get_data() assert_allclose(cascade_data, serial_data, atol=1e-20)
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_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 = sorted(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() # This was 291 on `master` before gh-5590. Then refactoring transforms # it became 279 despite a < 1e-8 change in vox_mri_t # Then it dropped to 123 once nearest-voxel was used in gh-7653 assert n_on in (123, 279, 291) img = stc.as_volume(src, mri_resolution=False) n_on = np.array(img.dataobj).astype(bool).sum() # was 20 on `master` before gh-5590 # then 44 before gh-7653, which took it back to 20 assert n_on == 20
def get_roi_filter(label_name, fs, channels, show=False, method='sLORETA', lambda2=1): info = mne.create_info( ch_names=channels, sfreq=fs, montage=mne.channels.read_montage(kind='standard_1005'), ch_types=['eeg' for ch in channels]) mne.utils.set_config("SUBJECTS_DIR", 'av_brain', set_env=True) noise_cov = mne.make_ad_hoc_cov(info, verbose=None) fwd = mne.read_forward_solution( r'C:\Users\nsmetanin\PycharmProjects\nfb\tests\sloreta\fsaverage-fwd-1005-1.fif', surf_ori=True) inv = mne.minimum_norm.make_inverse_operator(info, fwd, noise_cov, loose=0.2, depth=0.8, fixed=True) inv = mne.minimum_norm.prepare_inverse_operator(inv, nave=1, lambda2=lambda2, method=method) roi_label = get_roi_by_name(label_name) K, noise_norm, vertno = _assemble_kernel(inv, label=roi_label, method=method, pick_ori=None) w = get_filter(K, vertno, inv, roi_label, noise_norm) if show: mne.viz.plot_topomap(w, info) return w
def test_confidence(): """Test confidence limits.""" tempdir = _TempDir() evoked = read_evokeds(fname_evo_full, 'Left Auditory', baseline=(None, 0)) evoked.crop(0.08, 0.08).pick_types() # MEG-only cov = make_ad_hoc_cov(evoked.info) sphere = make_sphere_model((0., 0., 0.04), 0.08) dip_py = fit_dipole(evoked, cov, sphere)[0] fname_test = op.join(tempdir, 'temp-dip.txt') dip_py.save(fname_test) dip_read = read_dipole(fname_test) with warnings.catch_warnings(record=True) as w: dip_xfit = read_dipole(fname_dip_xfit) assert_equal(len(w), 1) assert ("['noise/ft/cm', 'prob']" in str(w[0].message)) for dip_check in (dip_py, dip_read): assert_allclose(dip_check.pos, dip_xfit.pos, atol=5e-4) # < 0.5 mm assert_allclose(dip_check.gof, dip_xfit.gof, atol=5e-1) # < 0.5% assert_array_equal(dip_check.nfree, dip_xfit.nfree) # exact match assert_allclose(dip_check.khi2, dip_xfit.khi2, rtol=2e-2) # 2% miss assert_equal(set(dip_check.conf.keys()), set(dip_xfit.conf.keys())) for key in sorted(dip_check.conf.keys()): assert_allclose(dip_check.conf[key], dip_xfit.conf[key], rtol=1.5e-1, err_msg=key)
def test_pick_channels_cov(): """Test picking channels from a Covariance object.""" info = create_info(['CH1', 'CH2', 'CH3'], 1., ch_types='eeg') cov = make_ad_hoc_cov(info) cov['data'] = np.array([1., 2., 3.]) cov_copy = pick_channels_cov(cov, ['CH2', 'CH1'], ordered=False, copy=True) assert cov_copy.ch_names == ['CH1', 'CH2'] assert_array_equal(cov_copy['data'], [1., 2.]) # Test re-ordering channels cov_copy = pick_channels_cov(cov, ['CH2', 'CH1'], ordered=True, copy=True) assert cov_copy.ch_names == ['CH2', 'CH1'] assert_array_equal(cov_copy['data'], [2., 1.]) # Test picking in-place pick_channels_cov(cov, ['CH2', 'CH1'], copy=False) assert cov.ch_names == ['CH1', 'CH2'] assert_array_equal(cov['data'], [1., 2.]) # Test whether `method` and `loglik` are dropped when None cov['method'] = None cov['loglik'] = None cov_copy = pick_channels_cov(cov, ['CH1', 'CH2'], copy=True) assert 'method' not in cov_copy assert 'loglik' not in cov_copy
def test_apply_inverse_sphere(evoked): """Test applying an inverse with a sphere model (rank-deficient).""" 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 compute_inverse(fnd): ''' move it elsewhere ... ''' # load EEG dataEEG = mne.read_epochs(fnd) dataEEG.apply_baseline( baseline=(None, 0) ) # baseline correction (important to have accurate estimates of the covariance matrix) info = mne.io.read_info(fnd) # load forward model fwd = mne.read_forward_solution(fn_forward) lambda2 = 1.0 / snr**2 # prepare inverse cov = mne.make_ad_hoc_cov(info) inverse_operator = make_inverse_operator(info, fwd, cov, depth=None, fixed=True) # if decimate > 0: dataEEG.decimate(decimate) evoked = dataEEG.average() stcEVK = apply_inverse(evoked, inverse_operator, lambda2, method=method, verbose=False) return dataEEG, stcEVK, info, inverse_operator
def test_unit_noise_gain_formula(pick_ori, weight_norm, reg, inversion): """Test unit-noise-gain filter against formula.""" raw = mne.io.read_raw_fif(fname_raw, preload=True) events = mne.find_events(raw) raw.pick_types(meg='mag') assert len(raw.ch_names) == 102 epochs = mne.Epochs(raw, events, None, preload=True) data_cov = mne.compute_covariance(epochs, tmin=0.04, tmax=0.15) # for now, avoid whitening to make life easier noise_cov = mne.make_ad_hoc_cov(epochs.info, std=dict(grad=1., mag=1.)) forward = mne.read_forward_solution(fname_fwd) convert_forward_solution(forward, surf_ori=True, copy=False) rank = None kwargs = dict(reg=reg, noise_cov=noise_cov, pick_ori=pick_ori, weight_norm=weight_norm, rank=rank, inversion=inversion) if inversion == 'single' and pick_ori == 'vector' and \ weight_norm == 'unit-noise-gain-invariant': with pytest.raises(ValueError, match='Cannot use'): make_lcmv(epochs.info, forward, data_cov, **kwargs) return filters = make_lcmv(epochs.info, forward, data_cov, **kwargs) _, _, _, _, G, _, _, _ = _prepare_beamformer_input( epochs.info, forward, None, 'vector', noise_cov=noise_cov, rank=rank, pca=False, exp=None) n_channels, n_sources = G.shape n_sources //= 3 G.shape = (n_channels, n_sources, 3) G = G.transpose(1, 2, 0) # verts, orient, ch _assert_weight_norm(filters, G)
def test_mxne_inverse_sure(): """Tests SURE criterion for automatic alpha selection on MEG data.""" def data_fun(times): data = np.zeros(times.shape) data[times >= 0] = 50e-9 return data n_dipoles = 2 raw = mne.io.read_raw_fif(fname_raw) info = mne.io.read_info(fname_data) with info._unlock(): info['projs'] = [] noise_cov = mne.make_ad_hoc_cov(info) label_names = ['Aud-lh', 'Aud-rh'] labels = [mne.read_label(data_path + '/MEG/sample/labels/%s.label' % ln) for ln in label_names] fname_fwd = op.join(data_path, 'MEG', 'sample', 'sample_audvis_trunc-meg-eeg-oct-4-fwd.fif') forward = mne.read_forward_solution(fname_fwd) forward = mne.pick_types_forward(forward, meg="grad", eeg=False, exclude=raw.info['bads']) times = np.arange(100, dtype=np.float64) / raw.info['sfreq'] - 0.1 stc = simulate_sparse_stc(forward['src'], n_dipoles=n_dipoles, times=times, random_state=1, labels=labels, data_fun=data_fun) nave = 30 evoked = simulate_evoked(forward, stc, info, noise_cov, nave=nave, use_cps=False, iir_filter=None) evoked = evoked.crop(tmin=0, tmax=10e-3) stc_ = mixed_norm(evoked, forward, noise_cov, loose=0.9, n_mxne_iter=5, depth=0.9) assert_array_equal(stc_.vertices, stc.vertices)
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 _bias_params(evoked, noise_cov, fwd): evoked.pick_types(meg=True, eeg=True, exclude=()) # restrict to limited set of verts (small src here) and one hemi for speed vertices = [fwd['src'][0]['vertno'].copy(), []] stc = mne.SourceEstimate(np.zeros((sum(len(v) for v in vertices), 1)), vertices, 0, 1) fwd = mne.forward.restrict_forward_to_stc(fwd, stc) assert fwd['sol']['row_names'] == noise_cov['names'] assert noise_cov['names'] == evoked.ch_names evoked = mne.EvokedArray(fwd['sol']['data'].copy(), evoked.info) data_cov = noise_cov.copy() data = fwd['sol']['data'] @ fwd['sol']['data'].T data *= 1e-14 # 100 nAm at each source, effectively (1e-18 would be 1 nAm) # This is rank-deficient, so let's make it actually positive semidefinite # by regularizing a tiny bit data.flat[::data.shape[0] + 1] += mne.make_ad_hoc_cov(evoked.info)['data'] # Do our projection proj, _, _ = mne.io.proj.make_projector(data_cov['projs'], data_cov['names']) data = proj @ data @ proj.T data_cov['data'][:] = data assert data_cov['data'].shape[0] == len(noise_cov['names']) want = np.arange(fwd['sol']['data'].shape[1]) if not mne.forward.is_fixed_orient(fwd): want //= 3 return evoked, fwd, noise_cov, data_cov, want
def test_ad_hoc_cov(): """Test ad hoc cov creation and I/O""" tempdir = _TempDir() out_fname = op.join(tempdir, 'test-cov.fif') evoked = read_evokeds(ave_fname)[0] cov = make_ad_hoc_cov(evoked.info) cov.save(out_fname) cov2 = read_cov(out_fname) assert_array_almost_equal(cov['data'], cov2['data'])
def test_simulate_raw_bem(raw_data): """Test simulation of raw data with BEM.""" raw, src, stc, trans, sphere = raw_data src = setup_source_space('sample', 'oct1', subjects_dir=subjects_dir) for s in src: s['nuse'] = 3 s['vertno'] = src[1]['vertno'][:3] s['inuse'].fill(0) s['inuse'][s['vertno']] = 1 # use different / more complete STC here vertices = [s['vertno'] for s in src] stc = SourceEstimate(np.eye(sum(len(v) for v in vertices)), vertices, 0, 1. / raw.info['sfreq']) with pytest.deprecated_call(): raw_sim_sph = simulate_raw(raw, stc, trans, src, sphere, cov=None, verbose=True) with pytest.deprecated_call(): raw_sim_bem = simulate_raw(raw, stc, trans, src, bem_fname, cov=None, n_jobs=2) # some components (especially radial) might not match that well, # so just make sure that most components have high correlation assert_array_equal(raw_sim_sph.ch_names, raw_sim_bem.ch_names) picks = pick_types(raw.info, meg=True, eeg=True) n_ch = len(picks) corr = np.corrcoef(raw_sim_sph[picks][0], raw_sim_bem[picks][0]) assert_array_equal(corr.shape, (2 * n_ch, 2 * n_ch)) med_corr = np.median(np.diag(corr[:n_ch, -n_ch:])) assert med_corr > 0.65 # do some round-trip localization for s in src: transform_surface_to(s, 'head', trans) locs = np.concatenate([s['rr'][s['vertno']] for s in src]) tmax = (len(locs) - 1) / raw.info['sfreq'] cov = make_ad_hoc_cov(raw.info) # The tolerance for the BEM is surprisingly high (28) but I get the same # result when using MNE-C and Xfit, even when using a proper 5120 BEM :( for use_raw, bem, tol in ((raw_sim_sph, sphere, 2), (raw_sim_bem, bem_fname, 31)): events = find_events(use_raw, 'STI 014') assert len(locs) == 6 evoked = Epochs(use_raw, events, 1, 0, tmax, baseline=None).average() assert len(evoked.times) == len(locs) fits = fit_dipole(evoked, cov, bem, trans, min_dist=1.)[0].pos diffs = np.sqrt(np.sum((locs - fits)**2, axis=-1)) * 1000 med_diff = np.median(diffs) assert med_diff < tol, '%s: %s' % (bem, med_diff)
def test_volume_labels_morph(tmpdir, sl, n_real, n_mri, n_orig): """Test generating a source space from volume label.""" import nibabel as nib n_use = (sl.stop - sl.start) // (sl.step or 1) # 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') lut, _ = read_freesurfer_lut() label_names = sorted(get_volume_labels_from_aseg(aseg_fname)) use_label_names = label_names[sl] src = setup_volume_source_space('sample', subjects_dir=subjects_dir, volume_label=use_label_names, mri=aseg_fname) assert len(src) == n_use 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) assert img.shape == (86, 86, 86, 1) n_on = np.array(img.dataobj).astype(bool).sum() aseg_img = _get_img_fdata(nib.load(fname_aseg)) n_got_real = np.in1d(aseg_img.ravel(), [lut[name] for name in use_label_names]).sum() assert n_got_real == n_real # - This was 291 on `master` before gh-5590 # - Refactoring transforms it became 279 with a < 1e-8 change in vox_mri_t # - Dropped to 123 once nearest-voxel was used in gh-7653 # - Jumped back up to 330 with morphing fixes actually correctly # interpolating across all volumes assert aseg_img.shape == img.shape[:3] assert n_on == n_mri for ii in range(2): # should work with (ii=0) or without (ii=1) the interpolator if ii: src[0]['interpolator'] = None img = stc.as_volume(src, mri_resolution=False) n_on = np.array(img.dataobj).astype(bool).sum() # was 20 on `master` before gh-5590 # then 44 before gh-7653, which took it back to 20 assert n_on == n_orig # without the interpolator, this should fail assert src[0]['interpolator'] is None with pytest.raises(RuntimeError, match=r'.*src\[0\], .* mri_resolution'): stc.as_volume(src, mri_resolution=True)
def test_ad_hoc_cov(): """Test ad hoc cov creation and I/O.""" tempdir = _TempDir() out_fname = op.join(tempdir, "test-cov.fif") evoked = read_evokeds(ave_fname)[0] cov = make_ad_hoc_cov(evoked.info) cov.save(out_fname) assert_true("Covariance" in repr(cov)) cov2 = read_cov(out_fname) assert_array_almost_equal(cov["data"], cov2["data"])
def _rand_csd(rng, info): scales = mne.make_ad_hoc_cov(info).data n = scales.size # Some random complex correlation structure (with channel scalings) data = rng.randn(n, n) + 1j * rng.randn(n, n) data = data @ data.conj().T data *= scales data *= scales[:, np.newaxis] data.flat[::n + 1] = scales return data
def test_dipole_fitting_ctf(): """Test dipole fitting with CTF data.""" raw_ctf = read_raw_ctf(fname_ctf).set_eeg_reference(projection=True) 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_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_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 get_roi_filter(label_name, fs, channels, show=False, method='sLORETA', lambda2=1): info = mne.create_info(ch_names=channels, sfreq=fs, montage=mne.channels.read_montage(kind='standard_1005'), ch_types=['eeg' for ch in channels]) mne.utils.set_config("SUBJECTS_DIR", 'av_brain', set_env=True) noise_cov = mne.make_ad_hoc_cov(info, verbose=None) fwd = mne.read_forward_solution(r'C:\Users\nsmetanin\PycharmProjects\nfb\tests\sloreta\fsaverage-fwd-1005-1.fif', surf_ori=True) inv = mne.minimum_norm.make_inverse_operator(info, fwd, noise_cov, loose=0.2, depth=0.8, fixed=True) inv = mne.minimum_norm.prepare_inverse_operator(inv, nave=1, lambda2=lambda2, method=method) roi_label = get_roi_by_name(label_name) K, noise_norm, vertno = _assemble_kernel(inv, label=roi_label, method=method, pick_ori=None) w = get_filter(K, vertno, inv, roi_label, noise_norm) if show: mne.viz.plot_topomap(w, info) return w
def test_ad_hoc_cov(tmpdir): """Test ad hoc cov creation and I/O.""" out_fname = tmpdir.join('test-cov.fif') evoked = read_evokeds(ave_fname)[0] cov = make_ad_hoc_cov(evoked.info) cov.save(out_fname) assert 'Covariance' in repr(cov) cov2 = read_cov(out_fname) assert_array_almost_equal(cov['data'], cov2['data']) std = dict(grad=2e-13, mag=10e-15, eeg=0.1e-6) cov = make_ad_hoc_cov(evoked.info, std) cov.save(out_fname) assert 'Covariance' in repr(cov) cov2 = read_cov(out_fname) assert_array_almost_equal(cov['data'], cov2['data']) cov['data'] = np.diag(cov['data']) with pytest.raises(RuntimeError, match='attributes inconsistent'): cov._get_square() cov['diag'] = False cov._get_square() cov['data'] = np.diag(cov['data']) with pytest.raises(RuntimeError, match='attributes inconsistent'): cov._get_square()
def get_roi_filter(label_name, fs, channels, show=False, method='sLORETA', lambda2=1): standard_montage = mne.channels.read_montage(kind='standard_1005') standard_montage_names = [name.upper() for name in standard_montage.ch_names] for j, channel in enumerate(channels): channels[j] = standard_montage.ch_names[standard_montage_names.index(channel.upper())] info = mne.create_info(ch_names=channels, sfreq=fs, montage=standard_montage, ch_types=['eeg' for ch in channels]) noise_cov = mne.make_ad_hoc_cov(info, verbose=None) fwd = get_fwd_solution() inv = mne.minimum_norm.make_inverse_operator(info, fwd, noise_cov, loose=0.2, depth=0.8, fixed=True) inv = mne.minimum_norm.prepare_inverse_operator(inv, nave=1, lambda2=lambda2, method=method) roi_label = get_roi_by_name(label_name) K, noise_norm, vertno = _assemble_kernel(inv, label=roi_label, method=method, pick_ori=None) w = get_filter(K, vertno, inv, roi_label, noise_norm) if show: mne.viz.plot_topomap(w, info) return w
def test_simulate_raw_bem(raw_data): """Test simulation of raw data with BEM.""" raw, src, stc, trans, sphere = raw_data src = setup_source_space('sample', 'oct1', subjects_dir=subjects_dir) for s in src: s['nuse'] = 3 s['vertno'] = src[1]['vertno'][:3] s['inuse'].fill(0) s['inuse'][s['vertno']] = 1 # use different / more complete STC here vertices = [s['vertno'] for s in src] stc = SourceEstimate(np.eye(sum(len(v) for v in vertices)), vertices, 0, 1. / raw.info['sfreq']) with pytest.deprecated_call(): raw_sim_sph = simulate_raw(raw, stc, trans, src, sphere, cov=None, verbose=True) with pytest.deprecated_call(): raw_sim_bem = simulate_raw(raw, stc, trans, src, bem_fname, cov=None, n_jobs=2) # some components (especially radial) might not match that well, # so just make sure that most components have high correlation assert_array_equal(raw_sim_sph.ch_names, raw_sim_bem.ch_names) picks = pick_types(raw.info, meg=True, eeg=True) n_ch = len(picks) corr = np.corrcoef(raw_sim_sph[picks][0], raw_sim_bem[picks][0]) assert_array_equal(corr.shape, (2 * n_ch, 2 * n_ch)) med_corr = np.median(np.diag(corr[:n_ch, -n_ch:])) assert med_corr > 0.65 # do some round-trip localization for s in src: transform_surface_to(s, 'head', trans) locs = np.concatenate([s['rr'][s['vertno']] for s in src]) tmax = (len(locs) - 1) / raw.info['sfreq'] cov = make_ad_hoc_cov(raw.info) # The tolerance for the BEM is surprisingly high (28) but I get the same # result when using MNE-C and Xfit, even when using a proper 5120 BEM :( for use_raw, bem, tol in ((raw_sim_sph, sphere, 2), (raw_sim_bem, bem_fname, 31)): events = find_events(use_raw, 'STI 014') assert len(locs) == 6 evoked = Epochs(use_raw, events, 1, 0, tmax, baseline=None).average() assert len(evoked.times) == len(locs) fits = fit_dipole(evoked, cov, bem, trans, min_dist=1.)[0].pos diffs = np.sqrt(np.sum((locs - fits) ** 2, axis=-1)) * 1000 med_diff = np.median(diffs) assert med_diff < tol, '%s: %s' % (bem, med_diff)
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 ((np.percentile(ds, [50, 90]) < [0.0005, perc_90]).all())
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 .* not match'): 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 .* not match'): apply_inverse_raw(raw, inv, 1. / 9.)
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_equalize_channels(): """Test equalizing channels and their ordering.""" # This function only tests the generic functionality of equalize_channels. # Additional tests for each instance type are included in the accompanying # test suite for each type. pytest.raises(TypeError, equalize_channels, ['foo', 'bar'], match='Instances to be modified must be an instance of') raw = RawArray([[1.], [2.], [3.], [4.]], create_info(['CH1', 'CH2', 'CH3', 'CH4'], sfreq=1.)) epochs = EpochsArray([[[1.], [2.], [3.]]], create_info(['CH5', 'CH2', 'CH1'], sfreq=1.)) cov = make_ad_hoc_cov( create_info(['CH2', 'CH1', 'CH8'], sfreq=1., ch_types='eeg')) cov['bads'] = ['CH1'] ave = EvokedArray([[1.], [2.]], create_info(['CH1', 'CH2'], sfreq=1.)) raw2, epochs2, cov2, ave2 = equalize_channels([raw, epochs, cov, ave], copy=True) # The Raw object was the first in the list, so should have been used as # template for the ordering of the channels. No bad channels should have # been dropped. assert raw2.ch_names == ['CH1', 'CH2'] assert_array_equal(raw2.get_data(), [[1.], [2.]]) assert epochs2.ch_names == ['CH1', 'CH2'] assert_array_equal(epochs2.get_data(), [[[3.], [2.]]]) assert cov2.ch_names == ['CH1', 'CH2'] assert cov2['bads'] == cov['bads'] assert ave2.ch_names == ave.ch_names assert_array_equal(ave2.data, ave.data) # All objects should have been copied, except for the Evoked object which # did not have to be touched. assert raw is not raw2 assert epochs is not epochs2 assert cov is not cov2 assert ave is ave2 # Test in-place operation raw2, epochs2 = equalize_channels([raw, epochs], copy=False) assert raw is raw2 assert epochs is epochs2
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_confidence(tmpdir): """Test confidence limits.""" evoked = read_evokeds(fname_evo_full, 'Left Auditory', baseline=(None, 0)) evoked.crop(0.08, 0.08).pick_types() # MEG-only cov = make_ad_hoc_cov(evoked.info) sphere = make_sphere_model((0., 0., 0.04), 0.08) dip_py = fit_dipole(evoked, cov, sphere)[0] fname_test = op.join(str(tmpdir), 'temp-dip.txt') dip_py.save(fname_test) dip_read = read_dipole(fname_test) with pytest.warns(RuntimeWarning, match="'noise/ft/cm', 'prob'"): dip_xfit = read_dipole(fname_dip_xfit_80) for dip_check in (dip_py, dip_read): assert_allclose(dip_check.pos, dip_xfit.pos, atol=5e-4) # < 0.5 mm assert_allclose(dip_check.gof, dip_xfit.gof, atol=5e-1) # < 0.5% assert_array_equal(dip_check.nfree, dip_xfit.nfree) # exact match assert_allclose(dip_check.khi2, dip_xfit.khi2, rtol=2e-2) # 2% miss assert set(dip_check.conf.keys()) == set(dip_xfit.conf.keys()) for key in sorted(dip_check.conf.keys()): assert_allclose(dip_check.conf[key], dip_xfit.conf[key], rtol=1.5e-1, err_msg=key)
def test_confidence(tmpdir): """Test confidence limits.""" evoked = read_evokeds(fname_evo_full, 'Left Auditory', baseline=(None, 0)) evoked.crop(0.08, 0.08).pick_types() # MEG-only cov = make_ad_hoc_cov(evoked.info) sphere = make_sphere_model((0., 0., 0.04), 0.08) dip_py = fit_dipole(evoked, cov, sphere)[0] fname_test = op.join(str(tmpdir), 'temp-dip.txt') dip_py.save(fname_test) dip_read = read_dipole(fname_test) with pytest.warns(RuntimeWarning, match="'noise/ft/cm', 'prob'"): dip_xfit = read_dipole(fname_dip_xfit) for dip_check in (dip_py, dip_read): assert_allclose(dip_check.pos, dip_xfit.pos, atol=5e-4) # < 0.5 mm assert_allclose(dip_check.gof, dip_xfit.gof, atol=5e-1) # < 0.5% assert_array_equal(dip_check.nfree, dip_xfit.nfree) # exact match assert_allclose(dip_check.khi2, dip_xfit.khi2, rtol=2e-2) # 2% miss assert set(dip_check.conf.keys()) == set(dip_xfit.conf.keys()) for key in sorted(dip_check.conf.keys()): assert_allclose(dip_check.conf[key], dip_xfit.conf[key], rtol=1.5e-1, err_msg=key)
def test_confidence(): """Test confidence limits.""" tempdir = _TempDir() evoked = read_evokeds(fname_evo_full, 'Left Auditory', baseline=(None, 0)) evoked.crop(0.08, 0.08).pick_types() # MEG-only cov = make_ad_hoc_cov(evoked.info) sphere = make_sphere_model((0., 0., 0.04), 0.08) dip_py = fit_dipole(evoked, cov, sphere)[0] fname_test = op.join(tempdir, 'temp-dip.txt') dip_py.save(fname_test) dip_read = read_dipole(fname_test) with warnings.catch_warnings(record=True) as w: dip_xfit = read_dipole(fname_dip_xfit) assert_equal(len(w), 1) assert_true("['noise/ft/cm', 'prob']" in str(w[0].message)) for dip_check in (dip_py, dip_read): assert_allclose(dip_check.pos, dip_xfit.pos, atol=5e-4) # < 0.5 mm assert_allclose(dip_check.gof, dip_xfit.gof, atol=5e-1) # < 0.5% assert_array_equal(dip_check.nfree, dip_xfit.nfree) # exact match assert_allclose(dip_check.khi2, dip_xfit.khi2, rtol=2e-2) # 2% miss assert_equal(set(dip_check.conf.keys()), set(dip_xfit.conf.keys())) for key in sorted(dip_check.conf.keys()): assert_allclose(dip_check.conf[key], dip_xfit.conf[key], rtol=1.5e-1, err_msg=key)
a = QApplication([]) rej, spatial, top = ICADialog.get_rejection(data.T, channels, fs, mode='ica', states=None)[:3] data = rej.apply(data.T).T standard_montage = mne.channels.read_montage(kind='standard_1005') standard_montage_names = [name.upper() for name in standard_montage.ch_names] for j, channel in enumerate(channels): channels[j] = standard_montage.ch_names[standard_montage_names.index(channel.upper())] # create info info = mne.create_info(ch_names=channels, sfreq=fs, montage=mne.channels.read_montage(kind='standard_1005'), ch_types=['eeg' for ch in channels]) # raw instance raw = mne.io.RawArray(data, info) #raw.set_eeg_reference() #noise_cov = mne.compute_raw_covariance(raw) noise_cov = mne.make_ad_hoc_cov(info, verbose=None) # forward solution #fwd = mne.make_forward_solution(info, trans=trans, src=src, bem=bem, fname='fsaverage-fwd.fif', meg=False, eeg=True, mindist=5.) fwd = mne.read_forward_solution(r'C:\Users\nsmetanin\PycharmProjects\nfb\tests\sloreta\fsaverage-fwd-1005-2.fif', surf_ori=True) # inverse from mne.minimum_norm.inverse import _assemble_kernel inv = mne.minimum_norm.make_inverse_operator(info, fwd, noise_cov, loose=0.2, depth=0.8, fixed=True) lambdas = [1000, 100, 10, 1, 0.1, 0.05, 0.01, 0.005, 0.001, 0.0001] f, axes = plt.subplots(2, len(lambdas))
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) 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) 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) 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() 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) 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) 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) 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 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) 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) 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) 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 raw_sim = simulate_raw(raw, stc, trans, src, sphere, cov=None) n_samp = int(round(raw.info['sfreq'])) for use_raw in (raw, raw.info): raw_sim_2 = simulate_raw(use_raw, stc, trans, src, sphere, cov=None, duration=1.) 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, stc, trans, src, sphere, cov=None, head_pos=head_pos_sim, interp='linear') 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, 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) pytest.raises(RuntimeError, simulate_raw, raw, stc, trans, src, bem_fname, ecg=False, blink=False, head_pos=head_pos_sim_err) # other degenerate conditions pytest.raises(TypeError, simulate_raw, 'foo', stc, trans, src, sphere) pytest.raises(TypeError, simulate_raw, raw, 'foo', trans, src, sphere) pytest.raises(ValueError, simulate_raw, raw, stc.copy().crop(0, 0), trans, src, sphere) with pytest.raises(ValueError, match='duration cannot be None'): simulate_raw(raw.info, stc, trans, src, sphere) with pytest.raises(TypeError, match='must be an instance of Raw or Info'): simulate_raw(0, stc, trans, src, sphere) stc_bad = stc.copy() stc_bad.tstep += 0.1 pytest.raises(ValueError, simulate_raw, raw, stc_bad, trans, src, sphere) pytest.raises(TypeError, simulate_raw, raw, stc, trans, src, sphere, cov=0) # wrong covariance type pytest.raises(RuntimeError, simulate_raw, raw, stc, trans, src, sphere, chpi=True) # no cHPI info pytest.raises(ValueError, simulate_raw, raw, stc, trans, src, sphere, interp='foo') pytest.raises(TypeError, simulate_raw, raw, stc, trans, src, sphere, head_pos=1.) pytest.raises(RuntimeError, simulate_raw, raw, stc, trans, src, sphere, head_pos=pos_fname) # 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) raw_bad = raw.copy() raw_bad.info['dig'] = None pytest.raises(RuntimeError, simulate_raw, raw_bad, stc, trans, src, sphere, blink=True)
def test_lcmv_reg_proj(proj, weight_norm): """Test LCMV with and without proj.""" raw = mne.io.read_raw_fif(fname_raw, preload=True) events = mne.find_events(raw) raw.pick_types(meg=True) assert len(raw.ch_names) == 305 epochs = mne.Epochs(raw, events, None, preload=True, proj=proj) with pytest.warns(RuntimeWarning, match='Too few samples'): noise_cov = mne.compute_covariance(epochs, tmax=0) data_cov = mne.compute_covariance(epochs, tmin=0.04, tmax=0.15) forward = mne.read_forward_solution(fname_fwd) filters = make_lcmv(epochs.info, forward, data_cov, reg=0.05, noise_cov=noise_cov, pick_ori='max-power', weight_norm='nai', rank=None, verbose=True) want_rank = 302 # 305 good channels - 3 MEG projs assert filters['rank'] == want_rank # And also with and without noise_cov with pytest.raises(ValueError, match='several sensor types'): make_lcmv(epochs.info, forward, data_cov, reg=0.05, noise_cov=None) epochs.pick_types(meg='grad') kwargs = dict(reg=0.05, pick_ori=None, weight_norm=weight_norm) filters_cov = make_lcmv(epochs.info, forward, data_cov, noise_cov=noise_cov, **kwargs) filters_nocov = make_lcmv(epochs.info, forward, data_cov, noise_cov=None, **kwargs) ad_hoc = mne.make_ad_hoc_cov(epochs.info) filters_adhoc = make_lcmv(epochs.info, forward, data_cov, noise_cov=ad_hoc, **kwargs) evoked = epochs.average() stc_cov = apply_lcmv(evoked, filters_cov) stc_nocov = apply_lcmv(evoked, filters_nocov) stc_adhoc = apply_lcmv(evoked, filters_adhoc) # Compare adhoc and nocov: scale difference is necessitated by using std=1. if weight_norm == 'unit-noise-gain': scale = np.sqrt(ad_hoc['data'][0]) else: scale = 1. assert_allclose(stc_nocov.data, stc_adhoc.data * scale) a = np.dot(filters_nocov['weights'], filters_nocov['whitener']) b = np.dot(filters_adhoc['weights'], filters_adhoc['whitener']) * scale atol = np.mean(np.sqrt(a * a)) * 1e-7 assert_allclose(a, b, atol=atol, rtol=1e-7) # Compare adhoc and cov: locs might not be equivalent, but the same # general profile should persist, so look at the std and be lenient: if weight_norm == 'unit-noise-gain': adhoc_scale = 0.12 else: adhoc_scale = 1. assert_allclose( np.linalg.norm(stc_adhoc.data, axis=0) * adhoc_scale, np.linalg.norm(stc_cov.data, axis=0), rtol=0.3) assert_allclose( np.linalg.norm(stc_nocov.data, axis=0) / scale * adhoc_scale, np.linalg.norm(stc_cov.data, axis=0), rtol=0.3) if weight_norm == 'nai': # NAI is always normalized by noise-level (based on eigenvalues) for stc in (stc_nocov, stc_cov): assert_allclose(stc.data.std(), 0.584, rtol=0.2) elif weight_norm is None: # None always represents something not normalized, reflecting channel # weights for stc in (stc_nocov, stc_cov): assert_allclose(stc.data.std(), 2.8e-8, rtol=0.1) else: assert weight_norm == 'unit-noise-gain' # Channel scalings depend on presence of noise_cov assert_allclose(stc_nocov.data.std(), 7.8e-13, rtol=0.1) assert_allclose(stc_cov.data.std(), 0.187, rtol=0.2)
# activate. Here we use a sine wave at 18 Hz with a peak amplitude # of 10 nAm. source_time_series = np.sin(2. * np.pi * 18. * np.arange(100) * tstep) * 10e-9 # Define when the activity occurs using events. The first column is the sample # of the event, the second is not used, and the third is the event id. Here the # events occur every 200 samples. n_events = 50 events = np.zeros((n_events, 3)) events[:, 0] = 100 + 200 * np.arange(n_events) # Events sample. events[:, 2] = 1 # All events have the sample id. # Create simulated source activity. Here we use a SourceSimulator whose # add_data method is key. It specified where (label), what # (source_time_series), and when (events) an event type will occur. source_simulator = mne.simulation.SourceSimulator(src, tstep=tstep) source_simulator.add_data(label, source_time_series, events) # Project the source time series to sensor space and add some noise. The source # simulator can be given directly to the simulate_raw function. raw = mne.simulation.simulate_raw(info, source_simulator, forward=fwd) cov = mne.make_ad_hoc_cov(raw.info) mne.simulation.add_noise(raw, cov, iir_filter=[0.2, -0.2, 0.04]) raw.plot() # Plot evoked data to get another view of the simulated raw data. events = mne.find_events(raw) epochs = mne.Epochs(raw, events, 1, tmin=-0.05, tmax=0.2) evoked = epochs.average() evoked.plot()
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 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_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, raw_sim_hann
def simulate_movement(raw, pos, stc, trans, src, bem, cov='simple', mindist=1.0, interp='linear', random_state=None, n_jobs=1, verbose=None): """Simulate raw data with head movements Parameters ---------- raw : instance of Raw The raw instance to use. The measurement info, including the head positions, will be used to simulate data. pos : str | dict | None Name of the position estimates file. Should be in the format of the files produced by maxfilter-produced. If dict, keys should be the time points and entries should be 4x3 ``dev_head_t`` matrices. If None, the original head position (from ``raw.info['dev_head_t']``) will be used. stc : instance of SourceEstimate The source estimate to use to simulate data. Must have the same sample rate as the raw data. trans : dict | str Either a transformation filename (usually made using mne_analyze) or an info dict (usually opened using read_trans()). If string, an ending of `.fif` or `.fif.gz` will be assumed to be in FIF format, any other ending will be assumed to be a text file with a 4x4 transformation matrix (like the `--trans` MNE-C option). src : str | instance of SourceSpaces If string, should be a source space filename. Can also be an instance of loaded or generated SourceSpaces. bem : str Filename of the BEM (e.g., "sample-5120-5120-5120-bem-sol.fif"). cov : instance of Covariance | 'simple' | None The sensor covariance matrix used to generate noise. If None, no noise will be added. If 'simple', a basic (diagonal) ad-hoc noise covariance will be used. mindist : float Minimum distance between sources and the inner skull boundary to use during forward calculation. interp : str Either 'linear' or 'zero', the type of forward-solution interpolation to use between provided time points. random_state : None | int | np.random.RandomState To specify the random generator state. n_jobs : int Number of jobs to use. verbose : bool, str, int, or None If not None, override default verbose level (see mne.verbose). Returns ------- raw : instance of Raw The simulated raw file. Notes ----- Events coded with the number of the forward solution used will be placed in the raw files in the trigger channel STI101 at the t=0 times of the SourceEstimates. The resulting SNR will be determined by the structure of the noise covariance, and the amplitudes of the SourceEstimate. Note that this will vary as a function of position. """ if isinstance(raw, string_types): with warnings.catch_warnings(record=True): raw = Raw(raw, allow_maxshield=True, preload=True, verbose=False) else: raw = raw.copy() if not isinstance(stc, _BaseSourceEstimate): raise TypeError('stc must be a SourceEstimate') if not np.allclose(raw.info['sfreq'], 1. / stc.tstep): raise ValueError('stc and raw must have same sample rate') rng = check_random_state(random_state) if interp not in ('linear', 'zero'): raise ValueError('interp must be "linear" or "zero"') if pos is None: # use pos from file dev_head_ts = [raw.info['dev_head_t']] * 2 offsets = np.array([0, raw.n_times]) interp = 'zero' else: if isinstance(pos, string_types): pos = get_chpi_positions(pos, verbose=False) if isinstance(pos, tuple): # can be an already-loaded pos file transs, rots, ts = pos ts -= raw.first_samp / raw.info['sfreq'] # MF files need reref dev_head_ts = [np.r_[np.c_[r, t[:, np.newaxis]], [[0, 0, 0, 1]]] for r, t in zip(rots, transs)] del transs, rots elif isinstance(pos, dict): ts = np.array(list(pos.keys()), float) ts.sort() dev_head_ts = [pos[float(tt)] for tt in ts] else: raise TypeError('unknown pos type %s' % type(pos)) if not (ts >= 0).all(): # pathological if not raise RuntimeError('Cannot have t < 0 in transform file') tend = raw.times[-1] assert not (ts < 0).any() assert not (ts > tend).any() if ts[0] > 0: ts = np.r_[[0.], ts] dev_head_ts.insert(0, raw.info['dev_head_t']['trans']) dev_head_ts = [{'trans': d, 'to': raw.info['dev_head_t']['to'], 'from': raw.info['dev_head_t']['from']} for d in dev_head_ts] if ts[-1] < tend: dev_head_ts.append(dev_head_ts[-1]) ts = np.r_[ts, [tend]] offsets = raw.time_as_index(ts) offsets[-1] = raw.n_times # fix for roundoff error assert offsets[-2] != offsets[-1] del ts if isinstance(cov, string_types): assert cov == 'simple' cov = make_ad_hoc_cov(raw.info, verbose=False) assert np.array_equal(offsets, np.unique(offsets)) assert len(offsets) == len(dev_head_ts) approx_events = int((raw.n_times / raw.info['sfreq']) / (stc.times[-1] - stc.times[0])) logger.info('Provided parameters will provide approximately %s event%s' % (approx_events, '' if approx_events == 1 else 's')) # get HPI freqs and reorder hpi_freqs = np.array([x['custom_ref'][0] for x in raw.info['hpi_meas'][0]['hpi_coils']]) n_freqs = len(hpi_freqs) order = [x['number'] - 1 for x in raw.info['hpi_meas'][0]['hpi_coils']] assert np.array_equal(np.unique(order), np.arange(n_freqs)) hpi_freqs = hpi_freqs[order] hpi_order = raw.info['hpi_results'][0]['order'] - 1 assert np.array_equal(np.unique(hpi_order), np.arange(n_freqs)) hpi_freqs = hpi_freqs[hpi_order] # extract necessary info picks = pick_types(raw.info, meg=True, eeg=True) # for simulation meg_picks = pick_types(raw.info, meg=True, eeg=False) # for CHPI fwd_info = pick_info(raw.info, picks) fwd_info['projs'] = [] logger.info('Setting up raw data simulation using %s head position%s' % (len(dev_head_ts), 's' if len(dev_head_ts) != 1 else '')) raw.preload_data(verbose=False) if isinstance(stc, VolSourceEstimate): verts = [stc.vertices] else: verts = stc.vertices src = _restrict_source_space_to(src, verts) # figure out our cHPI, ECG, and EOG dipoles dig = raw.info['dig'] assert all([d['coord_frame'] == FIFF.FIFFV_COORD_HEAD for d in dig if d['kind'] == FIFF.FIFFV_POINT_HPI]) chpi_rrs = [d['r'] for d in dig if d['kind'] == FIFF.FIFFV_POINT_HPI] R, r0 = fit_sphere_to_headshape(raw.info, verbose=False)[:2] R /= 1000. r0 /= 1000. ecg_rr = np.array([[-R, 0, -3 * R]]) eog_rr = [d['r'] for d in raw.info['dig'] if d['ident'] == FIFF.FIFFV_POINT_NASION][0] eog_rr = eog_rr - r0 eog_rr = (eog_rr / np.sqrt(np.sum(eog_rr * eog_rr)) * 0.98 * R)[np.newaxis, :] eog_rr += r0 eog_bem = make_sphere_model(r0, head_radius=R, relative_radii=(0.99, 1.), sigmas=(0.33, 0.33), verbose=False) # let's oscillate between resting (17 bpm) and reading (4.5 bpm) rate # http://www.ncbi.nlm.nih.gov/pubmed/9399231 blink_rate = np.cos(2 * np.pi * 1. / 60. * raw.times) blink_rate *= 12.5 / 60. blink_rate += 4.5 / 60. blink_data = rng.rand(raw.n_times) < blink_rate / raw.info['sfreq'] blink_data = blink_data * (rng.rand(raw.n_times) + 0.5) # vary amplitudes blink_kernel = np.hanning(int(0.25 * raw.info['sfreq'])) eog_data = np.convolve(blink_data, blink_kernel, 'same')[np.newaxis, :] eog_data += rng.randn(eog_data.shape[1]) * 0.05 eog_data *= 100e-6 del blink_data, max_beats = int(np.ceil(raw.times[-1] * 70. / 60.)) cardiac_idx = np.cumsum(rng.uniform(60. / 70., 60. / 50., max_beats) * raw.info['sfreq']).astype(int) cardiac_idx = cardiac_idx[cardiac_idx < raw.n_times] cardiac_data = np.zeros(raw.n_times) cardiac_data[cardiac_idx] = 1 cardiac_kernel = np.concatenate([ 2 * np.hanning(int(0.04 * raw.info['sfreq'])), -0.3 * np.hanning(int(0.05 * raw.info['sfreq'])), 0.2 * np.hanning(int(0.26 * raw.info['sfreq']))], axis=-1) ecg_data = np.convolve(cardiac_data, cardiac_kernel, 'same')[np.newaxis, :] ecg_data += rng.randn(ecg_data.shape[1]) * 0.05 ecg_data *= 3e-4 del cardiac_data # Add to data file, then rescale for simulation for data, scale, exg_ch in zip([eog_data, ecg_data], [1e-3, 5e-4], ['EOG062', 'ECG063']): ch = pick_channels(raw.ch_names, [exg_ch]) if len(ch) == 1: raw._data[ch[0], :] = data data *= scale evoked = EvokedArray(np.zeros((len(picks), len(stc.times))), fwd_info, stc.tmin, verbose=False) stc_event_idx = np.argmin(np.abs(stc.times)) event_ch = pick_channels(raw.info['ch_names'], ['STI101'])[0] used = np.zeros(raw.n_times, bool) stc_indices = np.arange(raw.n_times) % len(stc.times) raw._data[event_ch, ].fill(0) hpi_mag = 25e-9 last_fwd = last_fwd_chpi = last_fwd_eog = last_fwd_ecg = src_sel = None for fi, (fwd, fwd_eog, fwd_ecg, fwd_chpi) in \ enumerate(_make_forward_solutions( fwd_info, trans, src, bem, eog_bem, dev_head_ts, mindist, chpi_rrs, eog_rr, ecg_rr, n_jobs)): # must be fixed orientation fwd = convert_forward_solution(fwd, surf_ori=True, force_fixed=True, verbose=False) # just use one arbitrary direction fwd_eog = fwd_eog['sol']['data'][:, ::3] fwd_ecg = fwd_ecg['sol']['data'][:, ::3] fwd_chpi = fwd_chpi[:, ::3] if src_sel is None: src_sel = _stc_src_sel(fwd['src'], stc) if isinstance(stc, VolSourceEstimate): verts = [stc.vertices] else: verts = stc.vertices diff_ = sum([len(v) for v in verts]) - len(src_sel) if diff_ != 0: warnings.warn('%s STC vertices omitted due to fwd calculation' % (diff_,)) if last_fwd is None: last_fwd, last_fwd_eog, last_fwd_ecg, last_fwd_chpi = \ fwd, fwd_eog, fwd_ecg, fwd_chpi continue n_time = offsets[fi] - offsets[fi-1] time_slice = slice(offsets[fi-1], offsets[fi]) assert not used[time_slice].any() stc_idxs = stc_indices[time_slice] event_idxs = np.where(stc_idxs == stc_event_idx)[0] + offsets[fi-1] used[time_slice] = True logger.info(' Simulating data for %0.3f-%0.3f sec with %s event%s' % (tuple(offsets[fi-1:fi+1] / raw.info['sfreq']) + (len(event_idxs), '' if len(event_idxs) == 1 else 's'))) # simulate brain data stc_data = stc.data[:, stc_idxs][src_sel] data = _interp(last_fwd['sol']['data'], fwd['sol']['data'], stc_data, interp) simulated = EvokedArray(data, evoked.info, 0) if cov is not None: noise = generate_noise_evoked(simulated, cov, [1, -1, 0.2], rng) simulated.data += noise.data assert simulated.data.shape[0] == len(picks) assert simulated.data.shape[1] == len(stc_idxs) raw._data[picks, time_slice] = simulated.data # add ECG, EOG, and CHPI traces raw._data[picks, time_slice] += \ _interp(last_fwd_eog, fwd_eog, eog_data[:, time_slice], interp) raw._data[meg_picks, time_slice] += \ _interp(last_fwd_ecg, fwd_ecg, ecg_data[:, time_slice], interp) this_t = np.arange(offsets[fi-1], offsets[fi]) / raw.info['sfreq'] sinusoids = np.zeros((n_freqs, n_time)) for fi, freq in enumerate(hpi_freqs): sinusoids[fi] = 2 * np.pi * freq * this_t sinusoids[fi] = hpi_mag * np.sin(sinusoids[fi]) raw._data[meg_picks, time_slice] += \ _interp(last_fwd_chpi, fwd_chpi, sinusoids, interp) # add events raw._data[event_ch, event_idxs] = fi # prepare for next iteration last_fwd, last_fwd_eog, last_fwd_ecg, last_fwd_chpi = \ fwd, fwd_eog, fwd_ecg, fwd_chpi assert used.all() logger.info('Done') return raw
# activate. Here we use a sine wave at 18 Hz with a peak amplitude # of 10 nAm. source_time_series = np.sin(2. * np.pi * 18. * np.arange(100) * tstep) * 10e-9 # Define when the activity occurs using events. The first column is the sample # of the event, the second is not used, and the third is the event id. Here the # events occur every 200 samples. n_events = 50 events = np.zeros((n_events, 3)) events[:, 0] = 100 + 200 * np.arange(n_events) # Events sample. events[:, 2] = 1 # All events have the sample id. # Create simulated source activity. Here we use a SourceSimulator whose # add_data method is key. It specified where (label), what # (source_time_series), and when (events) an event type will occur. source_simulator = mne.simulation.SourceSimulator(src, tstep=tstep) source_simulator.add_data(label, source_time_series, events) # Project the source time series to sensor space and add some noise. The source # simulator can be given directly to the simulate_raw function. raw = mne.simulation.simulate_raw(info, source_simulator, forward=fwd) cov = mne.make_ad_hoc_cov(raw.info) mne.simulation.add_noise(raw, cov, iir_filter=[0.2, -0.2, 0.04]) raw.plot() # Plot evoked data to get another view of the simulated raw data. events = mne.find_events(raw) epochs = mne.Epochs(raw, events, 1, tmin=-0.05, tmax=0.2) evoked = epochs.average() evoked.plot()
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 must be one of'): 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['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 filters = make_lcmv(info, forward, data_cov, 0.05, noise_cov) filters_vector = make_lcmv(info, forward, data_cov, 0.05, noise_cov, pick_ori='vector') stc = apply_lcmv(this_evoked, filters) assert isinstance(stc, mne.SourceEstimate) stc_vector = apply_lcmv(this_evoked, filters_vector) 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