示例#1
0
def load_eeg_from_times(df,
                        channel_file,
                        rel_start_ms,
                        rel_stop_ms,
                        buf_ms=0,
                        noise_freq=[58., 62.],
                        downsample_freq=1000,
                        resample_freq=None,
                        pass_band=None):
    """

    Parameters
    ----------
    df: pandas.DataFrame
        An dataframe with a stTime column
    channel_file: str
        Path to Ncs file from which to load eeg.
    rel_start_ms: int
        Initial time (in ms), relative to the onset of each spike
    rel_stop_ms: int
        End time (in ms), relative to the onset of each spike
    buf_ms: int
        Amount of time (in ms) of buffer to add to both the beginning and end of the time interval
    noise_freq: list
        Stop filter will be applied to the given range. Default=[58. 62]
    downsample_freq
    resample_freq
    pass_band

    Returns
    -------

    """

    # # make a df with 'stTime' column to pass to _load_eeg_timeseries
    # events = pd.DataFrame(data=np.stack([s_times, clust_nums], -1), columns=['stTime', 'cluster_num'])

    # load eeg for this channel
    eeg = _load_eeg_timeseries(df, rel_start_ms, rel_stop_ms, [channel_file],
                               buf_ms, downsample_freq, resample_freq)

    # 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()

    # mean center the data
    eeg = eeg.baseline_corrected([rel_start_ms, rel_stop_ms])

    # do band pass if desired.
    if pass_band is not None:
        eeg = band_pass_eeg(eeg, pass_band)

    return eeg
示例#2
0
 def test_ButterworthFilter(self):
     bfilter = ButterworthFilter(time_series=self.time_series,
                                 freq_range=[10., 20.],
                                 filt_type='stop',
                                 order=2)
     bfilter.filter()
     return True
    def test_butterworth(self):
        filtered0 = ButterworthFilter(self.timeseries, self.freqs).filter()
        filtered1 = ButterworthFilter(self.timeseries.transpose(),
                                      self.freqs).filter()

        xr.testing.assert_allclose(filtered0,
                                   filtered1.transpose(*filtered0.dims))
示例#4
0
    def test_ButterwothFilter(self):

        from xarray.testing import assert_equal

        b_filter = ButterworthFilter(time_series=self.base_eegs, freq_range=[58., 62.], filt_type='stop', order=4)
        base_eegs_filtered_1 = b_filter.filter()

        base_eegs_filtered_2 = self.base_eegs.filtered(freq_range=[58., 62.], filt_type='stop', order=4)


        assert_equal(base_eegs_filtered_1, base_eegs_filtered_2)

        with self.assertRaises(AssertionError):
            assert_equal(base_eegs_filtered_1, self.base_eegs)
示例#5
0
def load_eeg_from_times(df, channel_file, rel_start_ms, rel_stop_ms, buf_ms=0, noise_freq=[58., 62.],
                        downsample_freq=1000, resample_freq=None, pass_band=None):
    """

    Parameters
    ----------
    df: pandas.DataFrame
        An dataframe with a stTime column
    channel_file: str
        Path to Ncs file from which to load eeg.
    rel_start_ms: int
        Initial time (in ms), relative to the onset of each spike
    rel_stop_ms: int
        End time (in ms), relative to the onset of each spike
    buf_ms: int
        Amount of time (in ms) of buffer to add to both the beginning and end of the time interval
    noise_freq: list
        Stop filter will be applied to the given range. Default=[58. 62]
    downsample_freq
    resample_freq
    pass_band

    Returns
    -------

    """

    # # make a df with 'stTime' column to pass to _load_eeg_timeseries
    # events = pd.DataFrame(data=np.stack([s_times, clust_nums], -1), columns=['stTime', 'cluster_num'])

    # load eeg for this channel
    eeg = _load_eeg_timeseries(df, rel_start_ms, rel_stop_ms, [channel_file], buf_ms, downsample_freq, resample_freq)

    # 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()

    # mean center the data
    eeg = eeg.baseline_corrected([rel_start_ms, rel_stop_ms])

    # do band pass if desired.
    if pass_band is not None:
        eeg = band_pass_eeg(eeg, pass_band)

    return eeg
    def test_ButterwothFilter(self):

        from xarray.testing import assert_equal

        b_filter = ButterworthFilter(timeseries=self.base_eegs,
                                     freq_range=[58., 62.],
                                     filt_type='stop',
                                     order=4)
        base_eegs_filtered_1 = b_filter.filter()

        base_eegs_filtered_2 = self.base_eegs.filtered(freq_range=[58., 62.],
                                                       filt_type='stop',
                                                       order=4)

        assert_equal(base_eegs_filtered_1, base_eegs_filtered_2)

        with self.assertRaises(AssertionError):
            assert_equal(base_eegs_filtered_1, self.base_eegs)
