def average_power_distribution(ridge_results, exclude_coi=False):
    '''
    Compute the power distribution of an ensemble
    of (ridge-)analyzed signals.

    Central measure is the time-averaged ridge-power of individual
    signals.

    Parameters
    ----------

    ridge_results : sequence (or iterable) of DataFrames
                   holding the ridge data for the individual signals
                   check pyboat.core.eval_ridge for details
                   about the DataFrame structure


    exclude_coi :  bool, if True only average the ridge outside of the COI,
                  for short noisy trajectories there might be no such points!
    '''

    powers = []

    # collect the time-averaged powers
    for rd in ridge_results:

        if exclude_coi:
            # take only ridge power outside of COI
            i_left, i_right = find_COI_crossing(rd)
            mpower = (rd.power[i_left:i_right]).mean()
        else:
            mpower = rd.power.mean()
        powers.append(mpower)

    return np.array(powers)
Beispiel #2
0
def plot_readout(ridge_data, time_unit="a.u.", draw_coi=False, fig=None):
    """
    ridge_data from core.eval_ridge(...)
    creates four axes: period, phase, amplitude and power
    """

    # restore the original complete time vector
    tvec = np.arange(ridge_data.Nt) * ridge_data.dt

    i_left, i_right = find_COI_crossing(ridge_data)

    if fig is None:
        fig = ppl.figure(figsize=(7, 4.8))

    periods = ridge_data["periods"]
    phases = ridge_data["phase"]
    powers = ridge_data["power"]
    amplitudes = ridge_data["amplitude"]
    ridge_t = ridge_data["time"]  # indexable

    # check for discontinuous ridge
    if np.all(np.diff(ridge_t, n=2) < 1e-12):
        # draw continuous lines
        lstyle = '-'
        mstyle = ''
    else:
        lstyle = ''
        mstyle = 'o'

    fig.subplots_adjust(wspace=0.3,
                        left=0.11,
                        top=0.98,
                        right=0.97,
                        bottom=0.14)

    axs = fig.subplots(2, 2, sharex=True)

    for ax in axs.flatten():
        ax.spines['top'].set_visible(False)
        ax.spines['right'].set_visible(False)

    ax1 = axs[0, 0]
    ax2 = axs[0, 1]
    ax3 = axs[1, 0]
    ax4 = axs[1, 1]

    # periods
    ax1.plot(ridge_t.loc[i_left:i_right],
             periods.loc[i_left:i_right],
             color=PERIOD_COLOR,
             alpha=0.8,
             lw=2.5,
             ls=lstyle,
             marker=mstyle,
             ms=1.5)
    # inside COI
    ax1.plot(ridge_t.loc[:i_left],
             periods.loc[:i_left],
             '--',
             color=PERIOD_COLOR,
             alpha=0.8,
             ms=2.5)
    ax1.plot(ridge_t.loc[i_right:],
             periods.loc[i_right:],
             '--',
             color=PERIOD_COLOR,
             alpha=0.8,
             ms=2.5)

    ax1.set_ylabel(f"Period ({time_unit})", fontsize=label_size)
    ax1.grid(True, axis="y")
    yl = ax1.get_ylim()
    ax1.set_ylim((max([0, 0.75 * yl[0]]), 1.25 * yl[1]))

    # only now draw the COI?
    if draw_coi:
        draw_COI(ax1, tvec)

    ax1.tick_params(axis="both", labelsize=tick_label_size)

    # ax1.set_ylim( (120,160) )

    # phases
    ax2.plot(ridge_t.loc[i_left:i_right],
             phases.loc[i_left:i_right],
             "-",
             c=PHASE_COLOR,
             alpha=0.8,
             ls=lstyle,
             marker=mstyle,
             ms=1.5)

    # inside COI
    ax2.plot(ridge_t.loc[:i_left],
             phases.loc[:i_left],
             '-.',
             color=PHASE_COLOR,
             alpha=0.5,
             ms=2.5)
    ax2.plot(ridge_t.loc[i_right:],
             phases.loc[i_right:],
             '-.',
             color=PHASE_COLOR,
             alpha=0.5,
             ms=2.5)

    ax2.set_ylabel("Phase (rad)", fontsize=label_size, labelpad=0.5)
    ax2.set_yticks((0, pi, 2 * pi))
    ax2.set_yticklabels(("$0$", "$\pi$", "$2\pi$"))
    ax2.tick_params(axis="both", labelsize=tick_label_size)

    # amplitudes
    ax3.plot(ridge_t.loc[i_left:i_right],
             amplitudes.loc[i_left:i_right],
             c=AMPLITUDE_COLOR,
             lw=2.5,
             alpha=0.9,
             ls=lstyle,
             marker=mstyle,
             ms=1.5)

    # inside COI
    ax3.plot(ridge_t.loc[:i_left],
             amplitudes.loc[:i_left],
             '--',
             color=AMPLITUDE_COLOR,
             alpha=0.6,
             ms=2.5)
    ax3.plot(ridge_t.loc[i_right:],
             amplitudes.loc[i_right:],
             '--',
             color=AMPLITUDE_COLOR,
             alpha=0.6,
             ms=2.5)

    ax3.set_ylim((0, 1.1 * amplitudes.max()))
    ax3.ticklabel_format(style="sci", axis="y", scilimits=(0, 0))
    ax3.yaxis.offsetText.set_fontsize(tick_label_size)
    ax3.set_ylabel("Amplitude (a.u.)", fontsize=label_size)
    ax3.set_xlabel("Time (" + time_unit + ")", fontsize=label_size)
    ax3.tick_params(axis="both", labelsize=tick_label_size)

    # powers
    ax4.plot(ridge_t.loc[i_left:i_right],
             powers.loc[i_left:i_right],
             lw=2.5,
             alpha=0.8,
             color=POWER_COLOR,
             ls=lstyle,
             marker=mstyle,
             ms=1.5)

    # inside COI
    ax4.plot(ridge_t.loc[:i_left],
             powers.loc[:i_left],
             '--',
             color=POWER_COLOR,
             alpha=0.6,
             ms=2.5)
    ax4.plot(ridge_t.loc[i_right:],
             powers.loc[i_right:],
             '--',
             color=POWER_COLOR,
             alpha=0.6,
             ms=2.5)

    ax4.set_ylim((0, 1.1 * powers.max()))
    ax4.set_ylabel("Power (wnp)", fontsize=label_size)
    ax4.set_xlabel("Time (" + time_unit + ")", fontsize=label_size)
    ax4.tick_params(axis="both", labelsize=tick_label_size)
