Source code for osl_dynamics.data.task
"""Functions to handle task data."""
import numpy as np
[docs]
def epoch(
data: np.ndarray, time_index: np.ndarray, pre: int, post: int, pad: bool = False
) -> np.ndarray:
"""Transform (time, channels) data to (epochs, time, channels) data.
Given a series of triggers given by :code:`time_index`, spit a continuous
dataset into epochs. :code:`time_index` should be a sequence of integers
representing the triggers of the epochs. :code:`pre` and :code:`post`
specify the window around each trigger event.
Parameters
----------
data : np.ndarray
A (time, channels) dataset to be epoched.
time_index : np.ndarray
The integer indices of the start of each epoch.
pre : int
The integer number of samples to include before the trigger.
post : int
The integer number of samples to include after the trigger.
pad : bool, optional
Pad with NaNs so that initial epochs will always been included.
Returns
-------
epoched : np.ndarray
An (epochs, time, channels) dataset.
"""
if pad:
# Pad before and after the data with zeros
data = np.pad(data, ((pre, post), (0, 0)), constant_values=np.nan)
time_index = time_index + pre
else:
# Only keep epochs we have all time points for
keep = np.logical_and(
time_index - pre > 0,
time_index + post < data.shape[0],
)
time_index = time_index[keep]
starts, stops = time_index - pre, time_index + post
epoched = np.array([data[start:stop] for start, stop in zip(starts, stops)])
return epoched
[docs]
def epoch_mean(
data: np.ndarray, time_index: np.ndarray, pre: int, post: int, pad: bool = False
) -> np.ndarray:
"""Get the mean over epochs of a (time, channels) dataset.
Calls :code:`epoch_mean`, and takes a mean over epochs, returning data
with dimensions (time, channels) in which the time is the length of the
epoch window.
Parameters
----------
data : np.ndarray
A (time, channels) dataset to be epoched.
time_index : np.ndarray
The integer indices of the start of each epoch.
pre : int
The integer number of samples to include before the trigger.
post : int
The integer number of samples to include after the trigger.
pad : bool, optional
Pad with NaNs so that initial epochs will always been included.
Returns
-------
epoch_mean : np.ndarray
(time, channels) data meant over epochs.
"""
return np.nanmean(epoch(data, time_index, pre, post, pad=pad), axis=0)