示例#7
0
def test_resting_state_connectivity(rhino_root):
    subject = "R1354E"

    index = get_data_index("r1", rhino_root)
    sessions = index[(index.subject == subject) &
                     (index.experiment == 'FR1')].session.unique()

    all_events = []
    all_resting = []
    data = []

    for session in sessions:
        reader = CMLReader(subject, 'FR1', session, rootdir=rhino_root)
        events = get_countdown_events(reader)
        resting = countdown_to_resting(events, reader.load('sources')['sample_rate'])

        all_events.append(events)
        all_resting.append(resting)

        eeg = read_eeg_data(reader, resting, reref=False)
        data.append(eeg)

    # Verify that events match Ethan's analysis; his events are ordered in an
    # odd way, so we have to sort them to make sure they match
    ethan = np.load(resource_filename("thetamod.test.data",
                                      "R1354E_events_ethan.npy"))
    assert_equal(sorted(ethan["eegoffset"]),
                 sorted(pd.concat(all_resting).eegoffset.values))

    eegs = TimeSeries.concatenate(data)
    eegs.data = ButterworthFilter(time_series=eegs.to_ptsa(),
                                  ).filter().values
    conn = get_resting_state_connectivity(eegs.to_mne(), eegs.samplerate)

    basename = ('{subject}_baseline3trials_network_theta-alpha.npy'
                .format(subject=subject))
    filename = Path(rhino_root).joinpath('scratch', 'esolo', 'tmi_analysis',
                                         subject, basename)

    data = np.load(filename)

    np.savez("test_output.npz",
             eeg=eegs.data,
             my_conn=conn,
             ethans_conn=data,
             events=pd.concat(all_events, ignore_index=True).to_records(),
             resting=pd.concat(all_resting, ignore_index=True).to_records())

    assert_almost_equal(scipy.special.logit(conn),
                        scipy.special.logit(data), 3)
示例#8
0
def band_pass_eeg(eeg, freq_range, order=4):
    """
    Runs a butterworth band pass filter on an eeg time seriesX object.

    Parameters
    ----------
    eeg: timeseries
        A ptsa.timeseries object
    freq_range: list
        List of two floats defining the range to filter in
    order: int
        Order of butterworth filter

    Returns
    -------
    timeseries
        Filtered EEG object
    """
    return ButterworthFilter(eeg, freq_range, filt_type='pass',
                             order=order).filter()
