def filter_data(data: mne.io.RawArray, notch: float, low_pass: float, high_pass: float) -> mne.io.RawArray: # data.notch_filter(freqs=notch, verbose=False) data.filter(l_freq=low_pass, h_freq=high_pass, verbose=False) return data
def raw_add_annotations(raw: mne.io.RawArray, marker_streams=None) -> mne.io.RawArray: t_reference = raw._t_original if marker_streams: for stream in marker_streams: annotations = marker_stream2annotations(stream, t_reference=t_reference) raw.set_annotations(raw.annotations + annotations) return raw
def filter_by_frequency_bands(eeg: mne.io.RawArray, filt_bands=[(1, 3), (3, 10), (10, 20), (20, 60)], hilbert=False): """ Applies bandpass filtering in the specified frequency bands to all eeg channels, appends to eeg data. Operates in place. """ for fband in filt_bands: raw_filt = eeg.copy() fband_name = '_' + str(fband[0]) + "Hz-" + str(fband[1]) + 'Hz' channel_name_remap = {chan: chan + fband_name for chan in eeg.ch_names} raw_filt.filter(*fband, h_trans_bandwidth='auto', l_trans_bandwidth='auto', filter_length='auto', phase='zero') # Filter all EEG Data raw_filt.rename_channels(channel_name_remap) if hilbert: raw_hilb = raw_filt.copy() raw_hilb.apply_hilbert() raw_hilb.apply_function(np.abs) channel_name_remap = { chan: chan + '_env' for chan in raw_filt.ch_names } raw_hilb.rename_channels(channel_name_remap) return raw_filt, raw_hilb #TODO APPEND THIS SHIT return raw_filt
def fit(self, raw: mne.io.RawArray, start: float = None, stop: float = None, reject_by_annotation: bool = True, gfp: bool = False, n_jobs: int = 1, verbose=None) -> mod_Kmeans: """[summary] Args: raw (mne.io.RawArray): [description] start (float, optional): [description]. Defaults to None. stop (float, optional): [description]. Defaults to None. reject_by_annotation (bool, optional): [description]. Defaults to True. gfp (bool, optional): [description]. Defaults to False. n_jobs (int, optional): [description]. Defaults to 1. verbose ([type], optional): [description]. Defaults to None. Returns: mod_Kmeans: [description] """ _validate_type(raw, (BaseRaw), 'raw', 'Raw') reject_by_annotation = 'omit' if reject_by_annotation else None start, stop = _check_start_stop(raw, start, stop) n_jobs = check_n_jobs(n_jobs) if len(raw.info['bads']) is not 0: warn('Bad channels are present in the recording. ' 'They will still be used to compute microstate topographies. ' 'Consider using Raw.pick() or Raw.interpolate_bads()' ' before fitting.') data = raw.get_data(start, stop, reject_by_annotation=reject_by_annotation) if gfp is True: data = _extract_gfps(data) best_gev = 0 if n_jobs == 1: for _ in range(self.n_init): gev, maps, segmentation = self._run_mod_kmeans(data) if gev > best_gev: best_gev, best_maps, best_segmentation = gev, maps, segmentation else: parallel, p_fun, _ = parallel_func(self._run_mod_kmeans, total=self.n_init, n_jobs=n_jobs) runs = parallel(p_fun(data) for i in range(self.n_init)) runs = np.array(runs) best_run = np.argmax(runs[:, 0]) best_gev, best_maps, best_segmentation = runs[best_run] self.cluster_centers = best_maps self.GEV = best_gev self.labels = best_segmentation self.current_fit = True return (self)
def add_events_df_to_mne_raw(mne_raw: mne.io.RawArray, events_df, orig_time): if mne_raw.annotations: mne_raw.annotations.append(onset=events_df['onset'] + orig_time, duration=events_df['duration'], description=events_df['description']) return mne_raw return mne_raw.set_annotations( mne_annotations_from_dataframe(events_df, orig_time))
def predict(self, raw: mne.io.RawArray, reject_by_annotation: bool = True, half_window_size: int = 3, factor: int = 10, crit: float = 10e-6, verbose: str = None) -> np.ndarray: """[summary] Args: raw (mne.io.RawArray): [description] reject_by_annotation (bool, optional): [description]. Defaults to True. half_window_size (int, optional): [description]. Defaults to 3. factor (int, optional): [description]. Defaults to 10. crit (float, optional): [description]. Defaults to 10e-6. verbose (str, optional): [description]. Defaults to None. Raises: ValueError: [description] Returns: np.ndarray: [description] """ if self.current_fit is False: raise ValueError('mod_Kmeans is not fitted.') data = raw.get_data() if reject_by_annotation: onsets, _ends = _annotations_starts_stops(raw, ['BAD']) if len(onsets) == 0: return (segment(data, self.cluster_centers, half_window_size, factor, crit)) onsets = onsets.tolist() onsets.append(data.shape[-1] - 1) _ends = _ends.tolist() ends = [0] ends.extend(_ends) segmentation = np.zeros(data.shape[-1]) for onset, end in zip(onsets, ends): if onset - end >= 2 * half_window_size + 1: # small segments can't be smoothed sample = data[:, end:onset] print(onset, end, type(end), type(onset)) segmentation[end:onset] = segment(sample, self.cluster_centers, half_window_size, factor, crit) return (segmentation) else: return (segment(data, self.cluster_centers, half_window_size, factor, crit))
def filter_data(data: mne.io.RawArray, notch: float, low_pass: float, high_pass: float) -> mne.io.RawArray: data.notch_filter(freqs=notch) data.filter(l_freq=low_pass, h_freq=None) data.filter(l_freq=None, h_freq=high_pass) return data
def _pyedf_saveas_edf( self, mne_raw: mne.io.RawArray, fname: Union[os.PathLike, str], events_list: List[Union[float, float, str]], picks=None, tmin=0, tmax=None, overwrite=False, ): """ Saves the raw content of an MNE.io.Raw and its subclasses to a file using the EDF+ filetype pyEDFlib is used to save the raw contents of the RawArray to disk Parameters ---------- mne_raw : mne.io.RawArray An object with super class mne.io.Raw that contains the data to save fname : string File name of the new dataset. This has to be a new filename unless data have been preloaded. Filenames should end with .edf picks : array-like of int | None Indices of channels to include. If None all channels are kept. tmin : float | None Time in seconds of first sample to save. If None first sample is used. tmax : float | None Time in seconds of last sample to save. If None last sample is used. overwrite : bool If True, the destination file (if it exists) will be overwritten. If False (default), an error will be raised if the file exists. """ if not issubclass(type(mne_raw), mne.io.BaseRaw): raise TypeError("Must be mne.io.Raw type") if not overwrite and os.path.exists(fname): raise OSError("File already exists. No overwrite.") # static settings file_type = pyedflib.FILETYPE_EDFPLUS sfreq = mne_raw.info["sfreq"] date = datetime.datetime.now().strftime("%d %b %Y %H:%M:%S") first_sample = int(sfreq * tmin) last_sample = int(sfreq * tmax) if tmax is not None else None # convert data channels = mne_raw.get_data(picks, start=first_sample, stop=last_sample) # convert to microvolts to scale up precision channels *= 1e6 # set conversion parameters dmin, dmax = [-32768, 32767] pmin, pmax = [channels.min(), channels.max()] n_channels = len(channels) # create channel from this print(fname) f = pyedflib.EdfWriter(fname, n_channels=n_channels, file_type=file_type) try: channel_info = [] data_list = [] for i in range(n_channels): ch_dict = { "label": mne_raw.ch_names[i], "dimension": "uV", "sample_rate": sfreq, "physical_min": pmin, "physical_max": pmax, "digital_min": dmin, "digital_max": dmax, "transducer": "", "prefilter": "", } channel_info.append(ch_dict) data_list.append(channels[i]) f.setTechnician("eegio") f.setSignalHeaders(channel_info) for event in events_list: onset_in_seconds, duration_in_seconds, description = event f.writeAnnotation( float(onset_in_seconds), int(duration_in_seconds), description ) f.setStartdatetime(date) f.writeSamples(data_list) except Exception as e: print(e) return False finally: f.close() return True
def rereference(edf: mne.io.RawArray, desired_ref: str, current_ref: str = None, pick_chans: list = None) -> Tuple[mne.io.RawArray, str]: """ reference an edf. M1 and M2 should be included, but NOT as eeg stype in the mne.io.RawArray. contra_mastoid reref will be undone if needed but this requires M1 and M2 PRIOR to any referencing. :param edf: edf to re-ref :param current_ref: current reference type, can be "contra_mastoid",'linked_ear' or a channel name :param desired_ref: current reference type, can be "contra_mastoid",'linked_ear' or a channel name. If None, assumed it is a common channels :return: """ if pick_chans is None: chans = edf.ch_names else: chans = pick_chans if current_ref == desired_ref: return edf, current_ref if desired_ref in ['linked_ear' ] and 'M1' not in chans or 'M2' not in chans: warnings.warn( 'Trying to reference to linked ear, but missing M1 and M2 channels. EEG file will not be re-referenced', EEGWarning) return edf, current_ref if current_ref == 'contra_mastoid': to_reref = [ch for ch in chans if ch not in ['M1', 'M2']] left = [ ch for ch in to_reref if len([n for n in ['1', '3', '5', '7', '9'] if n in ch]) > 0 ] right = [ ch for ch in to_reref if len([n for n in ['2', '4', '6', '8', '10'] if n in ch]) > 0 ] if len(left) > 0 and 'M2' not in chans: warnings.warn( 'Trying to reference to left channels to M2 ear, but missing M2 channel. left channels cannot be unreferenced' ) left_ref = [] left = [] else: left_ref = ['M2'] * len(left) if len(right) > 0 and 'M1' not in chans: warnings.warn( 'Trying to reference to right channels to M1 ear, but missing M1 channel. right channels cannot be unreferenced' ) right_ref = [] right = [] else: right_ref = ['M1'] * len(right) edf = edf.apply_function(lambda x: -x, picks=['M1', 'M2']) edf = mne.set_bipolar_reference(edf, left + right, left_ref + right_ref, drop_refs=False, verbose=False) edf = edf.drop_channels(left + right) edf.rename_channels({ch: ch.split('-')[0] for ch in edf.ch_names}) edf = edf.apply_function(lambda x: -x, picks=['M1', 'M2']) ref_type = desired_ref if desired_ref == 'contra_mastoid': if current_ref == 'linked_ear': edf = edf.apply_function(lambda x: -x, picks=['M1', 'M2']) edf, _ = mne.set_eeg_reference(edf, ref_channels=['M1', 'M2'], verbose=False) edf = edf.apply_function(lambda x: -x, picks=['M1', 'M2']) to_reref = [ch for ch in chans if ch not in ['M1', 'M2']] left = [ ch for ch in to_reref if len([n for n in ['1', '3', '5', '7', '9', 'z'] if n in ch]) > 0 ] right = [ ch for ch in to_reref if len([n for n in ['2', '4', '6', '8', '10'] if n in ch]) > 0 ] if len(left) > 0 and 'M2' not in chans: warnings.warn( 'Trying to reference to left channels to M2 ear, but missing M2 channel. left channels will not be re-referenced' ) left_ref = [] left = [] ref_type = 'contra_right_only' else: left_ref = ['M2'] * len(left) if len(right) > 0 and 'M1' not in chans: warnings.warn( 'Trying to reference to right channels to M1 ear, but missing M1 channel. right channels will not be re-referenced' ) right_ref = [] right = [] ref_type = 'contra_left_only' else: right_ref = ['M1'] * len(right) edf = mne.set_bipolar_reference(edf, left + right, left_ref + right_ref, drop_refs=False, verbose=False) edf = edf.drop_channels(left + right) edf.rename_channels({ch: ch.split('-')[0] for ch in edf.ch_names}) elif desired_ref == 'linked_ear': edf, _ = mne.set_eeg_reference(edf, ref_channels=['M1', 'M2'], verbose=False) else: edf, _ = mne.set_eeg_reference(edf, ref_channels=desired_ref, verbose=False) return edf, ref_type
def write_edf_from_mne_raw_array(mne_raw: mne.io.RawArray, fname: str, ref_type='', annotations=False, new_date=False, picks=None, tmin=0, tmax=None, overwrite=True): """ Saves the raw content of an MNE.io.Raw and its subclasses to a file using the EDF+ filetype pyEDFlib is used to save the raw contents of the RawArray to disk Parameters ---------- mne_raw : mne.io.Raw An object with super class mne.io.Raw that contains the data to save fname : string File name of the new dataset. This has to be a new filename unless data have been preloaded. Filenames should end with .edf picks : array-like of int | None Indices of channels to include. If None all channels are kept. tmin : float | None Time in seconds of first sample to save. If None first sample is used. tmax : float | None Time in seconds of last sample to save. If None last sample is used. overwrite : bool If True, the destination file (if it exists) will be overwritten. If False (default), an error will be raised if the file exists. """ if not issubclass(type(mne_raw), mne.io.BaseRaw): raise TypeError('Must be mne.io.Raw type') if not overwrite and os.path.exists(fname): raise OSError('File already exists. No overwrite.') # static settings if annotations: file_type = pyedflib.FILETYPE_EDFPLUS else: file_type = pyedflib.FILETYPE_EDF sfreq = mne_raw.info['sfreq'] date = datetime.now().strftime('%d %b %Y %H:%M:%S') if new_date \ else (datetime.fromtimestamp(mne_raw.info['meas_date'][0])).strftime('%d %b %Y %H:%M:%S') first_sample = int(sfreq * tmin) last_sample = int(sfreq * tmax) if tmax is not None else None # convert data channels = mne_raw.get_data(picks, start=first_sample, stop=last_sample) # convert to microvolts to scale up precision channels *= 1e6 # set conversion parameters dmin, dmax = [-32768, 32767] pmin, pmax = [channels.min(), channels.max()] n_channels = len(channels) # create channel from this try: f = pyedflib.EdfWriter(fname, n_channels=n_channels, file_type=file_type) channel_info = [] data_list = [] for i in range(n_channels): ch_dict = { 'label': mne_raw.ch_names[i], 'dimension': 'uV', 'sample_rate': sfreq, 'physical_min': pmin, 'physical_max': pmax, 'digital_min': dmin, 'digital_max': dmax, 'transducer': '', 'prefilter': '' } channel_info.append(ch_dict) data_list.append(channels[i]) f.setTechnician('mednickdb') f.setEquipment('ref=' + ref_type) f.setSignalHeaders(channel_info) f.setStartdatetime(date) f.writeSamples(data_list) except Exception as e: raise IOError('EDF could not be written') from e finally: f.close() return True