def test_tf_dics(_load_forward, idx, mat_tol, vol_tol): """Test 5D time-frequency beamforming based on DICS.""" fwd_free, fwd_surf, fwd_fixed, _ = _load_forward epochs, _, _, source_vertno, label, vertices, source_ind = \ _simulate_data(fwd_fixed, idx) reg = 1 # Lots of regularization for our toy dataset tmin = 0 tmax = 9 tstep = 4 win_lengths = [5, 5] frequencies = [10, 20] freq_bins = [(8, 12), (18, 22)] with pytest.raises(RuntimeError, match='several sensor types'): stcs = tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, freq_bins=freq_bins, frequencies=frequencies, decim=10, reg=reg, label=label) epochs.pick_types(meg='grad') # Compute DICS for two time windows and two frequencies for mode in ['fourier', 'multitaper', 'cwt_morlet']: stcs = tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode=mode, freq_bins=freq_bins, frequencies=frequencies, decim=10, reg=reg, label=label) # Did we find the true source at 20 Hz? dist = _fwd_dist(stcs[1], fwd_surf, vertices, source_ind, tidx=0) assert dist == 0 dist = _fwd_dist(stcs[1], fwd_surf, vertices, source_ind, tidx=1) assert dist == 0 # 20 Hz power should decrease over time assert stcs[1].data[source_ind, 0] > stcs[1].data[source_ind, 1] # 20 Hz power should be more than 10 Hz power at the true source assert stcs[1].data[source_ind, 0] > stcs[0].data[source_ind, 0] # Manually compute source power and compare with the last tf_dics result. source_power = [] time_windows = [(0, 5), (4, 9)] for time_window in time_windows: csd = csd_morlet(epochs, frequencies=[frequencies[1]], tmin=time_window[0], tmax=time_window[1], decim=10) csd = csd.sum() csd._data /= csd.n_fft filters = make_dics(epochs.info, fwd_surf, csd, reg=reg, label=label) stc_source_power, _ = apply_dics_csd(csd, filters) source_power.append(stc_source_power.data) # Comparing tf_dics results with dics_source_power results assert_allclose(stcs[1].data, np.array(source_power).squeeze().T, atol=0) # Test using noise csds. We're going to use identity matrices. That way, # since we're using unit-noise-gain weight normalization, there should be # no effect. stcs = tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode='cwt_morlet', frequencies=frequencies, decim=10, reg=reg, label=label, normalize_fwd=False, weight_norm='unit-noise-gain') noise_csd = csd.copy() inds = np.triu_indices(csd.n_channels) # Using [:, :] syntax for in-place broadcasting noise_csd._data[:, :] = 2 * np.eye(csd.n_channels)[inds][:, np.newaxis] noise_csd.n_fft = 2 # Dividing by n_fft should yield an identity CSD noise_csds = [noise_csd, noise_csd] # Two frequency bins stcs_norm = tf_dics(epochs, fwd_surf, noise_csds, tmin, tmax, tstep, win_lengths, mode='cwt_morlet', frequencies=frequencies, decim=10, reg=reg, label=label, normalize_fwd=False, weight_norm='unit-noise-gain') assert_allclose(stcs_norm[0].data, stcs[0].data, atol=0) assert_allclose(stcs_norm[1].data, stcs[1].data, atol=0) # Test invalid parameter combinations with pytest.raises(ValueError, match='fourier.*freq_bins" parameter'): tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode='fourier', freq_bins=None) with pytest.raises(ValueError, match='cwt_morlet.*frequencies" param'): tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode='cwt_morlet', frequencies=None) # Test if incorrect number of noise CSDs is detected with pytest.raises(ValueError, match='One noise CSD object expected per'): tf_dics(epochs, fwd_surf, [noise_csds[0]], tmin, tmax, tstep, win_lengths, freq_bins=freq_bins) # Test if freq_bins and win_lengths incompatibility is detected with pytest.raises(ValueError, match='One time window length expected'): tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths=[0, 1, 2], freq_bins=freq_bins) # Test if time step exceeding window lengths is detected with pytest.raises(ValueError, match='Time step should not be larger'): tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep=0.15, win_lengths=[0.2, 0.1], freq_bins=freq_bins) # Test if incorrect number of n_ffts is detected with pytest.raises(ValueError, match='When specifying number of FFT'): tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, freq_bins=freq_bins, n_ffts=[1]) # Test if incorrect number of mt_bandwidths is detected with pytest.raises(ValueError, match='When using multitaper mode and'): tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths=win_lengths, freq_bins=freq_bins, mode='multitaper', mt_bandwidths=[20]) # Test if subtracting evoked responses yields NaN's, since we only have one # epoch. Suppress division warnings. assert len(epochs) == 1, len(epochs) with np.errstate(invalid='ignore'): stcs = tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode='cwt_morlet', frequencies=frequencies, subtract_evoked=True, reg=reg, label=label, decim=20) assert np.all(np.isnan(stcs[0].data))
def test_tf_dics(): """Test 5D time-frequency beamforming based on DICS.""" fwd_free, fwd_surf, fwd_fixed, fwd_vol, label = _load_forward() epochs, evoked, _, source_vertno = _simulate_data(fwd_fixed) vertices = np.intersect1d(label.vertices, fwd_free['src'][0]['vertno']) source_ind = vertices.tolist().index(source_vertno) reg = 1 # Lots of regularization for our toy dataset tmin = 0 tmax = 9 tstep = 4 win_lengths = [5, 5] frequencies = [10, 20] freq_bins = [(8, 12), (18, 22)] # Compute DICS for two time windows and two frequencies for mode in ['fourier', 'multitaper', 'cwt_morlet']: stcs = tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode=mode, freq_bins=freq_bins, frequencies=frequencies, decim=10, reg=reg, label=label) # Did we find the true source at 20 Hz? assert np.argmax(stcs[1].data[:, 0]) == source_ind assert np.argmax(stcs[1].data[:, 1]) == source_ind # 20 Hz power should decrease over time assert stcs[1].data[source_ind, 0] > stcs[1].data[source_ind, 1] # 20 Hz power should be more than 10 Hz power at the true source assert stcs[1].data[source_ind, 0] > stcs[0].data[source_ind, 0] # Manually compute source power and compare with the last tf_dics result. source_power = [] time_windows = [(0, 5), (4, 9)] for time_window in time_windows: csd = csd_morlet(epochs, frequencies=[frequencies[1]], tmin=time_window[0], tmax=time_window[1], decim=10) csd = csd.sum() csd._data /= csd.n_fft filters = make_dics(epochs.info, fwd_surf, csd, reg=reg, label=label) stc_source_power, _ = apply_dics_csd(csd, filters) source_power.append(stc_source_power.data) # Comparing tf_dics results with dics_source_power results assert_allclose(stcs[1].data, np.array(source_power).squeeze().T, atol=0) # Test using noise csds. We're going to use identity matrices. That way, # since we're using unit-noise-gain weight normalization, there should be # no effect. stcs = tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode='cwt_morlet', frequencies=frequencies, decim=10, reg=reg, label=label, normalize_fwd=False, weight_norm='unit-noise-gain') noise_csd = csd.copy() inds = np.triu_indices(csd.n_channels) # Using [:, :] syntax for in-place broadcasting noise_csd._data[:, :] = 2 * np.eye(csd.n_channels)[inds][:, np.newaxis] noise_csd.n_fft = 2 # Dividing by n_fft should yield an identity CSD noise_csds = [noise_csd, noise_csd] # Two frequency bins stcs_norm = tf_dics(epochs, fwd_surf, noise_csds, tmin, tmax, tstep, win_lengths, mode='cwt_morlet', frequencies=frequencies, decim=10, reg=reg, label=label, normalize_fwd=False, weight_norm='unit-noise-gain') assert_allclose(stcs_norm[0].data, stcs[0].data, atol=0) assert_allclose(stcs_norm[1].data, stcs[1].data, atol=0) # Test invalid parameter combinations raises(ValueError, tf_dics, epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode='fourier', freq_bins=None) raises(ValueError, tf_dics, epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode='cwt_morlet', frequencies=None) # Test if incorrect number of noise CSDs is detected raises(ValueError, tf_dics, epochs, fwd_surf, [noise_csds[0]], tmin, tmax, tstep, win_lengths, freq_bins=freq_bins) # Test if freq_bins and win_lengths incompatibility is detected raises(ValueError, tf_dics, epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths=[0, 1, 2], freq_bins=freq_bins) # Test if time step exceeding window lengths is detected raises(ValueError, tf_dics, epochs, fwd_surf, None, tmin, tmax, tstep=0.15, win_lengths=[0.2, 0.1], freq_bins=freq_bins) # Test if incorrent number of n_ffts is detected raises(ValueError, tf_dics, epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, freq_bins=freq_bins, n_ffts=[1]) # Test if incorrect number of mt_bandwidths is detected raises(ValueError, tf_dics, epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths=win_lengths, freq_bins=freq_bins, mode='multitaper', mt_bandwidths=[20]) # Test if subtracting evoked responses yields NaN's, since we only have one # epoch. Suppress division warnings. with pytest.warns(RuntimeWarning, match='[invalid|empty]'): stcs = tf_dics(epochs, fwd_surf, None, tmin, tmax, tstep, win_lengths, mode='cwt_morlet', frequencies=frequencies, subtract_evoked=True, reg=reg, label=label, decim=20) assert np.all(np.isnan(stcs[0].data))
def test_tf_dics(): """Test TF beamforming based on DICS """ tmin, tmax, tstep = -0.2, 0.2, 0.1 raw, epochs, _, _, _, label, forward, _, _, _ =\ _get_data(tmin, tmax, read_all_forward=False, compute_csds=False) freq_bins = [(4, 20), (30, 55)] win_lengths = [0.2, 0.2] reg = 0.001 noise_csds = [] for freq_bin, win_length in zip(freq_bins, win_lengths): noise_csd = csd_epochs(epochs, mode='fourier', fmin=freq_bin[0], fmax=freq_bin[1], fsum=True, tmin=tmin, tmax=tmin + win_length) noise_csds.append(noise_csd) stcs = tf_dics(epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins, reg=reg, label=label) assert_true(len(stcs) == len(freq_bins)) assert_true(stcs[0].shape[1] == 4) # Manually calculating source power in several time windows to compare # results and test overlapping source_power = [] time_windows = [(-0.1, 0.1), (0.0, 0.2)] for time_window in time_windows: data_csd = csd_epochs(epochs, mode='fourier', fmin=freq_bins[0][0], fmax=freq_bins[0][1], fsum=True, tmin=time_window[0], tmax=time_window[1]) noise_csd = csd_epochs(epochs, mode='fourier', fmin=freq_bins[0][0], fmax=freq_bins[0][1], fsum=True, tmin=-0.2, tmax=0.0) data_csd.data /= data_csd.n_fft noise_csd.data /= noise_csd.n_fft stc_source_power = dics_source_power(epochs.info, forward, noise_csd, data_csd, reg=reg, label=label) source_power.append(stc_source_power.data) # Averaging all time windows that overlap the time period 0 to 100 ms source_power = np.mean(source_power, axis=0) # Selecting the first frequency bin in tf_dics results stc = stcs[0] # Comparing tf_dics results with dics_source_power results assert_array_almost_equal(stc.data[:, 2], source_power[:, 0]) # Test if using unsupported max-power orientation is detected assert_raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins=freq_bins, pick_ori='max-power') # Test if incorrect number of noise CSDs is detected assert_raises(ValueError, tf_dics, epochs, forward, [noise_csds[0]], tmin, tmax, tstep, win_lengths, freq_bins=freq_bins) # Test if freq_bins and win_lengths incompatibility is detected assert_raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths=[0, 1, 2], freq_bins=freq_bins) # Test if time step exceeding window lengths is detected assert_raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep=0.15, win_lengths=[0.2, 0.1], freq_bins=freq_bins) # Test if incorrect number of mt_bandwidths is detected assert_raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins, mode='multitaper', mt_bandwidths=[20]) # Pass only one epoch to test if subtracting evoked responses yields zeros stcs = tf_dics(epochs[0], forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins, subtract_evoked=True, reg=reg, label=label) assert_array_almost_equal(stcs[0].data, np.zeros_like(stcs[0].data))
fmin=freq_bin[0], fmax=freq_bin[1], fsum=True, tmin=-win_length, tmax=0, n_fft=n_fft) noise_csds.append(noise_csd) # Computing DICS solutions for time-frequency windows in a label in source # space for faster computation, use label=None for full solution stcs = tf_dics(epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins=freq_bins, subtract_evoked=subtract_evoked, n_ffts=n_ffts, reg=0.001, label=label) # Plotting source spectrogram for source with maximum activity # Note that tmin and tmax are set to display a time range that is smaller than # the one for which beamforming estimates were calculated. This ensures that # all time bins shown are a result of smoothing across an identical number of # time windows. plot_source_spectrogram(stcs, freq_bins, tmin=tmin_plot, tmax=tmax_plot,
def test_tf_dics(): """Test TF beamforming based on DICS """ tmin, tmax, tstep = -0.2, 0.2, 0.1 raw, epochs, _, _, _, label, forward, _, _, _ =\ _get_data(tmin, tmax, read_all_forward=False, compute_csds=False) freq_bins = [(4, 20), (30, 55)] win_lengths = [0.2, 0.2] reg = 0.001 noise_csds = [] for freq_bin, win_length in zip(freq_bins, win_lengths): noise_csd = compute_epochs_csd(epochs, mode='fourier', fmin=freq_bin[0], fmax=freq_bin[1], fsum=True, tmin=tmin, tmax=tmin + win_length) noise_csds.append(noise_csd) stcs = tf_dics(epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins, reg=reg, label=label) assert_true(len(stcs) == len(freq_bins)) assert_true(stcs[0].shape[1] == 4) # Manually calculating source power in several time windows to compare # results and test overlapping source_power = [] time_windows = [(-0.1, 0.1), (0.0, 0.2)] for time_window in time_windows: data_csd = compute_epochs_csd(epochs, mode='fourier', fmin=freq_bins[0][0], fmax=freq_bins[0][1], fsum=True, tmin=time_window[0], tmax=time_window[1]) noise_csd = compute_epochs_csd(epochs, mode='fourier', fmin=freq_bins[0][0], fmax=freq_bins[0][1], fsum=True, tmin=-0.2, tmax=0.0) data_csd.data /= data_csd.n_fft noise_csd.data /= noise_csd.n_fft stc_source_power = dics_source_power(epochs.info, forward, noise_csd, data_csd, reg=reg, label=label) source_power.append(stc_source_power.data) # Averaging all time windows that overlap the time period 0 to 100 ms source_power = np.mean(source_power, axis=0) # Selecting the first frequency bin in tf_dics results stc = stcs[0] # Comparing tf_dics results with dics_source_power results assert_array_almost_equal(stc.data[:, 2], source_power[:, 0]) # Test if using unsupported max-power orientation is detected assert_raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins=freq_bins, pick_ori='max-power') # Test if incorrect number of noise CSDs is detected assert_raises(ValueError, tf_dics, epochs, forward, [noise_csds[0]], tmin, tmax, tstep, win_lengths, freq_bins=freq_bins) # Test if freq_bins and win_lengths incompatibility is detected assert_raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths=[0, 1, 2], freq_bins=freq_bins) # Test if time step exceeding window lengths is detected assert_raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep=0.15, win_lengths=[0.2, 0.1], freq_bins=freq_bins) # Test if incorrect number of mt_bandwidths is detected assert_raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins, mode='multitaper', mt_bandwidths=[20]) # Pass only one epoch to test if subtracting evoked responses yields zeros stcs = tf_dics(epochs[0], forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins, subtract_evoked=True, reg=reg, label=label) assert_array_almost_equal(stcs[0].data, np.zeros_like(stcs[0].data))
win_lengths = [0.3, 0.2, 0.15, 0.1] # s # Then set FFTs length for each frequency range. # Should be a power of 2 to be faster. n_ffts = [256, 128, 128, 128] # Subtract evoked response prior to computation? subtract_evoked = False # Calculating noise cross-spectral density from empty room noise for each # frequency bin and the corresponding time window length. To calculate noise # from the baseline period in the data, change epochs_noise to epochs noise_csds = [] for freq_bin, win_length, n_fft in zip(freq_bins, win_lengths, n_ffts): noise_csd = csd_fourier(epochs_noise, fmin=freq_bin[0], fmax=freq_bin[1], tmin=-win_length, tmax=0, n_fft=n_fft) noise_csds.append(noise_csd.sum()) # Computing DICS solutions for time-frequency windows in a label in source # space for faster computation, use label=None for full solution stcs = tf_dics(epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins=freq_bins, subtract_evoked=subtract_evoked, n_ffts=n_ffts, reg=0.05, label=label, inversion='matrix') # Plotting source spectrogram for source with maximum activity # Note that tmin and tmax are set to display a time range that is smaller than # the one for which beamforming estimates were calculated. This ensures that # all time bins shown are a result of smoothing across an identical number of # time windows. plot_source_spectrogram(stcs, freq_bins, tmin=tmin_plot, tmax=tmax_plot, source_index=None, colorbar=True)
annot_fname=None, regexp=None, subjects_dir=mri_dir, sort=False, verbose=None) label = [l for l in labels if l.name == loi][0] print("Calculating TF_DICS negative for {}".format(meg)) stcs_neg = tf_dics(epo['negative'], fwd, noise_csds=None, tmin=tmin, tmax=tmax, tstep=tstep, win_lengths=win_lengths, subtract_evoked=False, mode='cwt_morlet', frequencies=frequencies, cwt_n_cycles=cwt_n_cycles, reg=0.05, label=label, pick_ori='max-power', inversion='single', depth=1.0, n_jobs=n_jobs) for fb in range(len(freq_bins)): stcs_neg[fb].save("{}{}_TF_dics_neg_{}-{}_{}-stc.h5".format( save_dir, meg, freq_bins[fb][0], freq_bins[fb][-1], loi)) print("Calculating TF_DICS positive for {}".format(meg)) stcs_pos = tf_dics(epo['positive'], fwd, noise_csds=None,
reject = dict(mag=4e-12) # Re-normalize our empty-room projectors, which should be fine after subselection raw.info.normalize_proj() # Setting time windows. tmin, tmax, tstep = -0.5, 0.75, 0.05 # Read epochs event_id = 1 events = mne.read_events(event_fname) epochs = mne.Epochs(raw, events, event_id, tmin, tmax, baseline=None, preload=True, proj=True, reject=reject) # Read forward operator forward = mne.read_forward_solution(fname_fwd) # Read label label = mne.read_label(fname_label) # CWT_MORLET exemplary PARAMETERS for TF-DICS beamformer to re-produce bug/error frequencies = [[4.,5.,6.,7.,8.,9.,10.,11.,12.],[12.,13.,14.,15.,16.,17.,18.,19.,20.,21.,22.,23.,24.,25.,26.,27.,28.,29.,30.]] win_lengths = [0.3, 0.2] # use this line for cwt_cycles as list of float cwt_n_cycles = [5.,7.] # use this line to test single value # cwt_n_cycles = 7. # TF_DICS CALCULATION stcs = tf_dics(epochs, forward, noise_csds = None, tmin=tmin, tmax=tmax, tstep=tstep, win_lengths=win_lengths, subtract_evoked=False, mode='cwt_morlet', frequencies=frequencies, reg = 0.05, label=label, pick_ori='max-power', inversion='single', depth=1.0)