示例#9
0
def power_spectra_from_spike_times(s_times,
                                   clust_nums,
                                   channel_file,
                                   rel_start_ms,
                                   rel_stop_ms,
                                   freqs,
                                   noise_freq=[58., 62.],
                                   downsample_freq=250,
                                   mean_over_spikes=True):
    """
    Function to compute power relative to spike times. This computes power at given frequencies for the ENTIRE session
    and then bins it relative to spike times. You WILL run out of memory if you don't let it downsample first. Default
    downsample is to 250 Hz.

    Parameters
    ----------
    s_times: np.ndarray
        Array (or list) of timestamps of when spikes occured. EEG will be loaded relative to these times.
    clust_nums:
        s_times: np.ndarray
        Array (or list) of cluster IDs, same size as s_times
    channel_file: str
        Path to Ncs file from which to load eeg.
    rel_start_ms: int
        Initial time (in ms), relative to the onset of each spike
    rel_stop_ms: int
        End time (in ms), relative to the onset of each spike
    freqs: np.ndarray
        array of frequencies at which to compute power
    noise_freq: list
        Stop filter will be applied to the given range. Default=[58. 62]
    downsample_freq: int or float
        Frequency to downsample the data. Use decimate, so we will likely not reach the exact frequency.
    mean_over_spikes: bool
        After computing the spike x frequency array, do we mean over spikes and return only the mean power spectra

    Returns
    -------
    dict
        dict of either spike x frequency array of power values or just frequencies, if mean_over_spikes. Keys are
        cluster numbers
    """

    # make a df with 'stTime' column for epoching
    events = pd.DataFrame(data=np.stack([s_times, clust_nums], -1),
                          columns=['stTime', 'cluster_num'])

    # load channel data
    signals, timestamps, sr = load_ncs(channel_file)

    # downsample the session
    if downsample_freq is not None:
        signals, timestamps, sr = _my_downsample(signals, timestamps, sr,
                                                 downsample_freq)
    else:
        print(
            'I HIGHLY recommend you downsample the data before computing power across the whole session...'
        )
        print('You will probably run out of memory.')

    # make into timeseries
    eeg = TimeSeries.create(signals,
                            samplerate=sr,
                            dims=['time'],
                            coords={'time': timestamps / 1e6})

    # 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()

    # compute power
    wave_pow = MorletWaveletFilter(eeg,
                                   freqs,
                                   output='power',
                                   width=5,
                                   cpus=12,
                                   verbose=False).filter()

    # log the power
    data = wave_pow.data
    wave_pow.data = numexpr.evaluate('log10(data)')

    # get start and stop relative to the spikes
    epochs = _compute_epochs(events, rel_start_ms, rel_stop_ms, timestamps, sr)
    bad_epochs = (np.any(epochs < 0, 1)) | (np.any(epochs > len(signals), 1))
    epochs = epochs[~bad_epochs]
    events = events[~bad_epochs].reset_index(drop=True)

    # mean over time within epochs
    spikes_x_freqs = np.stack(
        [np.mean(wave_pow.data[:, x[0]:x[1]], axis=1) for x in epochs])

    # make dict with keys being cluster numbers. Mean over spikes if desired.
    pow_spect_dict = {}
    for this_cluster in events.cluster_num.unique():
        if mean_over_spikes:
            pow_spect_dict[this_cluster] = spikes_x_freqs[
                events.cluster_num == this_cluster].mean(axis=0)
        else:
            pow_spect_dict[this_cluster] = spikes_x_freqs[events.cluster_num ==
                                                          this_cluster]

    return pow_spect_dict
    use_reref_eeg=True,
    common_root='data').read()
words = events[events.type == 'WORD']

# select all available channels
eegfile = words[0].eegfile
eegfile_reref = str.split(str(eegfile), '/')
day = eegfile_reref[-1]
eegfile_reref = '/'.join(eegfile_reref[0:-1])
channels = glob.glob(eegfile_reref + '/' + day + "*.[0-9]*")
channels = np.array([str.split(x, '.')[-1] for x in channels])
#channels = np.array(['{:03}'.format(x) for x in range(0,132)])

eeg = EEGReader(events=words, channels=channels, start_time=0.3,
                end_time=1.6).read()

b_filter = ButterworthFilter(time_series=eeg, order=4, freq_range=[58, 62])
eeg_filtered = b_filter.filter()
eeg_buffered = eeg_filtered.add_mirror_buffer(1.3)
eeg_buffered.data = np.ascontiguousarray(eeg_buffered.data)

import time
pt = time.time()
freqs = np.logspace(np.log10(3), np.log10(180), 50)
pow_ev, _ = MorletWaveletFilterCpp(time_series=eeg_buffered,
                                   freqs=freqs[0:1],
                                   output='power',
                                   cpus=20,
                                   verbose=False).filter()
run_time = time.time() - pt
示例#11
0
def load_eeg_full_timeseries(task,
                             subject,
                             session,
                             elec_scheme=None,
                             noise_freq=[58., 62.],
                             resample_freq=None,
                             pass_band=None):
    """
    Function for loading continuous EEG data from a full session, not based on event times.
    Returns a list of timeseries object.

    task: str
        The experiment name
    subject: str
        The subject number
    session: int
        The session number for this subject and task
    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). LOADING ALL ELECTRODES AND FOR AN ENTIRE SESSION AT ONCE IS NOT REALLY 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

    Returns
    -------
    list
        A TimeSeries object.
    """

    # load eeg
    eeg = CMLReader(subject=subject, experiment=task,
                    session=session).load_eeg(scheme=elec_scheme).to_ptsa()

    # 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)

    return eeg
示例#12
0
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
示例#13
0
 def test_ButterworthFilter(self):
     bfilter = ButterworthFilter(time_series = self.time_series,freq_range = [10.,20.],filt_type='stop',order=2)
     bfilter.filter()
     return True