Beispiel #3
0
def average_power_distribution(ridge_results,
                               signal_ids=None,
                               exclude_coi=False):
    '''
    Compute the power distribution of an ensemble
    of (ridge-)analyzed signals.

    Central measure is the time-averaged ridge-power of individual
    signals.

    Parameters
    ----------

    ridge_results : sequence of DataFrames,
                   holds the ridge data for the individual signals.
                   Check pyboat.core.eval_ridge for details
                   about the DataFrame structure
    
    signal_ids : sequence, optional 
                 labels of the analyzed signals, if not given
                 a numeric sequence of len(ridge_results)
                 will be used as labels

    exclude_coi :  bool, if True only average the ridge outside of the COI,
                  for short noisy trajectories there might be no such points!

    Returns
    -------
    power_series : pandas Series with the signal_ids as index 
                   and averaged powers as values
    
    '''

    powers = []
    ids = []

    if signal_ids is None:
        signal_ids = np.arange(len(ridge_results))

    assert len(signal_ids) == len(ridge_results)

    # collect the time-averaged powers
    for rd, _id in zip(ridge_results, signal_ids):

        if exclude_coi:
            # take only ridge power outside of COI
            i_left, i_right = find_COI_crossing(rd)
            mpower = (rd.power[i_left:i_right]).mean()
        else:
            mpower = rd.power.mean()

        # can happen if ridge exclusively inside COI
        if not np.isnan(mpower):
            powers.append(mpower)
            ids.append(_id)

    powers_series = pd.Series(index=ids, data=powers)

    # sort by power, descending
    powers_series.sort_values(ascending=False, inplace=True)

    return powers_series