def load_eeg(events, rel_start_ms, rel_stop_ms, buf_ms=0, elec_scheme=None, noise_freq=[58., 62.], resample_freq=None, pass_band=None, use_mirror_buf=False, demean=False, do_average_ref=False): """ Returns an EEG TimeSeries object. Parameters ---------- events: pandas.DataFrame An events dataframe that contains eegoffset and eegfile fields rel_start_ms: int Initial time (in ms), relative to the onset of each event rel_stop_ms: int End time (in ms), relative to the onset of each event buf_ms: Amount of time (in ms) of buffer to add to both the begining and end of the time interval elec_scheme: pandas.DataFrame A dataframe of electrode information, returned by load_elec_info(). If the column 'contact' is in the dataframe, monopolar electrodes will be loads. If the columns 'contact_1' and 'contact_2' are in the df, bipolar will be loaded. You may pass in a subset of rows to only load data for electrodes in those rows. If you do not enter an elec_scheme, all monopolar channels will be loaded (but they will not be labeled with correct channel tags). Entering a scheme is recommended. noise_freq: list Stop filter will be applied to the given range. Default=(58. 62) resample_freq: float Sampling rate to resample to after loading eeg. pass_band: list If given, the eeg will be band pass filtered in the given range. use_mirror_buf: bool If True, the buffer will be data taken from within the rel_start_ms to rel_stop_ms interval, mirrored and prepended and appended to the timeseries. If False, data outside the rel_start_ms and rel_stop_ms interval will be read. demean: bool If True, will subject the mean voltage between rel_start_ms and rel_stop_ms from each channel do_average_ref: bool If True, will compute the average reference based on the mean voltage across channels Returns ------- TimeSeries EEG timeseries object with dimensions channels x events x time (or bipolar_pairs x events x time) NOTE: The EEG data is returned with time buffer included. If you included a buffer and want to remove it, you may use the .remove_buffer() method. EXTRA NOTE: INPUT SECONDS FOR REMOVING BUFFER, NOT MS!! """ # add buffer is using if (buf_ms is not None) and not use_mirror_buf: actual_start = rel_start_ms - buf_ms actual_stop = rel_stop_ms + buf_ms else: actual_start = rel_start_ms actual_stop = rel_stop_ms # load eeg # Should auto convert to PTSA? Any reason not to? eeg = CMLReader(subject=events.iloc[0].subject).load_eeg( events, rel_start=actual_start, rel_stop=actual_stop, scheme=elec_scheme).to_ptsa() # compute average reference by subracting the mean across channels if do_average_ref: eeg = eeg - eeg.mean(dim='channel') # baseline correct subracting the mean within the baseline time range if demean: eeg = eeg.baseline_corrected([rel_start_ms, rel_stop_ms]) # add mirror buffer if using. PTSA is expecting this to be in seconds. if use_mirror_buf: eeg = eeg.add_mirror_buffer(buf_ms / 1000.) # filter line noise if noise_freq is not None: if isinstance(noise_freq[0], float): noise_freq = [noise_freq] for this_noise_freq in noise_freq: b_filter = ButterworthFilter(eeg, this_noise_freq, filt_type='stop', order=4) eeg = b_filter.filter() # resample if desired. Note: can be a bit slow especially if have a lot of eeg data if resample_freq is not None: r_filter = ResampleFilter(eeg, resample_freq) eeg = r_filter.filter() # do band pass if desired. if pass_band is not None: eeg = band_pass_eeg(eeg, pass_band) # reorder dims to make events first eeg = make_events_first_dim(eeg) return eeg
def load_eeg(events, rel_start_ms, rel_stop_ms, buf_ms=0, elec_scheme=None, noise_freq=[58., 62.], resample_freq=None, pass_band=None, use_mirror_buf=False, demean=False, do_average_ref=False): """ Returns an EEG TimeSeries object. Parameters ---------- events: pandas.DataFrame An events dataframe that contains eegoffset and eegfile fields rel_start_ms: int Initial time (in ms), relative to the onset of each event rel_stop_ms: int End time (in ms), relative to the onset of each event buf_ms: Amount of time (in ms) of buffer to add to both the begining and end of the time interval elec_scheme: pandas.DataFrame A dataframe of electrode information, returned by load_elec_info(). If the column 'contact' is in the dataframe, monopolar electrodes will be loads. If the columns 'contact_1' and 'contact_2' are in the df, bipolar will be loaded. You may pass in a subset of rows to only load data for electrodes in those rows. If you do not enter an elec_scheme, all monopolar channels will be loaded (but they will not be labeled with correct channel tags). Entering a scheme is recommended. noise_freq: list Stop filter will be applied to the given range. Default=(58. 62) resample_freq: float Sampling rate to resample to after loading eeg. pass_band: list If given, the eeg will be band pass filtered in the given range. use_mirror_buf: bool If True, the buffer will be data taken from within the rel_start_ms to rel_stop_ms interval, mirrored and prepended and appended to the timeseries. If False, data outside the rel_start_ms and rel_stop_ms interval will be read. demean: bool If True, will subject the mean voltage between rel_start_ms and rel_stop_ms from each channel do_average_ref: bool If True, will compute the average reference based on the mean voltage across channels Returns ------- TimeSeries EEG timeseries object with dimensions channels x events x time (or bipolar_pairs x events x time) NOTE: The EEG data is returned with time buffer included. If you included a buffer and want to remove it, you may use the .remove_buffer() method. EXTRA NOTE: INPUT SECONDS FOR REMOVING BUFFER, NOT MS!! """ # check if monopolar is possible for this subject if 'contact' in elec_scheme: eegfile = np.unique(events.eegfile)[0] if os.path.splitext(eegfile)[1] == '.h5': eegfile = f'/protocols/r1/subjects/{events.iloc[0].subject}/experiments/{events.iloc[0].experiment}/sessions/{events.iloc[0].session}/ephys/current_processed/noreref/{eegfile}' with h5py.File(eegfile, 'r') as f: if not np.array(f['monopolar_possible'])[0] == 1: print('Monopolar referencing not possible for {}'.format( events.iloc[0].subject)) return # add buffer is using if (buf_ms is not None) and not use_mirror_buf: actual_start = rel_start_ms - buf_ms actual_stop = rel_stop_ms + buf_ms else: actual_start = rel_start_ms actual_stop = rel_stop_ms # load eeg eeg = CMLReader(subject=events.iloc[0].subject).load_eeg( events, rel_start=actual_start, rel_stop=actual_stop, scheme=elec_scheme).to_ptsa() # now auto cast to float32 to help with memory issues with high sample rate data eeg.data = eeg.data.astype('float32') # baseline correct subracting the mean within the baseline time range if demean: eeg = eeg.baseline_corrected([rel_start_ms, rel_stop_ms]) # compute average reference by subracting the mean across channels if do_average_ref: eeg = eeg - eeg.mean(dim='channel') # add mirror buffer if using. PTSA is expecting this to be in seconds. if use_mirror_buf: eeg = eeg.add_mirror_buffer(buf_ms / 1000.) # filter line noise if noise_freq is not None: if isinstance(noise_freq[0], float): noise_freq = [noise_freq] for this_noise_freq in noise_freq: for this_chan in range(eeg.shape[1]): b_filter = ButterworthFilter(eeg[:, this_chan:this_chan + 1], this_noise_freq, filt_type='stop', order=4) eeg[:, this_chan:this_chan + 1] = b_filter.filter() # resample if desired. Note: can be a bit slow especially if have a lot of eeg data # pdb.set_trace() # if resample_freq is not None: # for this_chan in range(eeg.shape[1]): # r_filter = ResampleFilter(eeg[:, this_chan:this_chan+1], resample_freq) # eeg[:, this_chan:this_chan + 1] = r_filter.filter() if resample_freq is not None: eeg_resamp = [] for this_chan in range(eeg.shape[1]): r_filter = ResampleFilter(eeg[:, this_chan:this_chan + 1], resample_freq) eeg_resamp.append(r_filter.filter()) coords = {x: eeg[x] for x in eeg.coords.keys()} coords['time'] = eeg_resamp[0]['time'] coords['samplerate'] = resample_freq dims = eeg.dims eeg = TimeSeries.create(np.concatenate(eeg_resamp, axis=1), resample_freq, coords=coords, dims=dims) # do band pass if desired. if pass_band is not None: eeg = band_pass_eeg(eeg, pass_band) # reorder dims to make events first eeg = make_events_first_dim(eeg) return eeg