示例#14
0
def calc_subj_pep(subj,
                  elecs=None,
                  method='bip',
                  relstart=300,
                  relstop=1301,
                  freq_specs=(2, 120, 30),
                  percentthresh=.95,
                  numcyclesthresh=3,
                  load_eeg=False,
                  save_eeg=False,
                  save_result=False,
                  plot=False,
                  kind='r1',
                  experiment='FR1',
                  eeg_path='~/',
                  result_path='~/'):
    """
    Inputs:
    subj - subject string
    elecs - list of electrode pairs (strings)
    method - bip or avg depending on referencing scheme
    freq_specs - tuple of (low_freq, high_freq, num_freqs)
        for background fitting in BOSC.

    Returns:
    pep_all - average Pepisode for all words at each frequency
    pep_rec - average Pepisode for recalled words at each frequency
    pep_nrec - average Pepisode for non-recalled words at each frequency
    subj_tscores - t-score at each frequency, comparing rec and nrec
        across events
    ** Note that tscore is not itself meaningful because events are not
        independent. Comparing these tscores across subjects, however,
        is valid.
    """

    if save_eeg and load_eeg:
        raise ('Cannot save and load eeg simultaneously.')

    print('Subject: ', subj)
    if elecs is None:
        good_subj = pd.read_pickle(
            '/home1/jrudoler/Theta_Project/hippo_subject_pairs.csv')
        elecs = good_subj[good_subj['Subject'] == subj]['hippo_pairs'].iloc[0]
    subj_pepisode = None
    subj_recalled = None
    subj_tscores = None
    if plot:
        plt.figure(figsize=(12, 6))
    lowfreq, highfreq, numfreqs = freq_specs
    print(elecs)
    for pair_str in elecs:
        chans = pair_str.split('-')
        data = cml.get_data_index(kind=kind)
        data = data[data['experiment'] == experiment]
        sessions = data[data['subject'] == subj]['session'].unique()
        pepisodes = None  # events, freqs
        recalled = None  # events, freqs
        tscore = None
        for sess in sessions:
            try:
                print('Loading session {} EEG'.format(sess))
                reader = cml.CMLReader(subject=subj,
                                       experiment=experiment,
                                       session=sess)
                all_events = reader.load('task_events')
                if not os.path.exists(eeg_path):
                    os.makedirs(eeg_path)
                if load_eeg:
                    eeg = TimeSeries.from_hdf(eeg_path + 'session_' +
                                              str(sess) + '_' + pair_str)
                    bosc = P_episode(all_events,
                                     eeg,
                                     sr=eeg.samplerate.values,
                                     lowfreq=lowfreq,
                                     highfreq=highfreq,
                                     numfreqs=numfreqs)
                elif method == 'bip':
                    pairs = reader.load("pairs")
                    # bipolar eeg
                    bip = reader.load_eeg(
                        scheme=pairs[pairs.label == pair_str])\
                        .to_ptsa().mean(['event', 'channel'])
                    bip = ButterworthFilter(bip,
                                            freq_range=[58., 62.],
                                            filt_type='stop',
                                            order=4).filter()
                    print("Applying BOSC method!")
                    if save_eeg:
                        bip.to_hdf(eeg_path + 'session_' + str(sess) + '_' +
                                   pair_str)
                    bosc = P_episode(all_events,
                                     bip,
                                     sr=bip.samplerate.values,
                                     lowfreq=lowfreq,
                                     highfreq=highfreq,
                                     numfreqs=numfreqs)

                elif method == 'avg':
                    contacts = reader.load("contacts")
                    # average eeg
                    eeg = reader.load_eeg(
                        scheme=contacts).to_ptsa().mean('event')
                    # all zeros from a broken lead leads to -inf power,
                    # which results in a LinAlg error for log-log fit
                    # TODO: verify this channel exclusion doesn't cause any
                    # problems. Maybe print a message or raise an error?
                    bad_chan_mask = ~np.all(eeg.values == 0, axis=1)
                    contacts = contacts[bad_chan_mask]
                    eeg = eeg[bad_chan_mask, :]
                    avg = (eeg[contacts.label.str.contains(chans[0]) | \
                               contacts.label.str.contains(chans[1]), :] - eeg.mean('channel')
                           ).mean('channel')
                    avg = ButterworthFilter(avg,
                                            freq_range=[58., 62.],
                                            filt_type='stop',
                                            order=4).filter()
                    if save_eeg:
                        avg.to_hdf(eeg_path + '/session_' + str(sess) + '_' +
                                   pair_str)
                    bosc = P_episode(all_events,
                                     avg,
                                     sr=avg.samplerate.values,
                                     lowfreq=lowfreq,
                                     highfreq=highfreq,
                                     numfreqs=numfreqs)

                if plot:
                    bosc.background_fit(plot_type='session')

                if pepisodes is None:
                    pepisodes = bosc.Pepisode
                    # be careful to only use events from lists that have eeg data.
                    # [np.isin(bosc.interest_events.list, self.lists)]
                    recalled = bosc.interest_events.recalled.values
                    tscore, _ = scp.ttest_ind(pepisodes[recalled],
                                              pepisodes[~recalled],
                                              axis=0)
                elif np.isnan(tscore).all():
                    tscore, _ = scp.ttest_ind(pepisodes[recalled],
                                              pepisodes[~recalled],
                                              axis=0)
                else:
                    pepisodes = np.vstack([pepisodes, bosc.Pepisode])
                    recalled = np.hstack(
                        [recalled, bosc.interest_events.recalled.values])
                    t, _ = scp.ttest_ind(pepisodes[recalled],
                                         pepisodes[~recalled],
                                         axis=0)
                    tscore = np.vstack([tscore, t])
                print("Proportion recalled:", recalled.mean())
            except IndexError:
                print('IndexError for subject {} session {}'.format(
                    subj, sess))
            except FileNotFoundError:
                print('FileNotFoundError for {} session {}'.format(subj, sess))
                continue
        if pepisodes is None:
            raise Exception('No working sessions')
        subj_pepisode = pepisodes if subj_pepisode is None else np.dstack(
            [subj_pepisode, pepisodes])
        subj_recalled = recalled if subj_recalled is None else np.vstack(
            [subj_recalled, recalled])
        subj_tscores = tscore if subj_tscores is None else np.vstack(
            [subj_tscores, tscore])
        if np.isnan(subj_tscores).all():
            raise Exception('Too many nan in T-scores. This problem can arise \
                when there are no recalled events.')
    if subj_pepisode.ndim > 2:  # if multiple electrode pairs, average over pairs
        print("Averaging over {} electrodes for subject {}".format(
            subj_pepisode.shape[2], subj))
        subj_pepisode = subj_pepisode.mean(2)
        subj_recalled = subj_recalled.mean(0)
    subj_recalled = subj_recalled.astype(bool)
    if subj_tscores.ndim > 1:
        print(len(sessions), 'sessions')
        subj_tscores = np.nanmean(subj_tscores, axis=0)

    print('{} total events: {} recalled \
    	and {} non-recalled'.format(len(subj_recalled), sum(subj_recalled),
                                 sum(~subj_recalled)))

    pep_rec = subj_pepisode[subj_recalled, :].mean(0)
    pep_nrec = subj_pepisode[~subj_recalled, :].mean(0)
    pep_all = subj_pepisode.mean(0)

    if save_result:
        if not os.path.exists(result_path):
            os.makedirs(result_path)
        np.save(result_path + '{}_all_{}'.format(subj, method), pep_all)
        np.save(result_path + '{}_rec_{}'.format(subj, method), pep_rec)
        np.save(result_path + '{}_nrec_{}'.format(subj, method), pep_nrec)
        np.save(result_path + '{}_tscore_{}'.format(subj, method),
                subj_tscores)

    return pep_all, pep_rec, pep_nrec, subj_tscores
 def test_butterworth(self, time_series):
     bfilter = ButterworthFilter(timeseries=time_series,
                                 freq_range=[10., 20.],
                                 filt_type='stop',
                                 order=2)
     bfilter.filter()
