def compute_surface_laplacian(epochs: Epochs, verbose: bool = True) -> Epochs: """ Performs the surface Laplacian transform on the Epochs instance For more information about the transform parameters please refer to Cohen, M. X. (2014). Analyzing neural time series data: theory and practice . MIT press. For more information about this function in particular, visit the MNE documentation at: https://mne.tools/dev/generated/mne.preprocessing.compute_current_source_density.html Parameters ---------- epochs: the epochs to be transformed verbose: whether to visualize the power spectral densities before and after the Laplacian transform Returns ------- Raw instance """ epochs_csd = compute_current_source_density(epochs.copy()) if verbose: fig, axes_subplot = plt.subplots( nrows=2, ncols=1, sharex="all", sharey="all", dpi=220 ) epochs.plot_psd(ax=axes_subplot[0], show=False, fmax=60) epochs_csd.plot_psd(ax=axes_subplot[1], show=False, fmax=60) fig.show() return epochs_csd
def test_csd_matlab(evoked_csd_sphere): """Test replication of the CSD MATLAB toolbox.""" evoked, csd, sphere = evoked_csd_sphere evoked_csd = compute_current_source_density(evoked, sphere=sphere) assert_allclose(linalg.norm(csd), 0.00177, atol=1e-5) # If we don't project onto the sphere, we get 1e-12 accuracy here, # but it's a bad assumption for real data! # Also, we divide by (radius ** 2) to get to units of V/m², unclear # why this isn't done in the upstream implementation evoked_csd_data = evoked_csd.data * sphere[-1] ** 2 assert_allclose(evoked_csd_data, csd, atol=2e-7) with pytest.raises(ValueError, match=('CSD already applied, ' 'should not be reapplied')): compute_current_source_density(evoked_csd, sphere=sphere) # 1e-5 here if we don't project... assert_allclose(evoked_csd_data.sum(), 0.02455, atol=2e-3)
def test_csd_epochs(tmp_path): """Test making epochs, saving to disk and loading.""" raw = read_raw_fif(raw_fname) raw.pick_types(eeg=True, stim=True).load_data() events = find_events(raw) epochs = Epochs(raw, events, reject=dict(eeg=1e-4), preload=True) epochs = compute_current_source_density(epochs) epo_fname = tmp_path / 'test_csd_epo.fif' epochs.save(epo_fname) epochs2 = read_epochs(epo_fname, preload=True) assert_allclose(epochs._data, epochs2._data)
def test_pick_types_csd(): """Test pick_types(csd=True).""" # info with laplacian/CSD channels at indices 1, 2 names = ['F1', 'F2', 'C1', 'C2', 'A1', 'A2', 'misc1', 'CSD1'] info1 = create_info( names, 256, ["eeg", "eeg", "eeg", "eeg", "mag", "mag", 'misc', 'csd']) raw = RawArray(np.zeros((8, 512)), info1) raw.set_montage(make_standard_montage('standard_1020'), verbose='error') raw_csd = compute_current_source_density(raw, verbose='error') assert_array_equal(pick_types(info1, csd=True), [7]) # pick from the raw object assert raw_csd.copy().pick_types(csd=True).ch_names == [ 'F1', 'F2', 'C1', 'C2', 'CSD1' ]
def test_csd_matlab(raw_epochs_sphere): """Test replication of the CSD MATLAB toolbox.""" raw, epochs, sphere = raw_epochs_sphere n_epochs = len(epochs) picks = pick_types(epochs.info, meg=False, eeg=True, eog=False, stim=False, exclude='bads') csd_data = sio.loadmat(csd_fname) montage = make_standard_montage('EGI_256', head_size=0.100004) positions = np.array([montage.dig[pick]['r'] * 10 for pick in picks]) cosang = np.dot(positions, positions.T) G = _calc_g(cosang) assert_allclose(G, csd_data['G'], atol=1e-3) H = _calc_h(cosang) assert_allclose(H, csd_data['H'], atol=1e-3) for i in range(n_epochs): epochs_csd = compute_current_source_density(epochs, sphere=sphere) assert_allclose(epochs_csd.get_data(), csd_data['X'], atol=1e-3) # test raw csd_raw = compute_current_source_density(raw, sphere=sphere) with pytest.raises(ValueError, match=('CSD already applied, ' 'should not be reapplied')): compute_current_source_density(csd_raw, sphere=sphere) csd_raw_test_array = np.array([[2.29938168e-07, 1.55737642e-07], [-9.63976630e-09, 8.31646698e-09], [-2.30898926e-07, -1.56250505e-07], [-1.81081104e-07, -5.46661150e-08], [-9.08835568e-08, 1.61788422e-07], [5.38295661e-09, 3.75240220e-07]]) assert_allclose(csd_raw._data[:, 100:102], csd_raw_test_array, atol=1e-3) csd_epochs = compute_current_source_density(epochs, sphere=sphere) assert_allclose(csd_epochs._data, csd_data['X'], atol=1e-3) csd_epochs = compute_current_source_density(epochs, sphere=sphere) csd_evoked = compute_current_source_density(epochs.average(), sphere=sphere) assert_allclose(csd_evoked.data, csd_data['X'].mean(0), atol=1e-3) assert_allclose(csd_evoked.data, csd_epochs._data.mean(0), atol=1e-3)
def test_csd_fif(): """Test applying CSD to FIF data.""" raw = read_raw_fif(raw_fname).load_data() raw.info['bads'] = [] picks = pick_types(raw.info, meg=False, eeg=True) assert 'csd' not in raw orig_eeg = raw.get_data('eeg') assert len(orig_eeg) == 60 raw_csd = compute_current_source_density(raw) assert 'eeg' not in raw_csd new_eeg = raw_csd.get_data('csd') assert not (orig_eeg == new_eeg).any() # reset the only things that should change, and assert objects are the same assert raw_csd.info['custom_ref_applied'] == FIFF.FIFFV_MNE_CUSTOM_REF_CSD raw_csd.info['custom_ref_applied'] = 0 for pick in picks: ch = raw_csd.info['chs'][pick] assert ch['coil_type'] == FIFF.FIFFV_COIL_EEG_CSD assert ch['unit'] == FIFF.FIFF_UNIT_V_M2 ch.update(coil_type=FIFF.FIFFV_COIL_EEG, unit=FIFF.FIFF_UNIT_V) raw_csd._data[pick] = raw._data[pick] assert object_diff(raw.info, raw_csd.info) == ''
def test_csd_degenerate(evoked_csd_sphere): """Test degenerate conditions.""" evoked, csd, sphere = evoked_csd_sphere warn_evoked = evoked.copy() warn_evoked.info['bads'].append(warn_evoked.ch_names[3]) with pytest.raises(ValueError, match='Either drop.*or interpolate'): compute_current_source_density(warn_evoked) with pytest.raises(TypeError, match='must be an instance of'): compute_current_source_density(None) fail_evoked = evoked.copy() with pytest.raises(ValueError, match='Zero or infinite position'): for ch in fail_evoked.info['chs']: ch['loc'][:3] = np.array([0, 0, 0]) compute_current_source_density(fail_evoked, sphere=sphere) with pytest.raises(ValueError, match='Zero or infinite position'): fail_evoked.info['chs'][3]['loc'][:3] = np.inf compute_current_source_density(fail_evoked, sphere=sphere) with pytest.raises(ValueError, match='No EEG channels found.'): fail_evoked = evoked.copy() fail_evoked.set_channel_types({ch_name: 'ecog' for ch_name in fail_evoked.ch_names}) compute_current_source_density(fail_evoked, sphere=sphere) with pytest.raises(TypeError, match='lambda2'): compute_current_source_density(evoked, lambda2='0', sphere=sphere) with pytest.raises(ValueError, match='lambda2 must be between 0 and 1'): compute_current_source_density(evoked, lambda2=2, sphere=sphere) with pytest.raises(TypeError, match='stiffness must be'): compute_current_source_density(evoked, stiffness='0', sphere=sphere) with pytest.raises(ValueError, match='stiffness must be non-negative'): compute_current_source_density(evoked, stiffness=-2, sphere=sphere) with pytest.raises(TypeError, match='n_legendre_terms must be'): compute_current_source_density(evoked, n_legendre_terms=0.1, sphere=sphere) with pytest.raises(ValueError, match=('n_legendre_terms must be ' 'greater than 0')): compute_current_source_density(evoked, n_legendre_terms=0, sphere=sphere) with pytest.raises(ValueError, match='sphere must be'): compute_current_source_density(evoked, sphere=-0.1) with pytest.raises(ValueError, match=('sphere radius must be ' 'greater than 0')): compute_current_source_density(evoked, sphere=(-0.1, 0., 0., -1.)) with pytest.raises(TypeError): compute_current_source_density(evoked, copy=2, sphere=sphere) # gh-7859 raw = RawArray(evoked.data, evoked.info) epochs = Epochs( raw, [[0, 0, 1]], tmin=0, tmax=evoked.times[-1] - evoked.times[0], baseline=None, preload=False, proj=False) epochs.drop_bad() assert len(epochs) == 1 assert_allclose(epochs.get_data()[0], evoked.data) with pytest.raises(RuntimeError, match='Computing CSD requires.*preload'): compute_current_source_density(epochs) epochs.load_data() raw = compute_current_source_density(raw) assert not np.allclose(raw.get_data(), evoked.data) evoked = compute_current_source_density(evoked) assert_allclose(raw.get_data(), evoked.data) epochs = compute_current_source_density(epochs) assert_allclose(epochs.get_data()[0], evoked.data)
def test_csd_degenerate(evoked_csd_sphere): """Test degenerate conditions.""" evoked, csd, sphere = evoked_csd_sphere warn_evoked = evoked.copy() warn_evoked.info['bads'].append(warn_evoked.ch_names[3]) with pytest.raises(ValueError, match='Either drop.*or interpolate'): compute_current_source_density(warn_evoked) with pytest.raises(TypeError, match='must be an instance of'): compute_current_source_density(None) fail_evoked = evoked.copy() with pytest.raises(ValueError, match='Zero or infinite position'): for ch in fail_evoked.info['chs']: ch['loc'][:3] = np.array([0, 0, 0]) compute_current_source_density(fail_evoked, sphere=sphere) with pytest.raises(ValueError, match='Zero or infinite position'): fail_evoked.info['chs'][3]['loc'][:3] = np.inf compute_current_source_density(fail_evoked, sphere=sphere) with pytest.raises(ValueError, match='No EEG channels found.'): fail_evoked = evoked.copy() fail_evoked.set_channel_types( {ch_name: 'ecog' for ch_name in fail_evoked.ch_names}) compute_current_source_density(fail_evoked, sphere=sphere) with pytest.raises(TypeError, match='lambda2'): compute_current_source_density(evoked, lambda2='0', sphere=sphere) with pytest.raises(ValueError, match='lambda2 must be between 0 and 1'): compute_current_source_density(evoked, lambda2=2, sphere=sphere) with pytest.raises(TypeError, match='stiffness must be'): compute_current_source_density(evoked, stiffness='0', sphere=sphere) with pytest.raises(ValueError, match='stiffness must be non-negative'): compute_current_source_density(evoked, stiffness=-2, sphere=sphere) with pytest.raises(TypeError, match='n_legendre_terms must be'): compute_current_source_density(evoked, n_legendre_terms=0.1, sphere=sphere) with pytest.raises(ValueError, match=('n_legendre_terms must be ' 'greater than 0')): compute_current_source_density(evoked, n_legendre_terms=0, sphere=sphere) with pytest.raises(ValueError, match='sphere must be'): compute_current_source_density(evoked, sphere=-0.1) with pytest.raises(ValueError, match=('sphere radius must be ' 'greater than 0')): compute_current_source_density(evoked, sphere=(-0.1, 0., 0., -1.)) with pytest.raises(TypeError): compute_current_source_density(evoked, copy=2, sphere=sphere)
window = .5 points = (epochs.tmax - epochs.tmin) * sfreq for i in range(points): t_start = epochs.tmin + (i / sfreq) t_end = t_start + window print(t_start, t_end) if t_end > epochs.tmax: break window_epoch = epochs.copy().crop(tmin=t_start, tmax=t_end) window_epoch = window_epoch.copy().resample(sfreq=500) # hjort-csd centered at c3 at 500Hz csd = compute_current_source_density(window_epoch, sphere=sphere_center) csd_data = csd.get_data() # fir forward-backward filter 8-12 Hz from mne.filter import create_filter filt = create_filter(data=csd_data, sfreq=sfreq, l_freq=8, h_freq=12, method='iir') csd_filtered = csd.filter(l_freq=8, h_freq=12, method='iir') # trimming of 64 ms start and end # AR prediction Yule-Walker order = 30