Source code for bycycle.features.cyclepoints

"""Compute cyclepoint features for individual cycles."""

import pandas as pd
import numpy as np

from bycycle.utils.checks import check_param_range
from bycycle.cyclepoints import find_extrema, find_zerox

###################################################################################################
###################################################################################################

[docs]def compute_cyclepoints(sig, fs, f_range, **find_extrema_kwargs): """Compute sample indices of cyclepoints. Parameters ---------- sig : 1d array Time series. fs : float Sampling rate, in Hz. f_range : tuple of (float, float) Frequency range, in Hz, to narrowband filter the signal. Used to find zero-crossings. find_extrema_kwargs : dict, optional, default: None Keyword arguments for the function to find peaks and troughs (:func:`~.find_extrema`) that change filter parameters or boundary. By default, the boundary is set to zero. Returns ------- df_samples : pandas.DataFrame Dataframe containing sample indices of cyclepoints. Columns (listed for peak-centered cycles): - ``peaks`` : signal indices of oscillatory peaks - ``troughs`` : signal indices of oscillatory troughs - ``rises`` : signal indices of oscillatory rising zero-crossings - ``decays`` : signal indices of oscillatory decaying zero-crossings - ``sample_peak`` : sample at which the peak occurs - ``sample_zerox_decay`` : sample of the decaying zero-crossing - ``sample_zerox_rise`` : sample of the rising zero-crossing - ``sample_last_trough`` : sample of the last trough - ``sample_next_trough`` : sample of the next trough Examples -------- Compute the signal indices of cyclepoints: >>> from neurodsp.sim import sim_bursty_oscillation >>> fs = 500 >>> sig = sim_bursty_oscillation(10, fs, freq=10) >>> df_samples = compute_cyclepoints(sig, fs, f_range=(8, 12)) """ # Ensure arguments are within valid range check_param_range(fs, 'fs', (0, np.inf)) # Find extrema and zero-crossings locations in the signal peaks, troughs = find_extrema(sig, fs, f_range, **find_extrema_kwargs) rises, decays = find_zerox(sig, peaks, troughs) # For each cycle, identify the sample of each extrema and zero-crossing samples = {} samples['sample_peak'] = peaks[1:] samples['sample_last_zerox_decay'] = decays[:-1] samples['sample_zerox_decay'] = decays[1:] samples['sample_zerox_rise'] = rises samples['sample_last_trough'] = troughs[:-1] samples['sample_next_trough'] = troughs[1:] df_samples = pd.DataFrame.from_dict(samples) return df_samples