예제 #1
0
def compute_period_consistency(df_shape_features, direction='both'):
    """Compute the period consistency of each cycle.

    Parameters
    ----------
    df_shape_features : pandas.DataFrame
        Shape features for each cycle, determined using :func:`~.compute_shape_features`.
    direction : {'both', 'next', 'last'}
        The direction to compute consistency. Defaults to bi-directional.

    Returns
    -------
    period_consistency : 1d array
        The period consistency of each cycle.

    Examples
    --------
    Compute period consistency:

    >>> from bycycle.features import compute_shape_features
    >>> from neurodsp.sim import sim_bursty_oscillation
    >>> fs = 500
    >>> sig = sim_bursty_oscillation(10, fs, freq=10)
    >>> df_shapes = compute_shape_features(sig, fs, f_range=(8, 12))
    >>> period_consistency = compute_period_consistency(df_shapes)
    """

    # Check that param validity
    check_param_options(direction, 'direction', ['both', 'next', 'last'])

    # Compute period consistency
    cycles = len(df_shape_features)
    period_consistency = np.ones(cycles) * np.nan
    periods = df_shape_features['period'].values

    for cyc in range(1, cycles - 1):

        consist_last = np.min([periods[cyc], periods[cyc-1]]) / \
            np.max([periods[cyc], periods[cyc-1]])
        consist_next = np.min([periods[cyc+1], periods[cyc]]) / \
            np.max([periods[cyc+1], periods[cyc]])

        if direction == 'next':
            period_consistency[cyc] = consist_next
        elif direction == 'last':
            period_consistency[cyc] = consist_last
        elif direction == 'both':
            period_consistency[cyc] = np.min([consist_next, consist_last])

    return period_consistency
예제 #2
0
파일: utils.py 프로젝트: iea3/bycycle
def recompute_edge(df_features, cyc_idx, direction):
    """Recompute consistency features at the edge of a cycle.

    Parameters
    ----------
    df_features : pandas.DataFrame
        A dataframe containing shape and burst features for each cycle.
    cyc_idx : int
        The dataframe index of the edge.
    direction : {'both', 'next', 'last'}
        The direction to compute consistency.

    Returns
    -------
    df_features : pandas.DataFrame
        A dataframe with updated consistency features.
    """

    # Check that param validity
    check_param_options(direction, 'direction', ['both', 'next', 'last'])

    # Prevent circular imports between burst.utils and burst.cycle
    from bycycle.features.burst import compute_amp_consistency, compute_period_consistency

    # Slice edges rows and recompute burst features
    lower = max(cyc_idx - 1, 0)
    upper = min(cyc_idx + 2, len(df_features))
    edge_range = range(lower, upper)

    edge = df_features.iloc[edge_range].copy()

    # Update dataframe with recomputed consistency features
    df_features['amp_consistency'][cyc_idx] = \
        compute_amp_consistency(edge, direction=direction)[1]

    df_features['period_consistency'][cyc_idx] = \
        compute_period_consistency(edge, direction=direction)[1]

    return df_features
예제 #3
0
def compute_amp_consistency(df_shape_features, direction='both'):
    """Compute amplitude consistency for each cycle.

    Parameters
    ----------
    df_shape_features : pandas.DataFrame
        Shape features for each cycle, determined using :func:`~.compute_shape_features`.
    direction : {'both', 'next', 'last'}
        The direction to compute consistency. Defaults to bi-directional.

    Returns
    -------
    amp_consist : 1d array
        The amplitude consistency of each cycle.

    Examples
    --------
    Compute amplitude consistency:

    >>> from bycycle.features import compute_shape_features
    >>> from neurodsp.sim import sim_bursty_oscillation
    >>> fs = 500
    >>> sig = sim_bursty_oscillation(10, fs, freq=10)
    >>> df_shapes = compute_shape_features(sig, fs, f_range=(8, 12))
    >>> amp_consistency = compute_amp_consistency(df_shapes)
    """

    # Check that param validity
    check_param_options(direction, 'direction', ['both', 'next', 'last'])

    # Compute amplitude consistency
    cycles = len(df_shape_features)
    amp_consistency = np.ones(cycles) * np.nan
    rises = df_shape_features['volt_rise'].values
    decays = df_shape_features['volt_decay'].values

    for cyc in range(1, cycles - 1):

        # Division by zero will return np.nan, suppress warning.
        with np.errstate(invalid='ignore', divide='ignore'):

            consist_current = np.min([rises[cyc], decays[cyc]]) / np.max(
                [rises[cyc], decays[cyc]])

            if 'sample_peak' in df_shape_features.columns:

                consist_last = np.min([rises[cyc], decays[cyc-1]]) / \
                    np.max([rises[cyc], decays[cyc-1]])

                consist_next = np.min([rises[cyc+1], decays[cyc]]) / \
                    np.max([rises[cyc+1], decays[cyc]])

            else:

                consist_last = np.min([rises[cyc-1], decays[cyc]]) / \
                    np.max([rises[cyc-1], decays[cyc]])

                consist_next = np.min([rises[cyc], decays[cyc+1]]) / \
                    np.max([rises[cyc], decays[cyc+1]])

            if np.isnan([consist_current, consist_next, consist_last]).all():
                amp_consistency[cyc] = np.nan
            elif direction == 'next':
                amp_consistency[cyc] = np.nanmin(
                    [consist_current, consist_next])
            elif direction == 'last':
                amp_consistency[cyc] = np.nanmin(
                    [consist_current, consist_last])
            elif direction == 'both':
                amp_consistency[cyc] = np.nanmin(
                    [consist_current, consist_next, consist_last])

    # Prevent negative consistency
    if (amp_consistency < 0).any():

        amp_consistency[np.where(amp_consistency < 0)[0]] = 0

    return amp_consistency