示例#16
0
def power_spectra_from_spike_times(s_times, clust_nums, channel_file, rel_start_ms, rel_stop_ms, freqs,
                                           noise_freq=[58., 62.], downsample_freq=250, mean_over_spikes=True):
    """
    Function to compute power relative to spike times. This computes power at given frequencies for the ENTIRE session
    and then bins it relative to spike times. You WILL run out of memory if you don't let it downsample first. Default
    downsample is to 250 Hz.

    Parameters
    ----------
    s_times: np.ndarray
        Array (or list) of timestamps of when spikes occured. EEG will be loaded relative to these times.
    clust_nums:
        s_times: np.ndarray
        Array (or list) of cluster IDs, same size as s_times
    channel_file: str
        Path to Ncs file from which to load eeg.
    rel_start_ms: int
        Initial time (in ms), relative to the onset of each spike
    rel_stop_ms: int
        End time (in ms), relative to the onset of each spike
    freqs: np.ndarray
        array of frequencies at which to compute power
    noise_freq: list
        Stop filter will be applied to the given range. Default=[58. 62]
    downsample_freq: int or float
        Frequency to downsample the data. Use decimate, so we will likely not reach the exact frequency.
    mean_over_spikes: bool
        After computing the spike x frequency array, do we mean over spikes and return only the mean power spectra

    Returns
    -------
    dict
        dict of either spike x frequency array of power values or just frequencies, if mean_over_spikes. Keys are
        cluster numbers
    """

    # make a df with 'stTime' column for epoching
    events = pd.DataFrame(data=np.stack([s_times, clust_nums], -1), columns=['stTime', 'cluster_num'])

    # load channel data
    signals, timestamps, sr = load_ncs(channel_file)

    # downsample the session
    if downsample_freq is not None:
        signals, timestamps, sr = _my_downsample(signals, timestamps, sr, downsample_freq)
    else:
        print('I HIGHLY recommend you downsample the data before computing power across the whole session...')
        print('You will probably run out of memory.')

    # make into timeseries
    eeg = TimeSeries.create(signals, samplerate=sr, dims=['time'], coords={'time': timestamps / 1e6})

    # 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()

    # compute power
    wave_pow = MorletWaveletFilter(eeg, freqs, output='power', width=5, cpus=12, verbose=False).filter()

    # log the power
    data = wave_pow.data
    wave_pow.data = numexpr.evaluate('log10(data)')

    # get start and stop relative to the spikes
    epochs = _compute_epochs(events, rel_start_ms, rel_stop_ms, timestamps, sr)
    bad_epochs = (np.any(epochs < 0, 1)) | (np.any(epochs > len(signals), 1))
    epochs = epochs[~bad_epochs]
    events = events[~bad_epochs].reset_index(drop=True)

    # mean over time within epochs
    spikes_x_freqs = np.stack([np.mean(wave_pow.data[:, x[0]:x[1]], axis=1) for x in epochs])

    # make dict with keys being cluster numbers. Mean over spikes if desired.
    pow_spect_dict = {}
    for this_cluster in events.cluster_num.unique():
        if mean_over_spikes:
            pow_spect_dict[this_cluster] = spikes_x_freqs[events.cluster_num == this_cluster].mean(axis=0)
        else:
            pow_spect_dict[this_cluster] = spikes_x_freqs[events.cluster_num == this_cluster]

    return pow_spect_dict
