def cross_spectral_density_analysis(epochs, fmin, fmax): epochs = epochs.copy() #event_id = 998 #eog_events = mne.preprocessing.find_eog_events(data, event_id) #n_blinks = len(eog_events) # Read epochs #picks = mne.pick_types(data.info, eeg=True, exclude='bads') #tmin, tmax = -0.2, 0.2 #epochs_eog = mne.Epochs(data, eog_events, event_id, tmin, tmax, picks=picks, baseline=(None, 0), preload=True) csd_fft = csd_fourier(epochs, fmin=fmin, fmax=fmax, n_jobs=2) #csd_mt = csd_multitaper(epochs_eog, fmin=15, fmax=20, adaptive=True, n_jobs=1) #frequencies = [16, 17, 18, 19, 20] #csd_wav = csd_morlet(epochs_eog, frequencies, decim=10, n_jobs=1) return csd_fft #csd_fft.mean().plot() #plt.suptitle('short-term Fourier transform') #csd_mt.mean().plot() #plt.suptitle('adaptive multitapers') #csd_wav.mean().plot() #plt.suptitle('Morlet wavelet transform')
def test_csd_fourier(): """Test computing cross-spectral density using short-term Fourier.""" epochs = _generate_coherence_data() sfreq = epochs.info['sfreq'] _test_fourier_multitaper_parameters(epochs, csd_fourier, csd_array_fourier) # Compute CSDs using various parameters times = [(None, None), (1, 9)] as_arrays = [False, True] parameters = product(times, as_arrays) for (tmin, tmax), as_array in parameters: if as_array: csd = csd_array_fourier(epochs.get_data(), sfreq, epochs.tmin, fmin=9, fmax=23, tmin=tmin, tmax=tmax, ch_names=epochs.ch_names) else: csd = csd_fourier(epochs, fmin=9, fmax=23, tmin=tmin, tmax=tmax) if tmin is None and tmax is None: assert csd.tmin == 0 and csd.tmax == 9.98 else: assert csd.tmin == tmin and csd.tmax == tmax csd = csd.mean([9.9, 14.9, 21.9], [10.1, 15.1, 22.1]) _test_csd_matrix(csd) # For the next test, generate a simple sine wave with a known power times = np.arange(20 * sfreq) / sfreq # 20 seconds of signal signal = np.sin(2 * np.pi * 10 * times)[None, None, :] # 10 Hz wave signal_power_per_sample = sum_squared(signal) / len(times) # Power per sample should not depend on time window length for tmax in [12, 18]: t_mask = (times <= tmax) n_samples = sum(t_mask) # Power per sample should not depend on number of FFT points for add_n_fft in [0, 30]: n_fft = n_samples + add_n_fft csd = csd_array_fourier(signal, sfreq, tmax=tmax, n_fft=n_fft).sum().get_data() first_samp = csd[0, 0] fourier_power_per_sample = np.abs(first_samp) * sfreq / n_fft assert abs(signal_power_per_sample - fourier_power_per_sample) < 0.001
def test_csd_fourier(): """Test computing cross-spectral density using short-term Fourier.""" epochs = _generate_coherence_data() sfreq = epochs.info['sfreq'] _test_fourier_multitaper_parameters(epochs, csd_fourier, csd_array_fourier) # Compute CSDs using various parameters times = [(None, None), (1, 9)] as_arrays = [False, True] parameters = product(times, as_arrays) for (tmin, tmax), as_array in parameters: if as_array: csd = csd_array_fourier(epochs.get_data(), sfreq, epochs.tmin, fmin=9, fmax=23, tmin=tmin, tmax=tmax, ch_names=epochs.ch_names) else: csd = csd_fourier(epochs, fmin=9, fmax=23, tmin=tmin, tmax=tmax) if tmin is None and tmax is None: assert csd.tmin == 0 and csd.tmax == 9.98 else: assert csd.tmin == tmin and csd.tmax == tmax csd = csd.mean([9.9, 14.9, 21.9], [10.1, 15.1, 22.1]) _test_csd_matrix(csd) # For the next test, generate a simple sine wave with a known power times = np.arange(20 * sfreq) / sfreq # 20 seconds of signal signal = np.sin(2 * np.pi * 10 * times)[None, None, :] # 10 Hz wave signal_power_per_sample = sum_squared(signal) / len(times) # Power per sample should not depend on time window length for tmax in [12, 18]: t_mask = (times <= tmax) n_samples = sum(t_mask) # Power per sample should not depend on number of FFT points for add_n_fft in [0, 30]: n_fft = n_samples + add_n_fft csd = csd_array_fourier(signal, sfreq, tmax=tmax, n_fft=n_fft).sum().get_data() first_samp = csd[0, 0] fourier_power_per_sample = np.abs(first_samp) * sfreq / n_fft assert abs(signal_power_per_sample - fourier_power_per_sample) < 0.001
# Setting frequency bins as in Dalal et al. 2008 freq_bins = [(4, 12), (12, 30), (30, 55), (65, 300)] # Hz 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)
# Make some epochs, based on events with trigger code 1 epochs = mne.Epochs(raw, events, event_id=1, tmin=-0.2, tmax=1, picks=picks, baseline=(None, 0), reject=dict(grad=4000e-13), preload=True) ############################################################################### # Computing CSD matrices using short-term Fourier transform and (adaptive) # multitapers is straightforward: csd_fft = csd_fourier(epochs, fmin=15, fmax=20, n_jobs=n_jobs) csd_mt = csd_multitaper(epochs, fmin=15, fmax=20, adaptive=True, n_jobs=n_jobs) ############################################################################### # When computing the CSD with Morlet wavelets, you specify the exact # frequencies at which to compute it. For each frequency, a corresponding # wavelet will be constructed and convolved with the signal, resulting in a # time-frequency decomposition. # # The CSD is constructed by computing the correlation between the # time-frequency representations between all sensor-to-sensor pairs. The # time-frequency decomposition originally has the same sampling rate as the # signal, in our case ~600Hz. This means the decomposition is over-specified in # time and we may not need to use all samples during our CSD computation, just # enough to get a reliable correlation statistic. By specifying ``decim=10``, # we use every 10th sample, which will greatly speed up the computation and
# Setting frequency bins as in Dalal et al. 2008 freq_bins = [(4, 12), (12, 30), (30, 55), (65, 300)] # Hz 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)
#------------------------------------------------------------------------------ #plot power image (time frequency-analysis) n_cycles = 5 #number of cycles in Morlet wavelet freqs = np.arange(13, 30, 3) # frequencies of interest power, itc = tfr_morlet(epochs, freqs=freqs, n_cycles=n_cycles, return_itc=True, decim=3, n_jobs=1, use_fft=True) for electrode_position in power.ch_names: power.plot([power.ch_names.index(electrode_position)]) #------------------------------------------------------------------------------ #Compute a cross-spectral density matrix==covariance matrix n_jobs = 1 #number of cores used csd_fft = csd_fourier(epochs, fmin=7, fmax = 30, n_jobs=n_jobs) csd_mt = csd_multitaper(epochs, fmin=7, fmax=30, adaptive=True, n_jobs=n_jobs) frequencies = np.linspace(7.1,30,1000) csd_wav = csd_morlet(epochs, frequencies, decim=10, n_jobs=n_jobs) csd_fft.mean().plot() plt.suptitle('short-term Fourier transform') csd_mt.mean().plot() plt.suptitle('adaptive multitapers') csd_wav.mean().plot() plt.suptitle('Morlet wavelet transform') #------------------------------------------------------------------------------ #------------------------------------------------------------------------------ #------------------------------------------------------------------------------
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.05 noise_csds = [] for freq_bin, win_length in zip(freq_bins, win_lengths): noise_csd = csd_fourier(epochs, fmin=freq_bin[0], fmax=freq_bin[1], tmin=tmin, tmax=tmin + win_length) noise_csds.append(noise_csd.sum()) stcs = tf_dics(epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins, reg=reg, label=label) assert len(stcs) == len(freq_bins) assert stcs[0].shape[1] == 4 assert 2.2 < stcs[0].data.max() < 2.3 assert 0.94 < stcs[0].data.min() < 0.95 # 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_fourier(epochs, fmin=freq_bins[0][0], fmax=freq_bins[0][1], tmin=time_window[0], tmax=time_window[1]) data_csd = data_csd.sum() noise_csd = csd_fourier(epochs, fmin=freq_bins[0][0], fmax=freq_bins[0][1], tmin=-0.2, tmax=0.0) noise_csd = noise_csd.sum() 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 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 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 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 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 raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins, mode='multitaper', mt_bandwidths=[20]) # Test if unsupported 'cwt_morlet' CSD estimation mode is detected raises(ValueError, tf_dics, epochs, forward, noise_csds, tmin, tmax, tstep, win_lengths, freq_bins=freq_bins, mode='cwt_morlet') # 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))
# By default, CSD matrices are computed using all MEG/EEG channels. When # interpreting a CSD matrix with mixed sensor types, be aware that the # measurement units, and thus the scalings, differ across sensors. In this # example, for speed and clarity, we select a single channel type: # gradiometers. picks = mne.pick_types(raw.info, meg='grad') # Make some epochs, based on events with trigger code 1 epochs = mne.Epochs(raw, events, event_id=1, tmin=0, tmax=1, picks=picks, baseline=(None, 0), reject=dict(grad=4000e-13), preload=True) ############################################################################### # Computing CSD matrices using short-term Fourier transform and (adaptive) # multitapers is straightforward: csd_fft = csd_fourier(epochs, fmin=15, fmax=20, n_jobs=n_jobs) csd_mt = csd_multitaper(epochs, fmin=15, fmax=20, adaptive=True, n_jobs=n_jobs) ############################################################################### # When computing the CSD with Morlet wavelets, you specify the exact # frequencies at which to compute it. For each frequency, a corresponding # wavelet will be constructed and convolved with the signal, resulting in a # time-frequency decomposition. # # The CSD is constructed by computing the correlation between the # time-frequency representations between all sensor-to-sensor pairs. The # time-frequency decomposition originally has the same sampling rate as the # signal, in our case ~600Hz. This means the decomposition is over-specified in # time and we may not need to use all samples during our CSD computation, just # enough to get a reliable correlation statistic. By specifying ``decim=10``, # we use every 10th sample, which will greatly speed up the computation and