def test_simulate_evoked(): """ Test simulation of evoked data """ raw = Raw(raw_fname) fwd = read_forward_solution(fwd_fname, force_fixed=True) 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']) snr = 6 # dB 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) stc._data *= 1e-9 # Generate noisy evoked data iir_filter = [1, -0.9] evoked = simulate_evoked(fwd, stc, evoked_template.info, cov, snr, tmin=0.0, tmax=0.2, iir_filter=iir_filter) assert_array_almost_equal(evoked.times, stc.times) assert_true(len(evoked.data) == len(fwd['sol']['data'])) # 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, snr, tmin=0.0, tmax=0.2) evoked_1 = simulate_evoked(fwd, stc, evoked_template.info, cov, np.inf, tmin=0.0, tmax=0.2) evoked_2 = simulate_evoked(fwd, stc, evoked_template.info, cov, np.inf, tmin=0.0, tmax=0.2) assert_array_equal(evoked_1.data, evoked_2.data) # test snr definition in dB evoked_noise = simulate_evoked(fwd, stc, evoked_template.info, cov, snr=snr, tmin=None, tmax=None, iir_filter=None) evoked_clean = simulate_evoked(fwd, stc, evoked_template.info, cov, snr=np.inf, tmin=None, tmax=None, iir_filter=None) noise = evoked_noise.data - evoked_clean.data empirical_snr = 10 * np.log10(np.mean((evoked_clean.data ** 2).ravel()) / np.mean((noise ** 2).ravel())) assert_almost_equal(snr, empirical_snr, decimal=5) cov['names'] = cov.ch_names[:-2] # Error channels are different. assert_raises(ValueError, simulate_evoked, fwd, stc, evoked_template.info, cov, snr=3., tmin=None, tmax=None, iir_filter=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']) 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 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_simulate_evoked(): """ Test simulation of evoked data """ raw = Raw(raw_fname) fwd = read_forward_solution(fwd_fname, force_fixed=True) 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']) snr = 6 # dB 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) stc._data *= 1e-9 # Generate noisy evoked data iir_filter = [1, -0.9] evoked = simulate_evoked(fwd, stc, evoked_template.info, cov, snr, tmin=0.0, tmax=0.2, iir_filter=iir_filter) assert_array_almost_equal(evoked.times, stc.times) assert_true(len(evoked.data) == len(fwd['sol']['data'])) # 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, snr, tmin=0.0, tmax=0.2) evoked_1 = simulate_evoked(fwd, stc, evoked_template.info, cov, np.inf, tmin=0.0, tmax=0.2) evoked_2 = simulate_evoked(fwd, stc, evoked_template.info, cov, np.inf, tmin=0.0, tmax=0.2) assert_array_equal(evoked_1.data, evoked_2.data)
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())
kwargs = dict(subjects_dir=subjects_dir, hemi='split', smoothing_steps=4, time_unit='s', initial_time=0.05, size=1200, views=['lat', 'med']) clim = dict(kind='value', pos_lims=[1e-9, 1e-8, 1e-7]) figs = [mlab.figure(1), mlab.figure(2), mlab.figure(3), mlab.figure(4)] brain_gen = stc_gen.plot(clim=clim, figure=figs, **kwargs) ############################################################################### # Simulate sensor-space signals # ----------------------------- # # Use the forward solution and add Gaussian noise to simulate sensor-space # (evoked) data from the known source-space signals. The amount of noise is # controlled by `nave` (higher values imply less noise). # evoked_gen = simulate_evoked(fwd, stc_gen, evoked.info, cov, nave, random_state=seed) # Map the simulated sensor-space data to source-space using the inverse # operator. stc_inv = apply_inverse(evoked_gen, inv_op, lambda2, method=method) ############################################################################### # Plot the point-spread of corrupted signal # ----------------------------------------- # # Notice that after applying the forward- and inverse-operators to the known # point sources that the point sources have spread across the source-space. # This spread is due to the minimum norm solution so that the signal leaks to # nearby vertices with similar orientations so that signal ends up crossing the # sulci and gyri. figs = [mlab.figure(5), mlab.figure(6), mlab.figure(7), mlab.figure(8)]
times = np.arange(300, dtype=np.float) / raw.info['sfreq'] - 0.1 rng = np.random.RandomState(42) def data_fun(times): """Function to generate random source time courses""" return (50e-9 * np.sin(30. * times) * np.exp(- (times - 0.15 + 0.05 * rng.randn(1)) ** 2 / 0.01)) stc = simulate_sparse_stc(fwd['src'], n_dipoles=2, times=times, random_state=42, labels=labels, data_fun=data_fun) ############################################################################### # Generate noisy evoked data picks = mne.pick_types(raw.info, meg=True, exclude='bads') iir_filter = fit_iir_model_raw(raw, order=5, picks=picks, tmin=60, tmax=180)[1] nave = 100 # simulate average of 100 epochs evoked = simulate_evoked(fwd, stc, info, cov, nave=nave, use_cps=True, iir_filter=iir_filter) ############################################################################### # Plot plot_sparse_source_estimates(fwd['src'], stc, bgcolor=(1, 1, 1), opacity=0.5, high_resolution=True) plt.figure() plt.psd(evoked.data[0]) evoked.plot(time_unit='s')
evoked = mne.read_evokeds(fname_ave, condition='Right Auditory', baseline=(None, 0)) evoked.pick_types(meg=True, eeg=False) evoked.crop(0.07, 0.08) # Fit a dipole dip = mne.fit_dipole(evoked, fname_cov, fname_bem, fname_trans)[0] # Plot the result in 3D brain dip.plot_locations(fname_trans, 'sample', subjects_dir) ############################################################################### # Calculate and visualise magnetic field predicted by dipole with maximum GOF # and compare to the measured data, highlighting the ipsilateral (right) source fwd, stc = make_forward_dipole(dip, fname_bem, evoked.info, fname_trans) pred_evoked = simulate_evoked(fwd, stc, evoked.info, None, snr=np.inf) # find time point with highes GOF to plot best_time = dip.times[np.argmax(dip.gof)] # rememeber to create a subplot for the colorbar fig, axes = plt.subplots(nrows=1, ncols=4, figsize=[10., 3.4]) vmin, vmax = -400, 400 # make sure each plot has same colour range # first plot the topography at the time of the best fitting (single) dipole plot_params = dict(times=best_time, ch_type='mag', outlines='skirt', colorbar=False) evoked.plot_topomap(time_format='Measured field', axes=axes[0], **plot_params) # compare this to the predicted field pred_evoked.plot_topomap(time_format='Predicted field', axes=axes[1], **plot_params)
baseline=(None, 0)) evoked.pick_types(meg=True, eeg=False) evoked_full = evoked.copy() evoked.crop(0.07, 0.08) # Fit a dipole dip = mne.fit_dipole(evoked, fname_cov, fname_bem, fname_trans)[0] # Plot the result in 3D brain with the MRI image. dip.plot_locations(fname_trans, 'sample', subjects_dir, mode='orthoview') ############################################################################### # Calculate and visualise magnetic field predicted by dipole with maximum GOF # and compare to the measured data, highlighting the ipsilateral (right) source fwd, stc = make_forward_dipole(dip, fname_bem, evoked.info, fname_trans) pred_evoked = simulate_evoked(fwd, stc, evoked.info, cov=None, nave=np.inf) # find time point with highest GOF to plot best_idx = np.argmax(dip.gof) best_time = dip.times[best_idx] print('Highest GOF %0.1f%% at t=%0.1f ms with confidence volume %0.1f cm^3' % (dip.gof[best_idx], best_time * 1000, dip.conf['vol'][best_idx] * 100 ** 3)) # rememeber to create a subplot for the colorbar fig, axes = plt.subplots(nrows=1, ncols=4, figsize=[10., 3.4]) vmin, vmax = -400, 400 # make sure each plot has same colour range # first plot the topography at the time of the best fitting (single) dipole plot_params = dict(times=best_time, ch_type='mag', outlines='skirt', colorbar=False, time_unit='s') evoked.plot_topomap(time_format='Measured field', axes=axes[0], **plot_params)
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
kwargs = dict(subjects_dir=subjects_dir, hemi='split', smoothing_steps=4, time_unit='s', initial_time=0.05, size=1200, views=['lat', 'med']) clim = dict(kind='value', pos_lims=[1e-9, 1e-8, 1e-7]) figs = [mlab.figure(1), mlab.figure(2), mlab.figure(3), mlab.figure(4)] brain_gen = stc_gen.plot(clim=clim, figure=figs, **kwargs) ############################################################################### # Simulate sensor-space signals # ----------------------------- # # Use the forward solution and add Gaussian noise to simulate sensor-space # (evoked) data from the known source-space signals. The amount of noise is # controlled by `evoked_snr` (higher values imply less noise). # evoked_gen = simulate_evoked(fwd, stc_gen, evoked.info, cov, evoked_snr, tmin=0., tmax=1., random_state=seed) # Map the simulated sensor-space data to source-space using the inverse # operator. stc_inv = apply_inverse(evoked_gen, inv_op, lambda2, method=method) ############################################################################### # Plot the point-spread of corrupted signal # ----------------------------------------- # # Notice that after applying the forward- and inverse-operators to the known # point sources that the point sources have spread across the source-space. # This spread is due to the minimum norm solution so that the signal leaks to # nearby vertices with similar orientations so that signal ends up crossing the # sulci and gyri. figs = [mlab.figure(5), mlab.figure(6), mlab.figure(7), mlab.figure(8)]
def test_dipole_fitting(tmpdir): """Test dipole fitting.""" amp = 100e-9 tempdir = str(tmpdir) rng = np.random.RandomState(0) fname_dtemp = op.join(tempdir, 'test.dip') fname_sim = op.join(tempdir, 'test-ave.fif') fwd = convert_forward_solution(read_forward_solution(fname_fwd), surf_ori=False, force_fixed=True, use_cps=True) evoked = read_evokeds(fname_evo)[0] cov = read_cov(fname_cov) n_per_hemi = 5 vertices = [np.sort(rng.permutation(s['vertno'])[:n_per_hemi]) for s in fwd['src']] nv = sum(len(v) for v in vertices) stc = SourceEstimate(amp * np.eye(nv), vertices, 0, 0.001) evoked = simulate_evoked(fwd, stc, evoked.info, cov, nave=evoked.nave, random_state=rng) # For speed, let's use a subset of channels (strange but works) picks = np.sort(np.concatenate([ pick_types(evoked.info, meg=True, eeg=False)[::2], pick_types(evoked.info, meg=False, eeg=True)[::2]])) evoked.pick_channels([evoked.ch_names[p] for p in picks]) evoked.add_proj(make_eeg_average_ref_proj(evoked.info)) write_evokeds(fname_sim, evoked) # Run MNE-C version run_subprocess([ 'mne_dipole_fit', '--meas', fname_sim, '--meg', '--eeg', '--noise', fname_cov, '--dip', fname_dtemp, '--mri', fname_fwd, '--reg', '0', '--tmin', '0', ]) dip_c = read_dipole(fname_dtemp) # Run mne-python version sphere = make_sphere_model(head_radius=0.1) with pytest.warns(RuntimeWarning, match='projection'): dip, residual = fit_dipole(evoked, cov, sphere, fname_fwd) assert isinstance(residual, Evoked) # Sanity check: do our residuals have less power than orig data? data_rms = np.sqrt(np.sum(evoked.data ** 2, axis=0)) resi_rms = np.sqrt(np.sum(residual.data ** 2, axis=0)) assert (data_rms > resi_rms * 0.95).all(), \ '%s (factor: %s)' % ((data_rms / resi_rms).min(), 0.95) # Compare to original points transform_surface_to(fwd['src'][0], 'head', fwd['mri_head_t']) transform_surface_to(fwd['src'][1], 'head', fwd['mri_head_t']) assert fwd['src'][0]['coord_frame'] == FIFF.FIFFV_COORD_HEAD src_rr = np.concatenate([s['rr'][v] for s, v in zip(fwd['src'], vertices)], axis=0) src_nn = np.concatenate([s['nn'][v] for s, v in zip(fwd['src'], vertices)], axis=0) # MNE-C skips the last "time" point :( out = dip.crop(dip_c.times[0], dip_c.times[-1]) assert (dip is out) src_rr, src_nn = src_rr[:-1], src_nn[:-1] # check that we did about as well corrs, dists, gc_dists, amp_errs, gofs = [], [], [], [], [] for d in (dip_c, dip): new = d.pos diffs = new - src_rr corrs += [np.corrcoef(src_rr.ravel(), new.ravel())[0, 1]] dists += [np.sqrt(np.mean(np.sum(diffs * diffs, axis=1)))] gc_dists += [180 / np.pi * np.mean(np.arccos(np.sum(src_nn * d.ori, axis=1)))] amp_errs += [np.sqrt(np.mean((amp - d.amplitude) ** 2))] gofs += [np.mean(d.gof)] # XXX possibly some OpenBLAS numerical differences make # things slightly worse for us factor = 0.7 assert dists[0] / factor >= dists[1], 'dists: %s' % dists assert corrs[0] * factor <= corrs[1], 'corrs: %s' % corrs assert gc_dists[0] / factor >= gc_dists[1] * 0.8, \ 'gc-dists (ori): %s' % gc_dists assert amp_errs[0] / factor >= amp_errs[1],\ 'amplitude errors: %s' % amp_errs # This one is weird because our cov/sim/picking is weird assert gofs[0] * factor <= gofs[1] * 2, 'gof: %s' % gofs
def test_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['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_dipole_fitting(): """Test dipole fitting.""" amp = 10e-9 tempdir = _TempDir() rng = np.random.RandomState(0) fname_dtemp = op.join(tempdir, 'test.dip') fname_sim = op.join(tempdir, 'test-ave.fif') fwd = convert_forward_solution(read_forward_solution(fname_fwd), surf_ori=False, force_fixed=True) evoked = read_evokeds(fname_evo)[0] cov = read_cov(fname_cov) n_per_hemi = 5 vertices = [np.sort(rng.permutation(s['vertno'])[:n_per_hemi]) for s in fwd['src']] nv = sum(len(v) for v in vertices) stc = SourceEstimate(amp * np.eye(nv), vertices, 0, 0.001) evoked = simulate_evoked(fwd, stc, evoked.info, cov, snr=20, random_state=rng) # For speed, let's use a subset of channels (strange but works) picks = np.sort(np.concatenate([ pick_types(evoked.info, meg=True, eeg=False)[::2], pick_types(evoked.info, meg=False, eeg=True)[::2]])) evoked.pick_channels([evoked.ch_names[p] for p in picks]) evoked.add_proj(make_eeg_average_ref_proj(evoked.info)) write_evokeds(fname_sim, evoked) # Run MNE-C version run_subprocess([ 'mne_dipole_fit', '--meas', fname_sim, '--meg', '--eeg', '--noise', fname_cov, '--dip', fname_dtemp, '--mri', fname_fwd, '--reg', '0', '--tmin', '0', ]) dip_c = read_dipole(fname_dtemp) # Run mne-python version sphere = make_sphere_model(head_radius=0.1) dip, residuals = fit_dipole(evoked, fname_cov, sphere, fname_fwd) # Sanity check: do our residuals have less power than orig data? data_rms = np.sqrt(np.sum(evoked.data ** 2, axis=0)) resi_rms = np.sqrt(np.sum(residuals ** 2, axis=0)) factor = 1. # XXX weird, inexplicable differenc for 3.5 build we'll assume is due to # Anaconda bug for now... if os.getenv('TRAVIS', 'false') == 'true' and \ sys.version[:3] in ('3.5', '2.7'): factor = 0.8 assert_true((data_rms > factor * resi_rms).all(), msg='%s (factor: %s)' % ((data_rms / resi_rms).min(), factor)) # Compare to original points transform_surface_to(fwd['src'][0], 'head', fwd['mri_head_t']) transform_surface_to(fwd['src'][1], 'head', fwd['mri_head_t']) src_rr = np.concatenate([s['rr'][v] for s, v in zip(fwd['src'], vertices)], axis=0) src_nn = np.concatenate([s['nn'][v] for s, v in zip(fwd['src'], vertices)], axis=0) # MNE-C skips the last "time" point :( dip.crop(dip_c.times[0], dip_c.times[-1]) src_rr, src_nn = src_rr[:-1], src_nn[:-1] # check that we did at least as well corrs, dists, gc_dists, amp_errs, gofs = [], [], [], [], [] for d in (dip_c, dip): new = d.pos diffs = new - src_rr corrs += [np.corrcoef(src_rr.ravel(), new.ravel())[0, 1]] dists += [np.sqrt(np.mean(np.sum(diffs * diffs, axis=1)))] gc_dists += [180 / np.pi * np.mean(np.arccos(np.sum(src_nn * d.ori, axis=1)))] amp_errs += [np.sqrt(np.mean((amp - d.amplitude) ** 2))] gofs += [np.mean(d.gof)] assert_true(dists[0] >= dists[1] * factor, 'dists: %s' % dists) assert_true(corrs[0] <= corrs[1] / factor, 'corrs: %s' % corrs) assert_true(gc_dists[0] >= gc_dists[1] * factor, 'gc-dists (ori): %s' % gc_dists) assert_true(amp_errs[0] >= amp_errs[1] * factor, 'amplitude errors: %s' % amp_errs) assert_true(gofs[0] <= gofs[1] / factor, 'gof: %s' % gofs)
def test_dipole_fitting(): """Test dipole fitting""" amp = 10e-9 tempdir = _TempDir() rng = np.random.RandomState(0) fname_dtemp = op.join(tempdir, "test.dip") fname_sim = op.join(tempdir, "test-ave.fif") fwd = convert_forward_solution(read_forward_solution(fname_fwd), surf_ori=False, force_fixed=True) evoked = read_evokeds(fname_evo)[0] cov = read_cov(fname_cov) n_per_hemi = 5 vertices = [np.sort(rng.permutation(s["vertno"])[:n_per_hemi]) for s in fwd["src"]] nv = sum(len(v) for v in vertices) stc = SourceEstimate(amp * np.eye(nv), vertices, 0, 0.001) evoked = simulate_evoked(fwd, stc, evoked.info, cov, snr=20, random_state=rng) # For speed, let's use a subset of channels (strange but works) picks = np.sort( np.concatenate( [pick_types(evoked.info, meg=True, eeg=False)[::2], pick_types(evoked.info, meg=False, eeg=True)[::2]] ) ) evoked.pick_channels([evoked.ch_names[p] for p in picks]) evoked.add_proj(make_eeg_average_ref_proj(evoked.info)) write_evokeds(fname_sim, evoked) # Run MNE-C version run_subprocess( [ "mne_dipole_fit", "--meas", fname_sim, "--meg", "--eeg", "--noise", fname_cov, "--dip", fname_dtemp, "--mri", fname_fwd, "--reg", "0", "--tmin", "0", ] ) dip_c = read_dipole(fname_dtemp) # Run mne-python version sphere = make_sphere_model(head_radius=0.1) dip, residuals = fit_dipole(evoked, fname_cov, sphere, fname_fwd) # Sanity check: do our residuals have less power than orig data? data_rms = np.sqrt(np.sum(evoked.data ** 2, axis=0)) resi_rms = np.sqrt(np.sum(residuals ** 2, axis=0)) 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) assert_true(gofs[0] <= gofs[1], "gof: %s" % gofs)
size=1200, views=['lat', 'med']) clim = dict(kind='value', pos_lims=[1e-9, 1e-8, 1e-7]) brain_gen = stc_gen.plot(clim=clim, **kwargs) ############################################################################### # Simulate sensor-space signals # ----------------------------- # # Use the forward solution and add Gaussian noise to simulate sensor-space # (evoked) data from the known source-space signals. The amount of noise is # controlled by `nave` (higher values imply less noise). # evoked_gen = simulate_evoked(fwd, stc_gen, evoked.info, cov, nave, random_state=seed) # Map the simulated sensor-space data to source-space using the inverse # operator. stc_inv = apply_inverse(evoked_gen, inv_op, lambda2, method=method) ############################################################################### # Plot the point-spread of corrupted signal # ----------------------------------------- # # Notice that after applying the forward- and inverse-operators to the known # point sources that the point sources have spread across the source-space. # This spread is due to the minimum norm solution so that the signal leaks to # nearby vertices with similar orientations so that signal ends up crossing the
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)
stc = simulate_sparse_stc(fwd['src'], n_dipoles=2, times=times, random_state=42, labels=labels, data_fun=data_fun) ############################################################################### # Generate noisy evoked data picks = mne.pick_types(raw.info, meg=True, exclude='bads') iir_filter = fit_iir_model_raw(raw, order=5, picks=picks, tmin=60, tmax=180)[1] nave = 100 # simulate average of 100 epochs evoked = simulate_evoked(fwd, stc, info, cov, nave=nave, use_cps=True, iir_filter=iir_filter) ############################################################################### # Plot plot_sparse_source_estimates(fwd['src'], stc, bgcolor=(1, 1, 1), opacity=0.5, high_resolution=True) plt.figure() plt.psd(evoked.data[0])
def test_make_forward_dipole(): """Test forward-projecting dipoles""" rng = np.random.RandomState(0) evoked = read_evokeds(fname_evo)[0] cov = read_cov(fname_cov) dip_c = read_dipole(fname_dip) # Only use magnetometers for speed! picks = pick_types(evoked.info, meg='mag', eeg=False) evoked.pick_channels([evoked.ch_names[p] for p in picks]) info = evoked.info # Make new Dipole object with n_test_dipoles picked from the dipoles # in the test dataset. n_test_dipoles = 3 # minimum 3 needed to get uneven sampling in time dipsel = np.sort(rng.permutation(np.arange(len(dip_c)))[:n_test_dipoles]) dip_test = Dipole(times=dip_c.times[dipsel], pos=dip_c.pos[dipsel], amplitude=dip_c.amplitude[dipsel], ori=dip_c.ori[dipsel], gof=dip_c.gof[dipsel]) sphere = make_sphere_model(head_radius=0.1) # Warning emitted due to uneven sampling in time with warnings.catch_warnings(record=True) as w: fwd, stc = make_forward_dipole(dip_test, sphere, info, trans=fname_trans) assert_true(issubclass(w[-1].category, RuntimeWarning)) # stc is list of VolSourceEstimate's assert_true(isinstance(stc, list)) for nd in range(n_test_dipoles): assert_true(isinstance(stc[nd], VolSourceEstimate)) # Now simulate evoked responses for each of the test dipoles, # and fit dipoles to them (sphere model, MEG and EEG) times, pos, amplitude, ori, gof = [], [], [], [], [] snr = 20. # add a tiny amount of noise to the simulated evokeds for s in stc: evo_test = simulate_evoked(fwd, s, info, cov, snr=snr, random_state=rng) # evo_test.add_proj(make_eeg_average_ref_proj(evo_test.info)) dfit, resid = fit_dipole(evo_test, cov, sphere, None) times += dfit.times.tolist() pos += dfit.pos.tolist() amplitude += dfit.amplitude.tolist() ori += dfit.ori.tolist() gof += dfit.gof.tolist() # Create a new Dipole object with the dipole fits dip_fit = Dipole(times, pos, amplitude, ori, gof) # check that true (test) dipoles and fits are "close" # cf. mne/tests/test_dipole.py diff = dip_test.pos - dip_fit.pos corr = np.corrcoef(dip_test.pos.ravel(), dip_fit.pos.ravel())[0, 1] dist = np.sqrt(np.mean(np.sum(diff * diff, axis=1))) gc_dist = 180 / np.pi * \ np.mean(np.arccos(np.sum(dip_test.ori * dip_fit.ori, axis=1))) amp_err = np.sqrt(np.mean((dip_test.amplitude - dip_fit.amplitude)**2)) # Make sure each coordinate is close to reference # NB tolerance should be set relative to snr of simulated evoked! assert_allclose(dip_fit.pos, dip_test.pos, rtol=0, atol=1e-2, err_msg='position mismatch') assert_true(dist < 1e-2, 'dist: %s' % dist) # within 1 cm assert_true(corr > 1 - 1e-2, 'corr: %s' % corr) assert_true(gc_dist < 20, 'gc_dist: %s' % gc_dist) # less than 20 degrees assert_true(amp_err < 10e-9, 'amp_err: %s' % amp_err) # within 10 nAm # Make sure rejection works with BEM: one dipole at z=1m # NB _make_forward.py:_prepare_for_forward will raise a RuntimeError # if no points are left after min_dist exclusions, hence 2 dips here! dip_outside = Dipole(times=[0., 0.001], pos=[[0., 0., 1.0], [0., 0., 0.040]], amplitude=[100e-9, 100e-9], ori=[[1., 0., 0.], [1., 0., 0.]], gof=1) assert_raises(ValueError, make_forward_dipole, dip_outside, fname_bem, info, fname_trans) # if we get this far, can safely assume the code works with BEMs too # -> use sphere again below for speed # Now make an evenly sampled set of dipoles, some simultaneous, # should return a VolSourceEstimate regardless times = [0., 0., 0., 0.001, 0.001, 0.002] pos = np.random.rand(6, 3) * 0.020 + \ np.array([0., 0., 0.040])[np.newaxis, :] amplitude = np.random.rand(6) * 100e-9 ori = np.eye(6, 3) + np.eye(6, 3, -3) gof = np.arange(len(times)) / len(times) # arbitrary dip_even_samp = Dipole(times, pos, amplitude, ori, gof) fwd, stc = make_forward_dipole(dip_even_samp, sphere, info, trans=fname_trans) assert_true(isinstance, VolSourceEstimate) assert_allclose(stc.times, np.arange(0., 0.003, 0.001))
def test_make_forward_dipole(): """Test forward-projecting dipoles.""" rng = np.random.RandomState(0) evoked = read_evokeds(fname_evo)[0] cov = read_cov(fname_cov) cov['projs'] = [] # avoid proj warning dip_c = read_dipole(fname_dip) # Only use magnetometers for speed! picks = pick_types(evoked.info, meg='mag', eeg=False)[::8] evoked.pick_channels([evoked.ch_names[p] for p in picks]) evoked.info.normalize_proj() info = evoked.info # Make new Dipole object with n_test_dipoles picked from the dipoles # in the test dataset. n_test_dipoles = 3 # minimum 3 needed to get uneven sampling in time dipsel = np.sort(rng.permutation(np.arange(len(dip_c)))[:n_test_dipoles]) dip_test = Dipole(times=dip_c.times[dipsel], pos=dip_c.pos[dipsel], amplitude=dip_c.amplitude[dipsel], ori=dip_c.ori[dipsel], gof=dip_c.gof[dipsel]) sphere = make_sphere_model(head_radius=0.1) # Warning emitted due to uneven sampling in time with pytest.warns(RuntimeWarning, match='unevenly spaced'): fwd, stc = make_forward_dipole(dip_test, sphere, info, trans=fname_trans) # stc is list of VolSourceEstimate's assert isinstance(stc, list) for n_dip in range(n_test_dipoles): assert isinstance(stc[n_dip], VolSourceEstimate) # Now simulate evoked responses for each of the test dipoles, # and fit dipoles to them (sphere model, MEG and EEG) times, pos, amplitude, ori, gof = [], [], [], [], [] nave = 200 # add a tiny amount of noise to the simulated evokeds for s in stc: evo_test = simulate_evoked(fwd, s, info, cov, nave=nave, random_state=rng) # evo_test.add_proj(make_eeg_average_ref_proj(evo_test.info)) dfit, resid = fit_dipole(evo_test, cov, sphere, None) times += dfit.times.tolist() pos += dfit.pos.tolist() amplitude += dfit.amplitude.tolist() ori += dfit.ori.tolist() gof += dfit.gof.tolist() # Create a new Dipole object with the dipole fits dip_fit = Dipole(times, pos, amplitude, ori, gof) # check that true (test) dipoles and fits are "close" # cf. mne/tests/test_dipole.py diff = dip_test.pos - dip_fit.pos corr = np.corrcoef(dip_test.pos.ravel(), dip_fit.pos.ravel())[0, 1] dist = np.sqrt(np.mean(np.sum(diff * diff, axis=1))) gc_dist = 180 / np.pi * \ np.mean(np.arccos(np.sum(dip_test.ori * dip_fit.ori, axis=1))) amp_err = np.sqrt(np.mean((dip_test.amplitude - dip_fit.amplitude) ** 2)) # Make sure each coordinate is close to reference # NB tolerance should be set relative to snr of simulated evoked! assert_allclose(dip_fit.pos, dip_test.pos, rtol=0, atol=1e-2, err_msg='position mismatch') assert dist < 1e-2 # within 1 cm assert corr > 0.985 assert gc_dist < 20 # less than 20 degrees assert amp_err < 10e-9 # within 10 nAm # Make sure rejection works with BEM: one dipole at z=1m # NB _make_forward.py:_prepare_for_forward will raise a RuntimeError # if no points are left after min_dist exclusions, hence 2 dips here! dip_outside = Dipole(times=[0., 0.001], pos=[[0., 0., 1.0], [0., 0., 0.040]], amplitude=[100e-9, 100e-9], ori=[[1., 0., 0.], [1., 0., 0.]], gof=1) pytest.raises(ValueError, make_forward_dipole, dip_outside, fname_bem, info, fname_trans) # if we get this far, can safely assume the code works with BEMs too # -> use sphere again below for speed # Now make an evenly sampled set of dipoles, some simultaneous, # should return a VolSourceEstimate regardless times = [0., 0., 0., 0.001, 0.001, 0.002] pos = np.random.rand(6, 3) * 0.020 + \ np.array([0., 0., 0.040])[np.newaxis, :] amplitude = np.random.rand(6) * 100e-9 ori = np.eye(6, 3) + np.eye(6, 3, -3) gof = np.arange(len(times)) / len(times) # arbitrary dip_even_samp = Dipole(times, pos, amplitude, ori, gof) fwd, stc = make_forward_dipole(dip_even_samp, sphere, info, trans=fname_trans) assert isinstance(stc, VolSourceEstimate) assert_allclose(stc.times, np.arange(0., 0.003, 0.001))
def test_dipole_fitting(): """Test dipole fitting.""" amp = 100e-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, 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 warnings.catch_warnings(record=True): dip, residuals = fit_dipole(evoked, 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 * 0.95).all(), msg='%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_equal(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_true(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)] factor = 0.8 assert_true(dists[0] / factor >= dists[1], 'dists: %s' % dists) assert_true(corrs[0] * factor <= corrs[1], 'corrs: %s' % corrs) assert_true(gc_dists[0] / factor >= gc_dists[1] * 0.8, 'gc-dists (ori): %s' % gc_dists) assert_true(amp_errs[0] / factor >= amp_errs[1], 'amplitude errors: %s' % amp_errs) # This one is weird because our cov/sim/picking is weird assert_true(gofs[0] * factor <= gofs[1] * 2, 'gof: %s' % gofs)
# Generate source time courses from 2 dipoles and the correspond evoked data times = np.arange(300, dtype=np.float) / raw.info['sfreq'] - 0.1 rng = np.random.RandomState(42) def data_fun(times): """Function to generate random source time courses""" return (1e-9 * np.sin(30. * times) * np.exp(- (times - 0.15 + 0.05 * rng.randn(1)) ** 2 / 0.01)) stc = simulate_sparse_stc(fwd['src'], n_dipoles=2, times=times, random_state=42, labels=labels, data_fun=data_fun) ############################################################################### # Generate noisy evoked data picks = mne.pick_types(raw.info, meg=True, exclude='bads') iir_filter = fit_iir_model_raw(raw, order=5, picks=picks, tmin=60, tmax=180)[1] snr = 6. # dB evoked = simulate_evoked(fwd, stc, info, cov, snr, iir_filter=iir_filter) ############################################################################### # Plot plot_sparse_source_estimates(fwd['src'], stc, bgcolor=(1, 1, 1), opacity=0.5, high_resolution=True) plt.figure() plt.psd(evoked.data[0]) evoked.plot()
def test_simulate_evoked(): """Test simulation of evoked data.""" raw = read_raw_fif(raw_fname) fwd = read_forward_solution(fwd_fname, force_fixed=True) 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)