def test_multitaper_psd(): """Test multi-taper PSD computation.""" import nitime as ni for n_times in (100, 101): n_channels = 5 data = np.random.RandomState(0).randn(n_channels, n_times) sfreq = 500 info = create_info(n_channels, sfreq, 'eeg') raw = RawArray(data, info) pytest.raises(ValueError, psd_multitaper, raw, sfreq, normalization='foo') ni_5 = (LooseVersion(ni.__version__) >= LooseVersion('0.5')) norm = 'full' if ni_5 else 'length' for adaptive, n_jobs in zip((False, True, True), (1, 1, 2)): psd, freqs = psd_multitaper(raw, adaptive=adaptive, n_jobs=n_jobs, normalization=norm) with warnings.catch_warnings(record=True): # nitime integers freqs_ni, psd_ni, _ = ni.algorithms.spectral.multi_taper_psd( data, sfreq, adaptive=adaptive, jackknife=False) assert_array_almost_equal(psd, psd_ni, decimal=4) if n_times % 2 == 0: # nitime's frequency definitions must be incorrect, # they give the same values for 100 and 101 samples assert_array_almost_equal(freqs, freqs_ni) with pytest.raises(ValueError, match='use a value of at least'): psd_multitaper(raw, bandwidth=4.9)
def calc_psd_epochs(epochs, plot=False): """Calculate PSD for epoch. Parameters ---------- epochs : list of epochs plot : bool To show plot of the psds. It will be average for each condition that is shown. Returns ------- psds_vol : numpy array The psds for the voluntary condition. psds_invol : numpy array The psds for the involuntary condition. """ tmin, tmax = -0.5, 0.5 fmin, fmax = 2, 90 # n_fft = 2048 # the FFT size (n_fft). Ideally a power of 2 psds_vol, freqs = psd_multitaper(epochs["voluntary"], tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax) psds_inv, freqs = psd_multitaper(epochs["involuntary"], tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax) psds_vol = 20 * np.log10(psds_vol) # scale to dB psds_inv = 20 * np.log10(psds_inv) # scale to dB if plot: def my_callback(ax, ch_idx): """Executed once you click on one of the channels in the plot.""" ax.plot(freqs, psds_vol_plot[ch_idx], color='red', label="voluntary") ax.plot(freqs, psds_inv_plot[ch_idx], color='blue', label="involuntary") ax.set_xlabel = 'Frequency (Hz)' ax.set_ylabel = 'Power (dB)' ax.legend() psds_vol_plot = psds_vol.copy().mean(axis=0) psds_inv_plot = psds_inv.copy().mean(axis=0) for ax, idx in iter_topography(epochs.info, fig_facecolor='k', axis_facecolor='k', axis_spinecolor='k', on_pick=my_callback): ax.plot(psds_vol_plot[idx], color='red', label="voluntary") ax.plot(psds_inv_plot[idx], color='blue', label="involuntary") plt.legend() plt.gcf().suptitle('Power spectral densities') plt.show() return psds_vol, psds_inv, freqs
def compute_and_save_psd(epochs_fname, fmin=0, fmax=120, method='welch', n_fft=256, n_overlap=0, picks=None, proj=False, n_jobs=1, verbose=None): """ Load epochs from file, compute psd and save the result in numpy arrays """ import numpy as np import os from mne import read_epochs epochs = read_epochs(epochs_fname) epochs_meg = epochs.pick_types(meg=True, eeg=False, eog=False, ecg=False) if method == 'welch': from mne.time_frequency import psd_welch psds, freqs = psd_welch(epochs_meg) elif method == 'multitaper': from mne.time_frequency import psd_multitaper psds, freqs = psd_multitaper(epochs_meg) else: raise Exception('nonexistent method for psd computation') path, name = os.path.split(epochs_fname) base, ext = os.path.splitext(name) psds_fname = base + '-psds.npz' # freqs_fname = base + '-freqs.npy' psds_fname = os.path.abspath(psds_fname) # print(psds.shape) np.savez(psds_fname, psds=psds, freqs=freqs) # np.save(freqs_file, freqs) return psds_fname
def test_multitaper_psd(): """ Test multi-taper PSD computation """ import nitime as ni n_times = 1000 n_channels = 5 data = np.random.RandomState(0).randn(n_channels, n_times) sfreq = 500 info = create_info(n_channels, sfreq, 'eeg') raw = RawArray(data, info) assert_raises(ValueError, psd_multitaper, raw, sfreq, normalization='foo') ni_5 = (LooseVersion(ni.__version__) >= LooseVersion('0.5')) norm = 'full' if ni_5 else 'length' for adaptive, n_jobs in zip((False, True, True), (1, 1, 2)): psd, freqs = psd_multitaper(raw, adaptive=adaptive, n_jobs=n_jobs, normalization=norm) freqs_ni, psd_ni, _ = ni.algorithms.spectral.multi_taper_psd( data, sfreq, adaptive=adaptive, jackknife=False) # for some reason nitime returns n_times + 1 frequency points # causing the value at 0 to be different assert_array_almost_equal(psd[:, 1:], psd_ni[:, 1:-1], decimal=3) assert_array_almost_equal(freqs, freqs_ni[:-1])
def test_csd_multitaper(): """Test computing cross-spectral density using multitapers.""" epochs = _generate_coherence_data() sfreq = epochs.info['sfreq'] _test_fourier_multitaper_parameters(epochs, csd_multitaper, csd_array_multitaper) # Compute CSDs using various parameters times = [(None, None), (1, 9)] as_arrays = [False, True] adaptives = [False, True] parameters = product(times, as_arrays, adaptives) for (tmin, tmax), as_array, adaptive in parameters: if as_array: csd = csd_array_multitaper(epochs.get_data(), sfreq, epochs.tmin, adaptive=adaptive, fmin=9, fmax=23, tmin=tmin, tmax=tmax, ch_names=epochs.ch_names) else: csd = csd_multitaper(epochs, adaptive=adaptive, 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) # Test equivalence with PSD psd, psd_freqs = psd_multitaper(epochs, fmin=1e-3, normalization='full') # omit DC csd = csd_multitaper(epochs) assert_allclose(psd_freqs, csd.frequencies) csd = np.array([np.diag(csd.get_data(index=ii)) for ii in range(len(csd))]).T assert_allclose(psd[0], 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) n_fft = len(times) # Power per sample should not depend on number of tapers for n_tapers in [1, 2, 5]: bandwidth = sfreq / float(n_samples) * (n_tapers + 1) csd_mt = csd_array_multitaper(signal, sfreq, tmax=tmax, bandwidth=bandwidth, n_fft=n_fft).sum().get_data() mt_power_per_sample = np.abs(csd_mt[0, 0]) * sfreq / n_fft assert abs(signal_power_per_sample - mt_power_per_sample) < 0.001
############################################################################### # Let's first check out all channel types by averaging across epochs. epochs.plot_psd(fmin=2., fmax=40., average=True, spatial_colors=False) ############################################################################### # Now let's take a look at the spatial distributions of the PSD. epochs.plot_psd_topomap(ch_type='grad', normalize=True) ############################################################################### # Alternatively, you can also create PSDs from Epochs objects with functions # that start with ``psd_`` such as # :func:`mne.time_frequency.psd_multitaper` and # :func:`mne.time_frequency.psd_welch`. f, ax = plt.subplots() psds, freqs = psd_multitaper(epochs, fmin=2, fmax=40, n_jobs=1) psds = 10. * np.log10(psds) psds_mean = psds.mean(0).mean(0) psds_std = psds.mean(0).std(0) ax.plot(freqs, psds_mean, color='k') ax.fill_between(freqs, psds_mean - psds_std, psds_mean + psds_std, color='k', alpha=.5) ax.set(title='Multitaper PSD (gradiometers)', xlabel='Frequency (Hz)', ylabel='Power Spectral Density (dB)') plt.show() ############################################################################### # Notably, :func:`mne.time_frequency.psd_welch` supports the keyword argument # ``average``, which specifies how to estimate the PSD based on the individual # windowed segments. The default is ``average='mean'``, which simply calculates
def transform(self, x, y=None): psds, freqs = psd_multitaper(x, **self.kwargs) self.freqs = freqs return psds
""" Created on Sat Aug 25 14:50:05 2018 @author: Malte Gueth """ import mne from mne.time_frequency import psd_multitaper # Load epoched data segments and compute power spectral density for all genres # as alternative input for the rsa script file = './epochs/sub-03-reordered-epo.fif' epochs = mne.read_epochs(file) picks = mne.pick_types(epochs.info, eeg=True) tmin, tmax = 0, 1 # Pick time window within each epoch fmin, fmax = 1, 60 # Pick frequency range # Besides frequencies, the function returns an array of 320 epochs x 64 electrodes x 59 frequencies psds, freqs = psd_multitaper(epochs, tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax, picks=picks)
# And now do the same with SSP applied raw.plot_psd(tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax, n_fft=n_fft, n_jobs=1, proj=True, ax=ax, color=(0, 1, 0), picks=picks, show=False) # And now do the same with SSP + notch filtering # Pick all channels for notch since the SSP projection mixes channels together raw.notch_filter(np.arange(60, 241, 60), n_jobs=1) raw.plot_psd(tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax, n_fft=n_fft, n_jobs=1, proj=True, ax=ax, color=(1, 0, 0), picks=picks, show=False) ax.set_title('Four left-temporal magnetometers') plt.legend(['Without SSP', 'With SSP', 'SSP + Notch']) # Alternatively, you may also create PSDs from Raw objects with psd_XXX f, ax = plt.subplots() psds, freqs = psd_multitaper(raw, low_bias=True, tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax, proj=True, picks=picks, n_jobs=1) psds = 10 * np.log10(psds) psds_mean = psds.mean(0) psds_std = psds.std(0) ax.plot(freqs, psds_mean, color='k') ax.fill_between(freqs, psds_mean - psds_std, psds_mean + psds_std, color='k', alpha=.5) ax.set(title='Multitaper PSD', xlabel='Frequency', ylabel='Power Spectral Density (dB)') plt.show()
def compute_PSD(epochs, freqlist=FREQS, method="multitaper", tmin=0, tmax=0.8): epochs_psds = [] # Compute PSD if method == "multitaper": psds, freqs = psd_multitaper( epochs, fmin=min(min(freqlist)), fmax=max(max(freqlist)), n_jobs=1 ) if method == "pwelch": psds, freqs = psd_welch( epochs, average="median", fmin=min(min(freqlist)), fmax=max(max(freqlist)), n_jobs=1, ) if method == "pwelch" or method == "multitaper": psds = 10.0 * np.log10(psds) # Convert power to dB scale. # Average in freq bands for low, high in freqlist: freq_idx = [i for i, x in enumerate(freqs) if x >= low and x <= high] psd = np.mean(psds[:, :, freq_idx], axis=2) epochs_psds.append(psd) epochs_psds = np.array(epochs_psds).swapaxes(2, 0).swapaxes(1, 0) # TODO : compute via hilbert if method == "hilbert": for low, high in freqlist: # Filter continuous data data = epochs.copy().filter(low, high) # Here epochs is a raw file hilbert = data.apply_hilbert(envelope=True) hilbert_pow = hilbert.copy() hilbert_pow._data = hilbert._data**2 # Segment them picks = mne.pick_types( epochs.info, meg=True, ref_meg=False, eeg=False, eog=False, stim=False ) try: events = mne.find_events( epochs, min_duration=1 / epochs.info["sfreq"], verbose=False ) except ValueError: events = mne.find_events( epochs, min_duration=2 / epochs.info["sfreq"], verbose=False ) event_id = {"Freq": 21, "Rare": 31} epochs = mne.Epochs( hilbert_pow, events=events, event_id=event_id, tmin=tmin, tmax=tmax, baseline=None, reject=None, picks=picks, preload=True, ) epochs.drop(ARlog.bad_epochs) epochs_psds.append(epochs.get_data()) epochs_psds = np.array(epochs_psds) epochs_psds = np.mean(epochs_psds, axis=3).transpose(1, 2, 0) print(epochs_psds.shape) return epochs_psds
epochs.plot_psd(fmin=2, fmax=200) # picks MEG gradiometers picks = mne.pick_types(raw.info, meg='grad', eeg=False, eog=False, stim=False, exclude='bads') # Now let's take a look at the spatial distributions of the psd. epochs.plot_psd_topomap(ch_type='grad', normalize=True) # Alternatively, you may also create PSDs from Epochs objects with psd_XXX f, ax = plt.subplots() psds, freqs = psd_multitaper(epochs, fmin=2, fmax=200, picks=picks, n_jobs=1) psds = 10 * np.log10(psds) psds_mean = psds.mean(0).mean(0) psds_std = psds.mean(0).std(0) ax.plot(freqs, psds_mean, color='k') ax.fill_between(freqs, psds_mean - psds_std, psds_mean + psds_std, color='k', alpha=.5) ax.set(title='Multitaper PSD (gradiometers)', xlabel='Frequency', ylabel='Power Spectral Density (dB)') plt.show()
def preprocess(args): f_high = 128 f_low = 1 blink_removal = not args.no_blink_removal save_epochs = args.save_epochs # number_bad_channels = [] montage = load_montage() montage_fig = montage.plot(scale_factor=20, show_names=True, kind='topomap', show=False) montage_fig.savefig(data_dir + '/results/montage_2D.png', dpi=500) plt.close(montage_fig) montage_fig2 = montage.plot(scale_factor=20, show_names=True, kind='3d', show=False) montage_fig2.savefig(data_dir + '/results/montagefig_3D.png', dpi=500) plt.close(montage_fig2) # fooof_fig, fooof_axes = plt.subplots(nrows=10, ncols=4, sharex=True, sharey=False, squeeze=False, figsize=(24, 40)) # power_fig, power_axes = plt.subplots(nrows=10, ncols=4, sharex=True, sharey=False, squeeze=False, figsize=(24, 40)) # topo_fig, topo_axes = plt.subplots(nrows=10, ncols=4, sharex=True, sharey=True, squeeze=False, figsize=(24, 40)) all_fooofs = [] fooof_r2s = np.zeros((n_participants, n_sessions)) filter_r2s = np.zeros((n_participants, n_sessions)) for participant_idx, participant in enumerate(participants): plt.close() # evoked_fig_filtered, evoked_ax_filtered = plt.subplots(nrows=10, ncols=3, sharex=True, sharey=False, squeeze=False, figsize=(10, 40)) # evoked_fig_amplified, evoked_ax_amplified = plt.subplots(nrows=10, ncols=3, sharex=True, sharey=False, squeeze=False, figsize=(10, 40)) for session_idx, session_name in enumerate(sessions): print('Participant', participant_idx + 1, '/', len(participants), 'session', session_idx + 1, '/', len(sessions)) filename = data_dir + participant + '/' + participant + session_name + '.bdf' eeg = read_raw_edf(filename, montage=montage, eog=eog_channels, preload=True, verbose=0) # mne.set_eeg_reference(eeg, ref_channels='average', copy=True, projection=False) events = mne.find_events(eeg, verbose=0) reject = dict(eeg=80e-5, eog=60e-4) # manually tuned argh eeg.pick_channels(channel_names) filter_eeg = eeg.copy() filter_eeg = filter_eeg.filter(1, 40, picks=list(range(132)), n_jobs=7, verbose=0) # band-pass print('Bandpass Filter') if blink_removal: print('ICA') eeg = ica_preprocessing(eeg, filter_eeg, participant, session_name, eog_channels[0], reject, f_low, f_high) eeg.set_eeg_reference('average', projection=True, verbose=0) eeg.apply_proj() if save_epochs: print('Saving Epochs') face_epochs, noise_epochs = save_epochs_as( eeg, 'Raw', events, reject, participant, session_name) # plot_evoked(face_epochs, noise_epochs, evoked_ax_filtered, session_idx) if args.connectivity: plot_connectivity(face_epochs, participant, session_name, 'face', 'raw') plot_connectivity(noise_epochs, participant, session_name, 'noise', 'raw') del (face_epochs) del (noise_epochs) if save_epochs: print('Saving Epochs') condition = 'Bandpass' if not blink_removal: condition = condition + ' (blinks)' face_epochs, noise_epochs = save_epochs_as( filter_eeg, condition, events, reject, participant, session_name) # plot_evoked(face_epochs, noise_epochs, evoked_ax_filtered, session_idx) if args.connectivity: plot_connectivity(face_epochs, participant, session_name, 'face', condition) plot_connectivity(noise_epochs, participant, session_name, 'noise', condition) del face_epochs del noise_epochs del filter_eeg if save_epochs: print('Highpass Filter') filter_eeg = eeg.copy() filter_eeg = filter_eeg.filter(1, None, picks=list(range(132)), n_jobs=7, verbose=0) condition = 'Highpass' if not blink_removal: condition = condition + ' (blinks)' print('Saving Epochs') face_epochs, noise_epochs = save_epochs_as( filter_eeg, condition, events, reject, participant, session_name) # plot_evoked(face_epochs, noise_epochs, evoked_ax_filtered, session_idx) if args.connectivity: plot_connectivity(face_epochs, participant, session_name, 'face', condition) plot_connectivity(noise_epochs, participant, session_name, 'noise', condition) del face_epochs del noise_epochs del filter_eeg # print('Plot Power') # eeg.plot_psd(tmin=100, fmin=0.1, fmax=256, picks=list(range(128)), ax=power_axes[session_idx][participant_idx], area_mode='std', area_alpha=0.33, dB=True, estimate='auto', average=False, show=False, n_jobs=7, spatial_colors=True, verbose=0) # eeg.pick_channels(channel_names[0:128]) # eeg.plot_psd_topo(tmin=100, dB=True, show=False, block=False, n_jobs=1, axes=topo_axes[session_idx][participant_idx], verbose=0) eeg = eeg.pick_channels(channel_names[0:132]) print('Computing power spectrum for entire session...') start_time = time.time() psds, freqs = psd_multitaper(eeg, f_low, 45, n_jobs=7, verbose=0) print('Took', (time.time() - start_time) // 60, 'mins') print('Frequencies shape:', freqs.shape, 'Power spectrum distribution shape:', psds.shape) # psds, freqs = psd_welch(channel_rejected_eeg, fmin=0, fmax=n_freqs, tmin=500, tmax=2000, n_fft=2048, n_overlap=512, n_jobs=7) print('Fitting FOOOF...') start_time = time.time() fooof = FOOOF(min_peak_amplitude=0.05, peak_width_limits=[3, 15], background_mode='knee') fooof.fit(freqs, np.mean(psds, axis=0), freq_range=[f_low / 2, 45]) print('FOOOF fit in', (time.time() - start_time) // 60, 'mins') # fooof.plot(plt_log=False, save_fig=True, file_name='FOOOF_' + participant + '_' + session_name, file_path=data_dir + '/results/') # fooof.plot(plt_log=False, ax=fooof_axes[session_idx][participant_idx]) fooof_r2s[participant_idx][session_idx] = fooof.r_squared_ all_fooofs.append(fooof) # amplify time series print('Amplifying Time') eeg_time_series = eeg.get_data(picks=list(range(132))) amplified_time_series = np.zeros_like(eeg_time_series) print('Learning Filters') log_filter_coeffs, gaussian_filter_coeffs, log_amplitudes, gaussian_amplitudes, amp_figs, ideal_gains, log_offset = fooof.learn_filters( 512, 5) amplitudes = log_amplitudes + gaussian_amplitudes filter_coeffs = log_filter_coeffs + gaussian_filter_coeffs for plot_idx, amp_fig in enumerate(amp_figs): # amp_fig.savefig(data_dir + '/results/' + participant + session_name + '_amplifier_' + str(plot_idx) + '.png') plt.close(amp_fig) fig, fig2, filter_r2 = plot_amplifier( log_filter_coeffs, log_amplitudes, gaussian_filter_coeffs, gaussian_amplitudes, 512, ideal_gains, fooof, log_offset) filter_r2s[participant_idx][session_idx] = filter_r2 # fig3, filter_responses = plt.subplots(1, 2, figsize=(12, 4)) # amplified_spectra = [] print('Applying Filters') for i, (coeffs, amplitude) in enumerate(zip(filter_coeffs, amplitudes)): if coeffs is not None: if isinstance(coeffs[0], np.float64): # fun = partial(lfilter, b=coeffs, a=[1.0], axis=-1) fun = partial(filtfilt, b=coeffs, a=[1.0], axis=-1) else: fun = partial(filtfilt, b=coeffs[0], a=coeffs[1], axis=-1) # fun = partial(lfilter, b=coeffs[0], a=coeffs[1], axis=-1) parallel, p_fun, _ = parallel_func(fun, 7) filtered_eeg = parallel( p_fun(x=eeg_time_series[p]) for p in range(132)) # filtered_eeg = filtered_eeg - np.mean(filtered_eeg, axis=0) # print('yet another power spectrum') # frequencies, pxx = welch(filtered_eeg, 512) # amplified_spectra.append(pxx) # filter_responses[0].plot(frequencies, np.log10(np.mean(pxx, axis=0))) for p in range(132): amplified_time_series[p] += (filtered_eeg[p] * amplitude) # filter_responses[-1].plot(frequencies, np.log10(np.mean(sum(amplified_spectra), axis=0))) # fig3.savefig(data_dir + '/results/' + participant + session_name + '_psd_filters.png') # plt.close(fig3) epoch_info = mne.pick_info(eeg.info, sel=(list(range(132))), copy=True) eeg = mne.io.RawArray(np.float64(amplified_time_series), epoch_info, verbose=0) amped_psds, freqs = psd_multitaper(eeg, f_low, 45, n_jobs=7, verbose=0) last_subfig = fig.axes[-1] last_subfig.plot(freqs, np.log10(np.mean(psds, axis=0)), color='k', label='Original Spectrum') last_subfig.plot(freqs, np.log10(np.mean(amped_psds, axis=0)), color='blue', linewidth=2, label='Normalized Spectrum') last_subfig.legend(loc="lower right", fontsize=16, shadow=True, fancybox=True) # last_subfig.plot(freqs, np.log10(np.mean(amped_psds, axis=0) - np.mean(psds, axis=0)), color='red', linewidth=1) last_subfig.set_ylabel('Power', fontsize=16) last_subfig.set_xlabel('Frequency (Hz)', fontsize=16) last_subfig.set_title('Normalized\nPower Spectrum', fontsize=20) for tick in last_subfig.xaxis.get_major_ticks(): tick.label.set_fontsize(16) for tick in last_subfig.yaxis.get_major_ticks(): tick.label.set_fontsize(16) fig.savefig(data_dir + '/results/' + participant + session_name + '_amplifier.png', dpi=500, bbox_inches='tight') fig2.savefig(data_dir + '/results/' + participant + session_name + '_log_approx.png', dpi=500, bbox_inches='tight') plt.close(fig) plt.close(fig2) if save_epochs: print('Saving Amplified Epochs') condition = 'NPA' if not blink_removal: condition = condition + ' (blinks)' face_epochs, noise_epochs = save_epochs_as( eeg, condition, events, None, participant, session_name) # plot_evoked(face_epochs, noise_epochs, evoked_ax_amplified, session_idx) if args.connectivity: plot_connectivity(face_epochs, participant, session_name, 'face', condition) plot_connectivity(noise_epochs, participant, session_name, 'noise', condition) del (face_epochs) del (noise_epochs) # evoked_fig_filtered.savefig(data_dir + '/results/evoked_filtered' + participant + '.png', dpi=500, bbox_inches='tight') # evoked_fig_amplified.savefig(data_dir + '/results/evoked_amplified' + participant + '.png', dpi=500, bbox_inches='tight') # for preproc_type in preproc_types: # evoked_fig = evoked_fig[preproc_type] # evoked_fig.savefig(data_dir + '/results/evoked_' + preproc_type + participant + '.png', dpi=500, bbox_inches='tight') # fooof_fig.savefig(data_dir + '/results/fooofs.png', dpi=500, bbox_inches='tight') # power_fig.savefig(data_dir + '/results/power.png', dpi=500, bbox_inches='tight') print('FOOOF r squared') print(fooof_r2s) print('NPA r squared') print(filter_r2s) print('NPA r2 stats:', np.mean(filter_r2s), np.var(filter_r2s)) r2_fig, r2_ax = plt.subplots(1, 2, figsize=(12, 4), sharey=True) r2_boxes1 = r2_ax[0].boxplot(fooof_r2s.T, patch_artist=True) r2_boxes2 = r2_ax[1].boxplot(filter_r2s.T, patch_artist=True) r2_ax[0].set_ylabel('$r^2$', fontsize=16) # r2_ax[1].set_ylabel('$r^2$', fontsize=16) r2_ax[0].set_xticklabels(['1', '2', '3', '4']) r2_ax[1].set_xticklabels(['1', '2', '3', '4']) r2_ax[0].set_xlabel('Participant', fontsize=16) r2_ax[1].set_xlabel('Participant', fontsize=16) for tick in r2_ax[0].xaxis.get_major_ticks(): tick.label.set_fontsize(16) for tick in r2_ax[1].xaxis.get_major_ticks(): tick.label.set_fontsize(16) for tick in r2_ax[0].yaxis.get_major_ticks(): tick.label.set_fontsize(16) for tick in r2_ax[1].yaxis.get_major_ticks(): tick.label.set_fontsize(16) r2_ax[0].yaxis.grid(True) r2_ax[1].yaxis.grid(True) for patch, colour in zip(r2_boxes1['boxes'], colours): patch.set_facecolor(colour) for patch, colour in zip(r2_boxes2['boxes'], colours): patch.set_facecolor(colour) r2_fig.savefig(data_dir + '/results/r2.png') all_slopes = [] all_knees = [] # scatter plot of slope/knee for fm in all_fooofs: all_slopes.append(fm.background_params_[2]) all_knees.append(fm.background_params_[1]) slope_knee_fig, slope_knee_ax = plt.subplots(1, 1, figsize=(6, 4)) print('Min/Max slope:', np.min(np.array(all_slopes)), np.max(np.array(all_slopes))) print('Min/Max knee:', np.min(np.array(all_knees)), np.max(np.array(all_knees))) slope_knee_ax.scatter(all_slopes[0:9], all_knees[0:9], label='Participant 1') slope_knee_ax.scatter(all_slopes[10:19], all_knees[10:19], marker='d', label='Participant 2') slope_knee_ax.scatter(all_slopes[20:29], all_knees[20:29], marker='x', label='Participant 3') slope_knee_ax.scatter(all_slopes[30:39], all_knees[30:39], marker='+', label='Participant 4') slope_knee_ax.set_xlabel('Slope ($\chi$)', fontsize=16) slope_knee_ax.set_ylabel('Knee ($k$)', fontsize=16) slope_knee_ax.legend(loc='center left', bbox_to_anchor=(1, 0.5), fancybox=True, shadow=True) slope_knee_ax.set_yscale('log') for tick in slope_knee_ax.xaxis.get_major_ticks(): tick.label.set_fontsize(16) for tick in slope_knee_ax.yaxis.get_major_ticks(): tick.label.set_fontsize(16) slope_knee_fig.savefig(data_dir + '/results/' + 'slope_knee_fig.png', dpi=500, bbox_inches='tight')
set_log_level(verbose="ERROR") ch_type = "grad" # load the data X, y = assemble_epochs("answer") # dict with subj -> epochs mapping info_src = bp.epochs.fpath(subject="01") info = read_info(info_src) sel_idx = pick_types(info, meg="grad") info.pick_channels([info.ch_names[s] for s in sel_idx]) ep_low = EpochsArray(X[y == LOW_CONF_EPOCH, ...], info, tmin=-1) ep_high = EpochsArray(X[y == HIGH_CONF_EPOCH, ...], info, tmin=-1) # erf_diff = combine_evoked([ep_low, -ep_high], weights="equal") psds_high, freqs = psd_multitaper(ep_high, tmin=0, tmax=1, fmax=50) psds_low, freqs = psd_multitaper(ep_low, tmin=0, tmax=1, fmax=50) theta_mask = np.logical_and(4 <= freqs, freqs < 8) theta_power_low = psds_low[:, :, theta_mask].mean(axis=2) theta_power_high = psds_high[:, :, theta_mask].mean(axis=2) ( picks, pos, merge_channels, names, ch_type, sphere, clip_origin, ) = _prepare_topomap_plot(ep_low, ch_type, sphere=None)
############################################################################### # Alternative functions for PSDs # ------------------------------ # # There are also several functions in MNE that create a PSD using a Raw # object. These are in the :mod:`mne.time_frequency` module and begin with # ``psd_*``. For example, we'll use a multitaper method to compute the PSD # below. f, ax = plt.subplots() psds, freqs = psd_multitaper(raw, low_bias=True, tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax, proj=True, picks=picks, n_jobs=1) psds = 10 * np.log10(psds) psds_mean = psds.mean(0) psds_std = psds.std(0) ax.plot(freqs, psds_mean, color='k') ax.fill_between(freqs, psds_mean - psds_std, psds_mean + psds_std, color='k', alpha=.5) ax.set(title='Multitaper PSD',
def _generate_report(raw, ica, subj_name, basename, ecg_evoked, ecg_scores, ecg_inds, ecg_ch_name, eog_evoked, eog_scores, eog_inds, eog_ch_name): """Generate report for ica solution.""" import matplotlib.pyplot as plt report = Report() ica_title = 'Sources related to %s artifacts (red)' is_show = False # ------------------- Generate report for ECG ------------------------ # fig_ecg_scores = ica.plot_scores(ecg_scores, exclude=ecg_inds, title=ica_title % 'ecg', show=is_show) # Pick the five largest ecg_scores and plot them show_picks = np.abs(ecg_scores).argsort()[::-1][:5] # Plot estimated latent sources given the unmixing matrix. fig_ecg_ts = ica.plot_sources(raw, show_picks, exclude=ecg_inds, title=ica_title % 'ecg' + ' in 30s', start=0, stop=30, show=is_show) # topoplot of unmixing matrix columns fig_ecg_comp = ica.plot_components(show_picks, title=ica_title % 'ecg', colorbar=True, show=is_show) # plot ECG sources + selection fig_ecg_src = ica.plot_sources(ecg_evoked, exclude=ecg_inds, show=is_show) fig = [fig_ecg_scores, fig_ecg_ts, fig_ecg_comp, fig_ecg_src] report.add_figs_to_section(fig, captions=[ 'Scores of ICs related to ECG', 'Time Series plots of ICs (ECG)', 'TopoMap of ICs (ECG)', 'Time-locked ECG sources' ], section='ICA - ECG') # -------------------- end generate report for ECG ---------------------- # # -------------------------- Generate report for EoG -------------------- # # check how many EoG ch we have if set(eog_ch_name.split(',')).issubset(set(raw.info['ch_names'])): fig_eog_scores = ica.plot_scores(eog_scores, exclude=eog_inds, title=ica_title % 'eog', show=is_show) report.add_figs_to_section(fig_eog_scores, captions=['Scores of ICs related to EOG'], section='ICA - EOG') n_eogs = np.shape(eog_scores) if len(n_eogs) > 1: n_eog0 = n_eogs[0] show_picks = [ np.abs(eog_scores[i][:]).argsort()[::-1][:5] for i in range(n_eog0) ] for i in range(n_eog0): fig_eog_comp = ica.plot_components(show_picks[i][:], title=ica_title % 'eog', colorbar=True, show=is_show) fig = [fig_eog_comp] report.add_figs_to_section(fig, captions=['Scores of EoG ICs'], section='ICA - EOG') else: show_picks = np.abs(eog_scores).argsort()[::-1][:5] fig_eog_comp = ica.plot_components(show_picks, title=ica_title % 'eog', colorbar=True, show=is_show) fig = [fig_eog_comp] report.add_figs_to_section(fig, captions=['TopoMap of ICs (EOG)'], section='ICA - EOG') fig_eog_src = ica.plot_sources(eog_evoked, exclude=eog_inds, show=is_show) fig = [fig_eog_src] report.add_figs_to_section(fig, captions=['Time-locked EOG sources'], section='ICA - EOG') # ----------------- end generate report for EoG ---------- # ic_nums = list(range(ica.n_components_)) fig = ica.plot_components(picks=ic_nums, show=False) report.add_figs_to_section(fig, captions=['All IC topographies'], section='ICA - muscles') fig = ica.plot_sources(raw, start=0, stop=None, show=False, title='All IC time series') report.add_figs_to_section(fig, captions=['All IC time series'], section='ICA - muscles') psds_fig = [] captions_psd = [] ica_src = ica.get_sources(raw) for i_ic in ic_nums: psds, freqs = psd_multitaper(ica_src, picks=i_ic, fmax=140, tmax=60) psds = np.squeeze(psds) f, ax = plt.subplots() psds = 10 * np.log10(psds) ax.plot(freqs, psds, color='k') ax.set(title='PSD', xlabel='Frequency', ylabel='Power Spectral Density (dB)') psds_fig.append(f) captions_psd.append('IC #' + str(i_ic)) report.add_figs_to_section(figs=psds_fig, captions=captions_psd, section='ICA - muscles') report_filename = os.path.join(basename + "-report.html") print(('******* ' + report_filename)) report.save(report_filename, open_browser=False, overwrite=True) return report_filename
for file_to_read in list_file_to_read: raw=mne.io.read_raw_fif(file_to_read[:-5]+'.fif',preload=True,add_eeg_ref=False) result[file_to_read[:-5]]=dict() channelList = ['F3','F4','C3','C4','O1','O2'] raw.pick_channels(channelList) picks = mne.pick_types(raw.info,eeg=True,eog=False) raw.filter(1,None,picks=picks,l_trans_bandwidth=0.5) fmin=0;fmax=50;epoch_length=30 epochs = eegPinelineDesign.make_overlap_windows(raw,epoch_length=epoch_length) psd_dict=dict() for names in channelList: psd_dict[names]=[] for ii,epch in enumerate(epochs): eegPinelineDesign.update_progress(ii,len(epochs)) psds, freqs = psd_multitaper(raw, low_bias=True, tmin=epch[0], tmax=epch[1], fmin=fmin, fmax=fmax, proj=False, picks=picks, n_jobs=-1) psds = 10 * np.log10(psds) for jj,names in enumerate(channelList): psd_dict[names].append(psds[jj,:]) psd_by_channel=dict() temp_total=[] fig=plt.figure(figsize=(30,30)) ax0=fig.add_subplot(331) for jj,names in enumerate(channelList): temp_total.append(psd_dict[names]) temp = np.vstack(psd_dict[names]) psd_by_channel[names]=[temp.mean(0),temp.std(0)] if jj == 0: ax = ax0 else:
epochs = mne.Epochs(raw, events, event_id, tmin, tmax, proj=True, baseline=(None, 0), preload=True, reject=dict(grad=4000e-13, eog=150e-6)) # Pull 2**n points to speed up computation tmax = tmin + 1023. / raw.info['sfreq'] epochs.crop(None, tmax) # Let's first check out all channel types by averaging across epochs. epochs.plot_psd(fmin=2, fmax=200) # picks MEG gradiometers picks = mne.pick_types(raw.info, meg='grad', eeg=False, eog=False, stim=False, exclude='bads') # Now let's take a look at the spatial distributions of the psd. epochs.plot_psd_topomap(ch_type='grad', normalize=True) # Alternatively, you may also create PSDs from Epochs objects with psd_XXX f, ax = plt.subplots() psds, freqs = psd_multitaper(epochs, fmin=2, fmax=200, picks=picks, n_jobs=1) psds = 10 * np.log10(psds) psds_mean = psds.mean(0).mean(0) psds_std = psds.mean(0).std(0) ax.plot(freqs, psds_mean, color='k') ax.fill_between(freqs, psds_mean - psds_std, psds_mean + psds_std, color='k', alpha=.5) ax.set(title='Multitaper PSD (gradiometers)', xlabel='Frequency', ylabel='Power Spectral Density (dB)') plt.show()
def Analyse_EEG(df): """ Analyses a dataframe containing raw EEG data """ # First we have to create the Raw MNE object to be # able to use the MNE library for the analysis eegchannels = df.iloc[:, 0:8] ch_names = list(eegchannels.columns) sfreq = 250 ch_types = ['eeg', 'eeg', 'eeg', 'eeg', 'eeg', 'eeg', 'eeg', 'eeg'] info = mne.create_info(ch_names, sfreq, ch_types=ch_types) raw = mne.io.RawArray(eegchannels.T, info) tmin, tmax = 0, len(raw.get_data('Ch1')[0]) # Data was already notch filtered during recording at around 50Hz. # psd_multitaper returns power spectral densities in psd (in this case # in shape (n_channels, n_freqs). The freqs contains information at # which frequency we had this power. The frequencies are spread between # the values defined below: fmin, fmax = 1, 100 psds, freqs = psd_multitaper(raw, low_bias=True, tmin=tmin, tmax=tmax, fmin=fmin, fmax=fmax, proj=True, picks=['all'], n_jobs=1) psds = 10 * np.log10(psds) psds_mean = psds.mean(0) psds_std = psds.std(0) # To convert the data into sensible band powers, we need to convert to Hz and extract the bands # The Hz conversion is data_length divided by (1/sampling freq) fft_freq = np.fft.rfftfreq((len(raw.get_data('Ch1')[0])), 1.0 / sfreq) # Define EEG bands eeg_bands = { 'Delta': (0, 4), 'Theta': (4, 8), 'Alpha': (8, 12), 'Beta': (12, 30), 'Gamma_low': (30, 45), 'Gamma_high': (55, 80) } eeg_band_fft = dict() for band in eeg_bands: freq_ix = np.where((fft_freq >= eeg_bands[band][0]) & (fft_freq <= eeg_bands[band][1]))[0] eeg_band_fft[band] = np.mean(psds[:, freq_ix], axis=1) for band in eeg_bands: freq_ix = np.where((fft_freq >= eeg_bands[band][0]) & (fft_freq <= eeg_bands[band][1]))[0] eeg_band_fft[band + '_std'] = np.std(psds[:, freq_ix], axis=1) # create a Pandas DataFrame, and normalize the values for each participant eeg_df = pd.DataFrame.from_dict(eeg_band_fft) # Lets normalize each participant: we are only interested in the relative differences between # electrodes overall_power_mean = np.mean(np.mean(eeg_df.iloc[:, 0:6])) eeg_df.iloc[:, 0:6] = eeg_df.iloc[:, 0:6] / overall_power_mean overall_std_mean = np.mean(np.mean(eeg_df.iloc[:, 6:])) eeg_df.iloc[:, 6:] = eeg_df.iloc[:, 6:] / overall_std_mean return eeg_df
############################################################################### # Let's first check out all channel types by averaging across epochs. epochs.plot_psd(fmin=2., fmax=40.) ############################################################################### # Now let's take a look at the spatial distributions of the PSD. epochs.plot_psd_topomap(ch_type='grad', normalize=True) ############################################################################### # Alternatively, you can also create PSDs from Epochs objects with functions # that start with ``psd_`` such as # :func:`mne.time_frequency.psd_multitaper` and # :func:`mne.time_frequency.psd_welch`. f, ax = plt.subplots() psds, freqs = psd_multitaper(epochs, fmin=2, fmax=40, n_jobs=1) psds = 10. * np.log10(psds) psds_mean = psds.mean(0).mean(0) psds_std = psds.mean(0).std(0) ax.plot(freqs, psds_mean, color='k') ax.fill_between(freqs, psds_mean - psds_std, psds_mean + psds_std, color='k', alpha=.5) ax.set(title='Multitaper PSD (gradiometers)', xlabel='Frequency', ylabel='Power Spectral Density (dB)') plt.show() ############################################################################### # Time-frequency analysis: power and inter-trial coherence # -------------------------------------------------------- #
def __init__(self, epochs, fmin=0, fmax=1500, tmin=None, tmax=None, method='multitaper', picks=None, montage=None, **kwargs): """ Computes the PSD of the epochs with the correct method multitaper or welch """ self.fmin, self.fmax = fmin, fmax self.tmin, self.tmax = tmin, tmax self.info = epochs.info self.method = method self.bandwidth = kwargs.get('bandwidth', 4.) self.n_fft = kwargs.get('n_fft', 256) self.n_per_seg = kwargs.get('n_per_seg', self.n_fft) self.n_overlap = kwargs.get('n_overlap', 0) self.cmap = 'inferno' if picks is not None: self.picks = picks else: self.picks = range(0, len(epochs.info['ch_names'])) if montage is not None: # First we create variable head_pos for a correct plotting self.pos = montage.get_pos2d() scale = 0.85 / (self.pos.max(axis=0) - self.pos.min(axis=0)) center = 0.5 * (self.pos.max(axis=0) + self.pos.min(axis=0)) self.head_pos = {'scale': scale, 'center': center} # Handling of possible channels without any known coordinates no_coord_channel = False try: names = montage.ch_names indices = [ names.index(epochs.info['ch_names'][i]) for i in self.picks ] self.pos = self.pos[indices, :] except: no_coord_channel = True # If there is not as much positions as the number of Channels # we have to eliminate some channels from the data of topomaps if no_coord_channel: print('got here') from mne.channels import read_montage from numpy import array index = 0 self.pos = [] # positions self.with_coord = [] # index in the self.data of channels # with a cooordinate for i in self.picks: ch_name = epochs.info['ch_names'][i] try: ch_montage = read_montage(montage.kind, ch_names=[ch_name]) coord = ch_montage.get_pos2d() self.pos.append(coord[0]) self.with_coord.append(index) except: pass index += 1 self.pos = array(self.pos) else: self.with_coord = [i for i in range(len(self.picks))] else: # If there is no montage available self.head_pos = None if method == 'multitaper': from mne.time_frequency import psd_multitaper print( "Computing Mulitaper PSD with parameter bandwidth = {}".format( self.bandwidth)) self.data, self.freqs = psd_multitaper(epochs, fmin=fmin, fmax=fmax, tmin=tmin, tmax=tmax, normalization='full', bandwidth=self.bandwidth, picks=self.picks) if method == 'welch': from mne.time_frequency import psd_welch print("Computing Welch PSD with parameters" + " n_fft = {}, n_per_seg = {}, n_overlap = {}".format( self.n_fft, self.n_per_seg, self.n_overlap)) self.data, self.freqs = psd_welch(epochs, fmin=fmin, fmax=fmax, tmin=tmin, tmax=tmax, n_fft=self.n_fft, n_overlap=self.n_overlap, n_per_seg=self.n_per_seg, picks=self.picks)
def frequency_analysis(epochs, states=[ 'meditate', 'baseline', 'lent', 'rapide', 'libre', 'resting1', 'val' ], show=True, pick='C4'): ''' Function to return psd of each state Parameters ---------- epochs : Epoch object states: list of strings (default all) show : wether do plot the psd (default = True) pick : if show = True, the channel to plot (string) Return ------ list_alphas := list of alpha powers[{'C4': [.....], 'P4' : [....]},{'C4': ....} ] (len(list_alphas) = len(states)) list_betas := list of beta powers list_thetas := list of theta powers list_baratio := list of Beta/alpha ratios ''' states = states nstate = [len(epochs[state]) for state in states] pick = pick alpha_band = 9.3 list_alphas, list_betas, list_thetas, list_ab = [], [], [], [] chan_alphas, chan_betas, chan_thetas, chan_ab = { 'C4': [], 'P4': [], 'O2': [], 'Fp': [] }, { 'C4': [], 'P4': [], 'O2': [], 'Fp': [] }, { 'C4': [], 'P4': [], 'O2': [], 'Fp': [] }, { 'C4': [], 'P4': [], 'O2': [], 'Fp': [] } for index, state in enumerate(states): print(state) for channel in ['C4', 'P4', 'O2', 'Fp']: if channel == 'Fp': raw = epochs[state].copy().pick_channels(['Fp2']) else: raw = epochs[state].copy().pick_channels([channel]) psds, freqs = psd_multitaper(raw, low_bias=True, fmin=2, fmax=40, n_jobs=1) psds = 10 * np.log10(psds) psds = psds.mean(1) test = psds.mean(0) psds_std = psds.mean(0).std(0) if channel == pick and (state not in []): plt.plot(freqs, test) plt.legend(states) plt.title('PSD of electrode ' + pick) plt.xlabel('frequency (Hz)') plt.ylabel('Power (dB)') plt.fill_between(freqs, test - psds_std, test + psds_std, alpha=.1) for t, epochspsds in enumerate(psds): xx = freqs[((freqs > alpha_band - 2) & (freqs < alpha_band + 2))] yy = epochspsds[(freqs > alpha_band - 2) & (freqs < alpha_band + 2)] alphach = (auc(xx, yy)) chan_alphas[channel].append(alphach) xx = freqs[((freqs < alpha_band - 2) & (freqs > alpha_band - 6))] yy = epochspsds[((freqs < alpha_band - 2) & (freqs > alpha_band - 6))] thetach = (auc(xx, yy)) chan_thetas[channel].append(thetach) xx = freqs[((freqs > alpha_band + 2) & (freqs < 40))] yy = epochspsds[((freqs > alpha_band + 2) & (freqs < 40))] betach = (auc(xx, yy)) chan_betas[channel].append(betach) chan_ab[channel].append((betach / alphach)) list_alphas.append(chan_alphas) list_betas.append(chan_betas) list_thetas.append(chan_thetas) list_ab.append(chan_ab) chan_alphas, chan_betas, chan_thetas, chan_ab = { 'C4': [], 'P4': [], 'O2': [], 'Fp': [] }, { 'C4': [], 'P4': [], 'O2': [], 'Fp': [] }, { 'C4': [], 'P4': [], 'O2': [], 'Fp': [] }, { 'C4': [], 'P4': [], 'O2': [], 'Fp': [] } print('MAR : ' + str(len(list_alphas))) alphas = [ round( mean(list_alphas[i]['C4'] + list_alphas[i]['P4'] + list_alphas[i]['O2'] + list_alphas[i]['Fp']), 2) for i in range(len(states) - 1) ] betas = [ round( mean(list_betas[i]['C4'] + list_betas[i]['P4'] + list_betas[i]['O2'] + list_betas[i]['Fp']), 2) for i in range(len(states) - 1) ] thetas = [ round( mean(list_thetas[i]['C4'] + list_thetas[i]['P4'] + list_thetas[i]['O2'] + list_thetas[i]['Fp']), 2) for i in range(len(states) - 1) ] ab = [ round( mean(list_ab[i]['C4'] + list_ab[i]['P4'] + list_ab[i]['O2'] + list_ab[i]['Fp']), 2) for i in range(len(states) - 1) ] plt.show() return list_alphas, list_betas, list_thetas, list_ab, alphas, betas, thetas, ab
#our recording standard: 10-20 montage = mne.channels.read_montage('standard_1020') k = 0 #i is the subject id for i in range(1, 6): for j in range(1, 5): #read for word-task, j is the trial code fname = data_path + "/Dataset/d" + str(i) + "-ep1-" + str(j) + ".set" raw = io.eeglab.read_raw_eeglab(fname, montage=montage) #measure the distribution of low-beta psds, freqs = psd_multitaper(raw, low_bias=True, fmin=12, fmax=16, proj=True, n_jobs=1) psds = 10 * np.log10(psds) low_beta_count[k][0] = psds.mean() low_beta_count[k][1] = psds.std() #measure the distribution of middle-beta psds, freqs = psd_multitaper(raw, low_bias=True, fmin=16, fmax=22, proj=True, n_jobs=1) psds = 10 * np.log10(psds) middle_beta_count[k][0] = psds.mean()