def load_power_spectra_from_files(*file_numbers, low_freq = None, high_freq = None, step = 1, filter = False): '''Returns a list, where each element is a tuple corresponding to a picture block, where first element is a tuple, where first element is a 2D np.array with first index corresponding to channel number and second index corresponding frequency and second element is a np.array where i-th element is the i-th frequency, in Hz and second element is a tuple of patient's arousal and valence evaluation (or may be other way around, it's just the way they are ordered in file). Visually: [ ( ( [[ch1pow1,ch1pow2,...],[ch2pow1,ch2pow2...],...], [freq1, freq2, ...] ), (arousal, valence) ), ( ( [[ch1pow1,ch1pow2,...],[ch2pow1,ch2pow2...],...], [freq1, freq2, ...] ), (arousal, valence) ), ... ] ] Parameters: - file_numbers - indices of available EEG files (from 0 to 10). There are loaded all blocks for each number in the order their indices are passed, i.e. load_data_from_files(3,1,2,3) will first return data for all blocks from file of index 3, then index 1, 2 and 3 again (duplicated). - low_freq - low frequency used for power spectra calcuation, in Hz - high_freq - high frequency used for power spectra calcuation, in Hz - step - the frequency step in returned power spectrum - filter - if True, the data will be explicitly filtered before power spectra calculation between the given frequencies This function uses mne function to get power spectra directly from whole EEG while defining frequencies. Notice that low_freq and high_freq are keyword-only parameters.''' available_eeg_paths_snapshot = available_eeg_paths() eegs_to_load = [available_eeg_paths_snapshot[i] for i in file_numbers] markers_to_load = [single_eeg_to_load + '.mrk' for single_eeg_to_load in eegs_to_load] evals_to_load = [_eval_path_from_eeg_path(single_eeg_to_load) for single_eeg_to_load in eegs_to_load] loaded_data = [] for eeg_path, marker_path, eval_path in zip(eegs_to_load, markers_to_load, evals_to_load): block_ranges = _load_block_ranges_from_marker(marker_path) # list of tuples eval_list = _load_evals(eval_path) raw_eeg = mne.io.read_raw_edf(eeg_path, preload = True) raw_eeg.pick_channels(raw_eeg.info["ch_names"][:-8]) if filter and not (low_freq is None and high_freq is None): raw_eeg.filter(low_freq, high_freq) low_freq = low_freq if low_freq is not None else 0 high_freq = high_freq if high_freq is not None else float("inf") for (eeg_start, eeg_end), single_eval in zip(block_ranges, eval_list): sample_freq = raw_eeg.info["sfreq"] block_frequencies = psd.psd_welch(raw_eeg, low_freq, high_freq, raw_eeg.times[eeg_start], raw_eeg.times[eeg_end], n_fft = round(sample_freq / step)) picture_block_data = (block_frequencies, single_eval) loaded_data.append(picture_block_data) # raw_eeg[channel's, sample's][tuple_elem(0=samples,1=times)] block_eeg = np.array(raw_eeg[0:-1, eeg_start:eeg_end + 1][0]) block_data = (block_eeg, single_eval) loaded_data.append(block_data) return loaded_data
def power_spectrum(self, low_freq = None, high_freq = None, step = 1): '''Returns a tuple, where first element is a 2D np.array with first index corresponding to channel number and second index corresponding frequency and second element is a np.array where i-th element is the i-th frequency, in Hz. The frequencies will be from low_freq to high_freq, inclusive, with step step.''' if low_freq is None: low_freq = self._low_freq if self._low_freq is not None else 0 if high_freq is None: high_freq = self._high_freq if self._high_freq is not None else float("inf") sample_freq = self.mne_eeg.info["sfreq"] return psd.psd_welch(self.mne_eeg, low_freq, high_freq, n_fft = round(sample_freq / step))
def remove_linenoise(raw, noise_freq, width=2, shuffle_time=True, decim=100, n_component=1, plot=False, copy=True, picks=None, harmonics=True): import matplotlib.pyplot as plt from mne import pick_types from mne.preprocessing import ICA from mne.time_frequency.psd import psd_welch # Setup line frequency if isinstance(noise_freq, str): # automatic harmonics if noise_freq == 'us': noise_freq = 60 else: noise_freq = 50 elif not isinstance(noise_freq, (float, int)): raise NotImplementedError('Multiple bands') def plot_psd(psd, freqs, ax, title): for psd_ in psd: ax.plot(freqs, np.log10(psd_)) ax.set_xlabel('Frequencies') ax.set_title(title) if copy: raw = raw.copy() if picks is None: picks = pick_types(raw.info, eeg=True, meg=True, seeg=True) if plot: fig, axes = plt.subplots(1, 3, sharex=True) psd, freqs = psd_welch(raw, picks=picks) plot_psd(psd, freqs, axes[0], 'Raw Sensors') # Fit ICA on filtered data raw_ = raw.copy() if harmonics: # set up harmonics n_harm = raw_.info['sfreq'] // (2. * noise_freq) + 1 harmonics = noise_freq * np.arange(1, n_harm) # Band pass filtering outside lowest harmonics and nquist raw_.filter(noise_freq - width, harmonics[-1] + width) # Band stop filter in between harmonics raw_.notch_filter(freqs=harmonics[:-1] + noise_freq // 2, notch_widths=noise_freq - 2 * width) else: raw_.filter(noise_freq - width, noise_freq + width) # Shuffle time axis to avoid decimation aliasing if shuffle_time: time = np.arange(raw_.n_times) np.random.shuffle(time) raw_._data[:, time] = raw_._data ica = ICA(verbose=False) ica.fit(raw_, decim=decim, picks=picks) # Compute PSD of components raw_._data[picks, :] = np.dot(ica.mixing_matrix_, raw._data[picks, :]) psd, freqs = psd_welch(raw_, picks=picks) if plot: plot_psd(psd, freqs, axes[1], 'Components') # Find noise component and remove freq = np.where(freqs >= noise_freq)[0][0] sel = np.argsort(psd[:, freq])[-n_component:].tolist() raw_ = ica.apply(raw, exclude=sel, copy=True) if plot: psd, freqs = psd_welch(raw_, picks=picks) plot_psd(psd, freqs, axes[2], 'Clean sensors') return raw_
def remove_linenoise(raw, noise_freq, width=2, shuffle_time=True, decim=100, n_component=1, plot=False, copy=True, picks=None, harmonics=True): import matplotlib.pyplot as plt from mne import pick_types from mne.preprocessing import ICA from mne.time_frequency.psd import psd_welch # Setup line frequency if isinstance(noise_freq, str): # automatic harmonics if noise_freq == 'us': noise_freq = 60 else: noise_freq = 50 elif not isinstance(noise_freq, (float, int)): raise NotImplementedError('Multiple bands') def plot_psd(psd, freqs, ax, title): for psd_ in psd: ax.plot(freqs, np.log10(psd_)) ax.set_xlabel('Frequencies') ax.set_title(title) if copy: raw = raw.copy() if picks is None: picks = pick_types(raw.info, eeg=True, meg=True, seeg=True) if plot: fig, axes = plt.subplots(1, 3, sharex=True) psd, freqs = psd_welch(raw, picks=picks) plot_psd(psd, freqs, axes[0], 'Raw Sensors') # Fit ICA on filtered data raw_ = raw.copy() if harmonics: # set up harmonics n_harm = raw_.info['sfreq'] // (2. * noise_freq) + 1 harmonics = noise_freq * np.arange(1, n_harm) # Band pass filtering outside lowest harmonics and nquist raw_.filter(noise_freq - width, harmonics[-1] + width) # Band stop filter in between harmonics raw_.notch_filter(freqs=harmonics[:-1]+noise_freq//2, notch_widths=noise_freq - 2*width) else: raw_.filter(noise_freq-width, noise_freq+width) # Shuffle time axis to avoid decimation aliasing if shuffle_time: time = np.arange(raw_.n_times) np.random.shuffle(time) raw_._data[:, time] = raw_._data ica = ICA(verbose=False) ica.fit(raw_, decim=decim, picks=picks) # Compute PSD of components raw_._data[picks, :] = np.dot(ica.mixing_matrix_, raw._data[picks, :]) psd, freqs = psd_welch(raw_, picks=picks) if plot: plot_psd(psd, freqs, axes[1], 'Components') # Find noise component and remove freq = np.where(freqs >= noise_freq)[0][0] sel = np.argsort(psd[:, freq])[-n_component:].tolist() raw_ = ica.apply(raw, exclude=sel, copy=True) if plot: psd, freqs = psd_welch(raw_, picks=picks) plot_psd(psd, freqs, axes[2], 'Clean sensors') return raw_
def calcPSD(self, raw, fmin, fmax, picks=None): return psd_welch(raw, fmin, fmax, picks=picks)