示例#17
0
def load_eeg_from_event_times(events, rel_start_ms, rel_stop_ms, channel_list, buf_ms=0, noise_freq=[58., 62.],
                              downsample_freq=1000,
                              resample_freq=None, pass_band=None, demean=False, do_average_ref=False):
    """
    Returns an EEG TimeSeries object.

    Parameters
    ----------
    events: pandas.DataFrame
        An events dataframe
    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
    channel_list: list
        list of paths to channels (ncs files)
    buf_ms: int
        Amount of time (in ms) of buffer to add to both the begining and end of the time interval
    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.
    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 event x time x channel

    """

    # eeg is a PTSA timeseries
    eeg = _load_eeg_timeseries(events, rel_start_ms, rel_stop_ms, channel_list, buf_ms, downsample_freq)

    # 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])

    # 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)

    return eeg
示例#18
0
def load_eeg_from_event_times(events,
                              rel_start_ms,
                              rel_stop_ms,
                              channel_list,
                              buf_ms=0,
                              noise_freq=[58., 62.],
                              downsample_freq=1000,
                              resample_freq=None,
                              pass_band=None,
                              demean=False,
                              do_average_ref=False):
    """
    Returns an EEG TimeSeries object.

    Parameters
    ----------
    events: pandas.DataFrame
        An events dataframe
    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
    channel_list: list
        list of paths to channels (ncs files)
    buf_ms: int
        Amount of time (in ms) of buffer to add to both the begining and end of the time interval
    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.
    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 event x time x channel

    """

    # eeg is a PTSA timeseries
    eeg = _load_eeg_timeseries(events, rel_start_ms, rel_stop_ms, channel_list,
                               buf_ms, downsample_freq)

    # 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])

    # 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)

    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