コード例 #1
0
def plot_peak_params(peaks,
                     freq_range=None,
                     colors=None,
                     labels=None,
                     ax=None,
                     plot_style=style_param_plot,
                     **plot_kwargs):
    """Plot peak parameters as dots representing center frequency, power and bandwidth.

    Parameters
    ----------
    peaks : 2d array or list of 2d array
        Peak data. Each row is a peak, as [CF, PW, BW].
    freq_range : list of [float, float] , optional
        The frequency range to plot the peak parameters across, as [f_min, f_max].
    colors : str or list of str, optional
        Color(s) to plot data.
    labels : list of str, optional
        Label(s) for plotted data, to be added in a legend.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    plot_style : callable, optional, default: style_param_plot
        A function to call to apply styling & aesthetics to the plot.
    **plot_kwargs
        Keyword arguments to pass into the plot call.
    """

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['params']))

    # If there is a list, use recurse function to loop across arrays of data and plot them
    if isinstance(peaks, list):
        recursive_plot(peaks,
                       plot_peak_params,
                       ax,
                       colors=colors,
                       labels=labels,
                       plot_style=plot_style,
                       **plot_kwargs)

    # Otherwise, plot the array of data
    else:

        # Unpack data: CF as x; PW as y; BW as size
        xs, ys = peaks[:, 0], peaks[:, 1]
        sizes = peaks[:, 2] * plot_kwargs.pop('s', 150)

        # Create the plot
        plot_kwargs = check_plot_kwargs(plot_kwargs, {'alpha': 0.7})
        ax.scatter(xs, ys, sizes, c=colors, label=labels, **plot_kwargs)

    # Add axis labels
    ax.set_xlabel('Center Frequency')
    ax.set_ylabel('Power')

    # Set plot limits
    if freq_range:
        ax.set_xlim(freq_range)
    ax.set_ylim([0, ax.get_ylim()[1]])

    check_n_style(plot_style, ax)
コード例 #2
0
ファイル: spectra.py プロジェクト: parhalje/fooof
def plot_spectra(freqs,
                 power_spectra,
                 log_freqs=False,
                 log_powers=False,
                 colors=None,
                 labels=None,
                 ax=None,
                 **plot_kwargs):
    """Plot one or multiple power spectra.

    Parameters
    ----------
    freqs : 1d or 2d array or list of 1d array
        Frequency values, to be plotted on the x-axis.
    power_spectra : 1d or 2d array or list of 1d array
        Power values, to be plotted on the y-axis.
    log_freqs : bool, optional, default: False
        Whether to plot the frequency axis in log spacing.
    log_powers : bool, optional, default: False
        Whether to plot the power axis in log spacing.
    colors : list of str, optional, default: None
        Line colors of the spectra.
    labels : list of str, optional, default: None
        Legend labels for the spectra.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    **plot_kwargs
        Keyword arguments to pass into the ``style_plot``.
    """

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['spectral']))

    # Create the plot
    plot_kwargs = check_plot_kwargs(plot_kwargs, {'linewidth': 2.0})

    # Make inputs iterable if need to be passed multiple times to plot each spectrum
    plt_powers = np.reshape(power_spectra, (1, -1)) if np.ndim(power_spectra) == 1 else \
        power_spectra
    plt_freqs = repeat(freqs) if isinstance(
        freqs, np.ndarray) and freqs.ndim == 1 else freqs

    # Set labels
    labels = plot_kwargs.pop('label') if 'label' in plot_kwargs.keys(
    ) and labels is None else labels
    labels = repeat(labels) if not isinstance(labels, list) else cycle(labels)
    colors = repeat(colors) if not isinstance(colors, list) else cycle(colors)

    # Plot
    for freqs, powers, color, label in zip(plt_freqs, plt_powers, colors,
                                           labels):

        # Set plot data, logging if requested, and collect color, if absent
        freqs = np.log10(freqs) if log_freqs else freqs
        powers = np.log10(powers) if log_powers else powers
        if color:
            plot_kwargs['color'] = color

        ax.plot(freqs, powers, label=label, **plot_kwargs)

    style_spectrum_plot(ax, log_freqs, log_powers)
コード例 #3
0
def plot_scatter_2(data_0, label_0, data_1, label_1, title=None, ax=None):
    """Plot a scatter plot, with two y-axes.

    Parameters
    ----------
    data_0 : 1d array
        Data to plot on the first axis.
    label_0 : str
        Label for the data on the first axis, to be set as the axis label.
    data_1 : 1d array
        Data to plot on the second axis.
    label_0 : str
        Label for the data on the second axis, to be set as the axis label.
    title : str, optional
        Title for the plot.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.

    Notes
    -----
    Data is jittered slightly, for visualization purposes (deviations on x-axis are meaningless).
    """

    ax = check_ax(ax)
    ax1 = ax.twinx()

    plot_scatter_1(data_0, label_0, ax=ax)
    plot_scatter_1(data_1, label_1, x_val=1, ax=ax1)

    if title:
        ax.set_title(title, fontsize=20)

    ax.set(xlim=[-0.5, 1.5], xticks=[0, 1], xticklabels=[label_0, label_1])
    ax.tick_params(axis='x', labelsize=16)
コード例 #4
0
def plot_hist(data, label, title=None, n_bins=25, x_lims=None, ax=None):
    """Plot a histogram.

    Parameters
    ----------
    data : 1d array
        Data to plot.
    label : str
        Label for the data, to be set as the x-axis label.
    title : str, optional
        Title for the plot.
    n_bins : int, optional, default: 25
        Number of bins to use for the histogram.
    x_lims : list of float, optional
        Limits for the x-axis of the plot.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    """

    ax = check_ax(ax)

    ax.hist(data[~np.isnan(data)], n_bins, range=x_lims, alpha=0.8)

    ax.set_xlabel(label, fontsize=16)
    ax.set_ylabel('Count', fontsize=16)

    if x_lims:
        ax.set_xlim(x_lims)

    if title:
        ax.set_title(title, fontsize=20)

    ax.tick_params(axis='both', labelsize=12)
コード例 #5
0
ファイル: spectra.py プロジェクト: vlitvak/fooof
def plot_spectrum_shading(freqs,
                          power_spectrum,
                          shades,
                          add_center=False,
                          ax=None,
                          plot_style=style_spectrum_plot,
                          **kwargs):
    """Plot a power spectrum with a shaded frequency region (or regions).

    Parameters
    ----------
    freqs : 1d array
        X-axis data, frequency values.
    power_spectrum : 1d array
        Y-axis data, power values for spectrum to plot.
    shades : list of [float, float] or list of list of [float, float]
        Shaded region(s) to add to plot, defined as [lower_bound, upper_bound].
    add_center : boolean, optional, default: False
        Whether to add a line at the center point of the shaded regions.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the plot.
    **kwargs
        Keyword arguments to be passed to the plot call.
    """

    ax = check_ax(ax)
    plot_spectrum(freqs, power_spectrum, plot_style=None, ax=ax, **kwargs)
    add_shades(ax, shades, add_center, kwargs.get('log_freqs', False))
    check_n_style(plot_style, ax, kwargs.get('log_freqs', False),
                  kwargs.get('log_powers', False))
コード例 #6
0
def plot_peak_iter(fm):
    """Plots a series of plots illustrating the peak search from a flattened spectrum.

    Parameters
    ----------
    fm : FOOOF() object
        FOOOF object, with model fit, data and settings available.
    """

    flatspec = fm._spectrum_flat
    n_gauss = fm._gaussian_params.shape[0]
    ylims = [
        min(flatspec) - 0.1 * np.abs(min(flatspec)),
        max(flatspec) + 0.1 * max(flatspec)
    ]

    for ind in range(n_gauss + 1):

        # Note: this forces to create a new plotting axes per iteration
        ax = check_ax(None)

        plot_spectrum(fm.freqs,
                      flatspec,
                      linewidth=2.0,
                      label='Flattened Spectrum',
                      ax=ax)
        plot_spectrum(fm.freqs,
                      [fm.peak_threshold * np.std(flatspec)] * len(fm.freqs),
                      color='orange',
                      linestyle='dashed',
                      label='Relative Threshold',
                      ax=ax)
        plot_spectrum(fm.freqs, [fm.min_peak_height] * len(fm.freqs),
                      color='red',
                      linestyle='dashed',
                      label='Absolute Threshold',
                      ax=ax)

        maxi = np.argmax(flatspec)
        ax.plot(fm.freqs[maxi], flatspec[maxi], '.', markersize=24)

        ax.set_ylim(ylims)
        ax.set_title('Iteration #' + str(ind + 1), fontsize=16)

        if ind < n_gauss:

            gauss = gaussian_function(fm.freqs, *fm._gaussian_params[ind, :])
            plot_spectrum(fm.freqs,
                          gauss,
                          label='Gaussian Fit',
                          linestyle=':',
                          linewidth=2.0,
                          ax=ax)

            flatspec = flatspec - gauss
コード例 #7
0
def plot_spectral_error(freqs,
                        error,
                        shade=None,
                        log_freqs=False,
                        ax=None,
                        plot_style=style_spectrum_plot,
                        **plot_kwargs):
    """Plot frequency by frequency error values.

    Parameters
    ----------
    freqs : 1d array
        Frequency values, to be plotted on the x-axis.
    error : 1d array
        Calculated error values or mean error values across frequencies, to plot on the y-axis.
    shade : 1d array, optional
        Values to shade in around the plotted error.
        This could be, for example, the standard deviation of the errors.
    log_freqs : bool, optional, default: False
        Whether to plot the frequency axis in log spacing.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the plot.
    **plot_kwargs
        Keyword arguments to be passed to `plot_spectra` or to the plot call.
    """

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['spectral']))

    plt_freqs = np.log10(freqs) if log_freqs else freqs

    plot_spectrum(plt_freqs,
                  error,
                  plot_style=None,
                  ax=ax,
                  linewidth=3,
                  **plot_kwargs)

    if np.any(shade):
        ax.fill_between(plt_freqs, error - shade, error + shade, alpha=0.25)

    ymin, ymax = ax.get_ylim()
    if ymin < 0:
        ax.set_ylim([0, ymax])
    ax.set_xlim(plt_freqs.min(), plt_freqs.max())

    check_n_style(plot_style, ax, log_freqs, True)
    ax.set_ylabel('Absolute Error')
コード例 #8
0
def plot_aperiodic_params(aps,
                          colors=None,
                          labels=None,
                          ax=None,
                          plot_style=style_param_plot,
                          **plot_kwargs):
    """Plot aperiodic parameters as dots representing offset and exponent value.

    Parameters
    ----------
    aps : 2d array or list of 2d array
        Aperiodic parameters. Each row is a parameter set, as [Off, Exp] or [Off, Knee, Exp].
    colors : str or list of str, optional
        Color(s) to plot data.
    labels : list of str, optional
        Label(s) for plotted data, to be added in a legend.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    plot_style : callable, optional, default: style_param_plot
        A function to call to apply styling & aesthetics to the plot.
    **plot_kwargs
        Keyword arguments to pass into the plot call.
    """

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['params']))

    if isinstance(aps, list):
        recursive_plot(aps,
                       plot_aperiodic_params,
                       ax,
                       colors=colors,
                       labels=labels,
                       plot_style=plot_style,
                       **plot_kwargs)

    else:

        # Unpack data: offset as x; exponent as y
        xs, ys = aps[:, 0], aps[:, -1]
        sizes = plot_kwargs.pop('s', 150)

        plot_kwargs = check_plot_kwargs(plot_kwargs, {'alpha': 0.7})
        ax.scatter(xs, ys, sizes, c=colors, label=labels, **plot_kwargs)

    # Add axis labels
    ax.set_xlabel('Offset')
    ax.set_ylabel('Exponent')

    check_n_style(plot_style, ax)
コード例 #9
0
def plot_spectra(freqs,
                 power_spectra,
                 log_freqs=False,
                 log_powers=False,
                 labels=None,
                 ax=None,
                 plot_style=style_spectrum_plot,
                 **plot_kwargs):
    """Plot multiple power spectra on the same plot.

    Parameters
    ----------
    freqs : 2d array or 1d array or list of 1d array
        Frequency values, to be plotted on the x-axis.
    power_spectra : 2d array or list of 1d array
        Power values, to be plotted on the y-axis.
    log_freqs : bool, optional, default: False
        Whether to plot the frequency axis in log spacing.
    log_powers : bool, optional, default: False
        Whether to plot the power axis in log spacing.
    labels : list of str, optional
        Legend labels, for each power spectrum.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the plot.
    **plot_kwargs
        Keyword arguments to be passed to the plot call.
    """

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['spectral']))

    # Make inputs iterable if need to be passed multiple times to plot each spectrum
    freqs = repeat(freqs) if isinstance(
        freqs, np.ndarray) and freqs.ndim == 1 else freqs
    labels = repeat(labels) if not isinstance(labels, list) else labels

    for freq, power_spectrum, label in zip(freqs, power_spectra, labels):
        plot_spectrum(freq,
                      power_spectrum,
                      log_freqs,
                      log_powers,
                      label=label,
                      plot_style=None,
                      ax=ax,
                      **plot_kwargs)

    check_n_style(plot_style, ax, log_freqs, log_powers)
コード例 #10
0
def plot_spectra_shading(freqs,
                         power_spectra,
                         shades,
                         shade_colors='r',
                         add_center=False,
                         ax=None,
                         plot_style=style_spectrum_plot,
                         **plot_kwargs):
    """Plot a group of power spectra with a shaded frequency region (or regions).

    Parameters
    ----------
    freqs : 2d array or 1d array or list of 1d array
        Frequency values, to be plotted on the x-axis.
    power_spectra : 2d array or list of 1d array
        Power values, to be plotted on the y-axis.
    shades : list of [float, float] or list of list of [float, float]
        Shaded region(s) to add to plot, defined as [lower_bound, upper_bound].
    shade_colors : str or list of string
        Color(s) to plot shades.
    add_center : bool, optional, default: False
        Whether to add a line at the center point of the shaded regions.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the plot.
    **plot_kwargs
        Keyword arguments to be passed to `plot_spectra` or to the plot call.

    Notes
    -----
    Parameters for `plot_spectra` can also be passed into this function as keyword arguments.

    This includes `log_freqs`, `log_powers` & `labels`. See `plot_spectra` for usage details.
    """

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['spectral']))

    plot_spectra(freqs, power_spectra, ax=ax, plot_style=None, **plot_kwargs)

    add_shades(ax, shades, shade_colors, add_center,
               plot_kwargs.get('log_freqs', False))

    check_n_style(plot_style, ax, plot_kwargs.get('log_freqs', False),
                  plot_kwargs.get('log_powers', False))
コード例 #11
0
def plot_spectra(freqs,
                 power_spectra,
                 log_freqs=False,
                 log_powers=False,
                 labels=None,
                 ax=None,
                 plot_style=style_spectrum_plot,
                 **kwargs):
    """Plot multiple power spectra on the same plot.

    Parameters
    ----------
    freqs : 2d array or 1d array or list of 1d array
        X-axis data, frequency values.
    power_spectra : 2d array or list of 1d array
        Y-axis data, power values for spectra to plot.
    log_freqs : boolean, optional, default: False
        Whether or not to take the log of the frequency axis before plotting.
    log_powers : boolean, optional, default: False
        Whether or not to take the log of the power axis before plotting.
    labels : list of str, optional
        Legend labels, for each power spectrum.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the plot.
    **kwargs
        Keyword arguments to be passed to the plot call.
    """

    freqs = repeat(freqs) if isinstance(
        freqs, np.ndarray) and freqs.ndim == 1 else freqs
    labels = repeat(labels) if not isinstance(labels, list) else labels

    ax = check_ax(ax)
    for freq, power_spectrum, label in zip(freqs, power_spectra, labels):
        plot_spectrum(freq,
                      power_spectrum,
                      log_freqs,
                      log_powers,
                      label=label,
                      plot_style=None,
                      ax=ax,
                      **kwargs)
    check_n_style(plot_style, ax, log_freqs, log_powers)
コード例 #12
0
def plot_spectrum_shading(freqs, power_spectrum, shades, add_center=False, ax=None, **kwargs):
    """Plot a power spectrum with a shaded frequency region (or regions).

    Parameters
    ----------
    freqs : 1d array
        X-axis data, frequency values.
    power_spectrum : list of 1d array
        Y-axis data, power spectrum power values for spectrum to plot.
    shades : list of [float, float] or list of list of [float, float]
        Shaded region(s) to add to plot, defined as [lower_bound, upper_bound].
    add_center : boolean
        Whether to add a line at the center point of the shaded regions.
    """

    ax = check_ax(ax)
    plot_spectrum(freqs, power_spectrum, ax=ax, **kwargs)
    add_shades(ax, shades, add_center, kwargs.get('log_freqs', False))
コード例 #13
0
def plot_fm(fm, plt_log=False, save_fig=False, file_name='FOOOF_fit', file_path=None, ax=None):
    """Plot the original power spectrum, and full model fit from FOOOF object.

    Parameters
    ----------
    fm : FOOOF() object
        FOOOF object, containing a power spectrum and (optionally) results from fitting.
    plt_log : boolean, optional
        Whether or not to plot the frequency axis in log space. default: False
    save_fig : boolean, optional
        Whether to save out a copy of the plot. default : False
    file_name : str, optional
        Name to give the saved out file.
    file_path : str, optional
        Path to directory in which to save. If None, saves to current directory.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    """

    if not np.all(fm.freqs):
        raise RuntimeError('No data available to plot - can not proceed.')

    ax = check_ax(ax)

    # Log Plot Settings - note that power values in FOOOF objects are already logged
    log_freqs = plt_log
    log_powers = False

    # Create the plot, adding data as is available
    if np.any(fm.power_spectrum):
        plot_spectrum(fm.freqs, fm.power_spectrum, log_freqs, log_powers, ax,
                      color='k', linewidth=1.25, label='Original Spectrum')
    if np.any(fm.fooofed_spectrum_):
        plot_spectrum(fm.freqs, fm.fooofed_spectrum_, log_freqs, log_powers, ax,
                      color='r', linewidth=3.0, alpha=0.5, label='Full Model Fit')
        plot_spectrum(fm.freqs, fm._ap_fit, log_freqs, log_powers, ax,
                      color='b', linestyle='dashed', linewidth=3.0,
                      alpha=0.5, label='Aperiodic Fit')

    # Save out figure, if requested
    if save_fig:
        plt.savefig(fpath(file_path, fname(file_name, 'png')))
コード例 #14
0
def plot_scatter_1(data, label=None, title=None, x_val=0, ax=None):
    """Plot a scatter plot, with a single y-axis.

    Parameters
    ----------
    data : 1d array
        Data to plot.
    label : str, optional
        Label for the data, to be set as the y-axis label.
    title : str, optional
        Title for the plot.
    x_val : int, optional, default: 0
        Position along the x-axis to plot set of data.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.

    Notes
    -----
    Data is jittered slightly, for visualization purposes (deviations on x-axis are meaningless).
    """

    ax = check_ax(ax)

    # Create x-axis data, with small jitter for visualization purposes
    x_data = np.ones_like(data) * x_val + np.random.normal(
        0, 0.025, data.shape)

    ax.scatter(x_data, data, s=36, alpha=set_alpha(len(data)))

    if label:
        ax.set_ylabel(label, fontsize=16)
        ax.set(xticks=[x_val], xticklabels=[label])

    if title:
        ax.set_title(title, fontsize=20)

    ax.tick_params(axis='x', labelsize=16)
    ax.tick_params(axis='y', labelsize=12)

    ax.set_xlim([-0.5, 0.5])
コード例 #15
0
def plot_spectra(freqs, power_spectra, log_freqs=False, log_powers=False, ax=None, **kwargs):
    """Plot multiple power spectra on the same plot.

    Parameters
    ----------
    freqs : 1d array
        X-axis data, frequency values.
    power_spectra : list of 1d array
        Y-axis data, power spectrum power values for spectra to plot.
    log_freqs : boolean, optional
        Whether or not to take the log of the power axis before plotting. default: False
    log_powers : boolean, optional
        Whether or not to take the log of the power axis before plotting. default: False
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    **kwargs
        Keyword arguments to be passed to the plot call.
    """

    ax = check_ax(ax)
    for power_spectrum in power_spectra:
        plot_spectrum(freqs, power_spectrum, log_freqs, log_powers, ax=ax, **kwargs)
コード例 #16
0
def plot_spectrum(freqs,
                  power_spectrum,
                  log_freqs=False,
                  log_powers=False,
                  ax=None,
                  plot_style=style_spectrum_plot,
                  **plot_kwargs):
    """Plot a power spectrum.

    Parameters
    ----------
    freqs : 1d array
        Frequency values, to be plotted on the x-axis.
    power_spectrum : 1d array
        Power values, to be plotted on the y-axis.
    log_freqs : bool, optional, default: False
        Whether to plot the frequency axis in log spacing.
    log_powers : bool, optional, default: False
        Whether to plot the power axis in log spacing.
    ax : matplotlib.Axes, optional
        Figure axis upon which to plot.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the plot.
    **plot_kwargs
        Keyword arguments to be passed to the plot call.
    """

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['spectral']))

    # Set plot data & labels, logging if requested
    plt_freqs = np.log10(freqs) if log_freqs else freqs
    plt_powers = np.log10(power_spectrum) if log_powers else power_spectrum

    # Create the plot
    plot_kwargs = check_plot_kwargs(plot_kwargs, {'linewidth': 2.0})
    ax.plot(plt_freqs, plt_powers, **plot_kwargs)

    check_n_style(plot_style, ax, log_freqs, log_powers)
コード例 #17
0
ファイル: spectra.py プロジェクト: vlitvak/fooof
def plot_spectra_shading(freqs,
                         power_spectra,
                         shades,
                         add_center=False,
                         ax=None,
                         plot_style=style_spectrum_plot,
                         **kwargs):
    """Plot a group of power spectra with a shaded frequency region (or regions).

    Parameters
    ----------
    freqs : 2d array or 1d array or list of 1d array
        X-axis data, frequency values.
    power_spectra : 2d array or list of 1d array
        Y-axis data, power values for spectra to plot.
    shades : list of [float, float] or list of list of [float, float]
        Shaded region(s) to add to plot, defined as [lower_bound, upper_bound].
    add_center : boolean, optional, default: False
        Whether to add a line at the center point of the shaded regions.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the plot.
    **kwargs
        Keyword arguments to be passed to plot_spectra or the plot call.

    Notes
    -----
    Parameters for `plot_spectra` can also be passed into this function as **kwargs.
    This includes `log_freqs`, `log_powers` & `labels`. See `plot_spectra for usage details.
    """

    ax = check_ax(ax)
    plot_spectra(freqs, power_spectra, ax=ax, plot_style=None, **kwargs)
    add_shades(ax, shades, add_center, kwargs.get('log_freqs', False))
    check_n_style(plot_style, ax, kwargs.get('log_freqs', False),
                  kwargs.get('log_powers', False))
コード例 #18
0
ファイル: aperiodic.py プロジェクト: parhalje/fooof
def plot_aperiodic_fits(aps,
                        freq_range,
                        control_offset=False,
                        log_freqs=False,
                        colors=None,
                        labels=None,
                        ax=None,
                        **plot_kwargs):
    """Plot reconstructions of model aperiodic fits.

    Parameters
    ----------
    aps : 2d array
        Aperiodic parameters. Each row is a parameter set, as [Off, Exp] or [Off, Knee, Exp].
    freq_range : list of [float, float]
        The frequency range to plot the peak fits across, as [f_min, f_max].
    control_offset : boolean, optional, default: False
        Whether to control for the offset, by setting it to zero.
    log_freqs : boolean, optional, default: False
        Whether to plot the x-axis in log space.
    colors : str or list of str, optional
        Color(s) to plot data.
    labels : list of str, optional
        Label(s) for plotted data, to be added in a legend.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    **plot_kwargs
        Keyword arguments to pass into the ``style_plot``.
    """

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['params']))

    if isinstance(aps, list):

        if not colors:
            colors = cycle(plt.rcParams['axes.prop_cycle'].by_key()['color'])

        recursive_plot(aps,
                       plot_aperiodic_fits,
                       ax=ax,
                       freq_range=tuple(freq_range),
                       control_offset=control_offset,
                       log_freqs=log_freqs,
                       colors=colors,
                       labels=labels,
                       **plot_kwargs)
    else:

        freqs = gen_freqs(freq_range, 0.1)
        plt_freqs = np.log10(freqs) if log_freqs else freqs

        colors = colors[0] if isinstance(colors, list) else colors

        avg_vals = np.zeros(shape=[len(freqs)])

        for ap_params in aps:

            if control_offset:

                # Copy the object to not overwrite any data
                ap_params = ap_params.copy()
                ap_params[0] = 0

            # Recreate & plot the aperiodic component from parameters
            ap_vals = gen_aperiodic(freqs, ap_params)

            ax.plot(plt_freqs,
                    ap_vals,
                    color=colors,
                    alpha=0.35,
                    linewidth=1.25)

            # Collect a running average across components
            avg_vals = np.nansum(np.vstack([avg_vals, ap_vals]), axis=0)

        # Plot the average component
        avg = avg_vals / aps.shape[0]
        avg_color = 'black' if not colors else colors
        ax.plot(plt_freqs, avg, linewidth=3.75, color=avg_color, label=labels)

    # Add axis labels
    ax.set_xlabel('log(Frequency)' if log_freqs else 'Frequency')
    ax.set_ylabel('log(Power)')

    # Set plot limit
    ax.set_xlim(np.log10(freq_range) if log_freqs else freq_range)

    style_param_plot(ax)
コード例 #19
0
ファイル: spectra.py プロジェクト: parhalje/fooof
def plot_spectra_yshade(freqs,
                        power_spectra,
                        shade='std',
                        average='mean',
                        scale=1,
                        log_freqs=False,
                        log_powers=False,
                        color=None,
                        label=None,
                        ax=None,
                        **plot_kwargs):
    """Plot standard deviation or error as a shaded region around the mean spectrum.

    Parameters
    ----------
    freqs : 1d array
        Frequency values, to be plotted on the x-axis.
    power_spectra : 1d or 2d array
        Power values, to be plotted on the y-axis. ``shade`` must be provided if 1d.
    shade : 'std', 'sem', 1d array or callable, optional, default: 'std'
        Approach for shading above/below the mean spectrum.
    average : 'mean', 'median' or callable, optional, default: 'mean'
        Averaging approach for the average spectrum to plot. Only used if power_spectra is 2d.
    scale : int, optional, default: 1
        Factor to multiply the plotted shade by.
    log_freqs : bool, optional, default: False
        Whether to plot the frequency axis in log spacing.
    log_powers : bool, optional, default: False
        Whether to plot the power axis in log spacing.
    color : str, optional, default: None
        Line color of the spectrum.
    label : str, optional, default: None
        Legend label for the spectrum.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    **plot_kwargs
        Keyword arguments to be passed to `plot_spectra` or to the plot call.
    """

    if (isinstance(shade, str)
            or isfunction(shade)) and power_spectra.ndim != 2:
        raise ValueError('Power spectra must be 2d if shade is not given.')

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['spectral']))

    # Set plot data & labels, logging if requested
    plt_freqs = np.log10(freqs) if log_freqs else freqs
    plt_powers = np.log10(power_spectra) if log_powers else power_spectra

    # Organize mean spectrum to plot
    avg_funcs = {'mean': np.mean, 'median': np.median}

    if isinstance(average, str) and plt_powers.ndim == 2:
        avg_powers = avg_funcs[average](plt_powers, axis=0)
    elif isfunction(average) and plt_powers.ndim == 2:
        avg_powers = average(plt_powers)
    else:
        avg_powers = plt_powers

    # Plot average power spectrum
    ax.plot(plt_freqs, avg_powers, linewidth=2.0, color=color, label=label)

    # Organize shading to plot
    shade_funcs = {'std': np.std, 'sem': sem}

    if isinstance(shade, str):
        shade_vals = scale * shade_funcs[shade](plt_powers, axis=0)
    elif isfunction(shade):
        shade_vals = scale * shade(plt_powers)
    else:
        shade_vals = scale * shade

    upper_shade = avg_powers + shade_vals
    lower_shade = avg_powers - shade_vals

    # Plot +/- yshading around spectrum
    alpha = plot_kwargs.pop('alpha', 0.25)
    ax.fill_between(plt_freqs,
                    lower_shade,
                    upper_shade,
                    alpha=alpha,
                    color=color,
                    **plot_kwargs)

    style_spectrum_plot(ax, log_freqs, log_powers)
コード例 #20
0
ファイル: annotate.py プロジェクト: ryanhammonds/fooof
def plot_annotated_peak_search(fm, plot_style=style_spectrum_plot):
    """Plot a series of plots illustrating the peak search from a flattened spectrum.

    Parameters
    ----------
    fm : FOOOF
        FOOOF object, with model fit, data and settings available.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the plots.
    """

    # Recalculate the initial aperiodic fit and flattened spectrum that
    #   is the same as the one that is used in the peak fitting procedure
    flatspec = fm.power_spectrum - \
        gen_aperiodic(fm.freqs, fm._robust_ap_fit(fm.freqs, fm.power_spectrum))

    # Calculate ylims of the plot that are scaled to the range of the data
    ylims = [
        min(flatspec) - 0.1 * np.abs(min(flatspec)),
        max(flatspec) + 0.1 * max(flatspec)
    ]

    # Loop through the iterative search for each peak
    for ind in range(fm.n_peaks_ + 1):

        # This forces the creation of a new plotting axes per iteration
        ax = check_ax(None, PLT_FIGSIZES['spectral'])

        plot_spectrum(fm.freqs,
                      flatspec,
                      ax=ax,
                      plot_style=None,
                      label='Flattened Spectrum',
                      color=PLT_COLORS['data'],
                      linewidth=2.5)
        plot_spectrum(fm.freqs,
                      [fm.peak_threshold * np.std(flatspec)] * len(fm.freqs),
                      ax=ax,
                      plot_style=None,
                      label='Relative Threshold',
                      color='orange',
                      linewidth=2.5,
                      linestyle='dashed')
        plot_spectrum(fm.freqs, [fm.min_peak_height] * len(fm.freqs),
                      ax=ax,
                      plot_style=None,
                      label='Absolute Threshold',
                      color='red',
                      linewidth=2.5,
                      linestyle='dashed')

        maxi = np.argmax(flatspec)
        ax.plot(fm.freqs[maxi],
                flatspec[maxi],
                '.',
                color=PLT_COLORS['periodic'],
                alpha=0.75,
                markersize=30)

        ax.set_ylim(ylims)
        ax.set_title('Iteration #' + str(ind + 1), fontsize=16)

        if ind < fm.n_peaks_:

            gauss = gaussian_function(fm.freqs, *fm.gaussian_params_[ind, :])
            plot_spectrum(fm.freqs,
                          gauss,
                          ax=ax,
                          plot_style=None,
                          label='Gaussian Fit',
                          color=PLT_COLORS['periodic'],
                          linestyle=':',
                          linewidth=3.0)

            flatspec = flatspec - gauss

        check_n_style(plot_style, ax, False, True)
コード例 #21
0
ファイル: annotate.py プロジェクト: ryanhammonds/fooof
def plot_annotated_model(fm,
                         plt_log=False,
                         annotate_peaks=True,
                         annotate_aperiodic=True,
                         ax=None,
                         plot_style=style_spectrum_plot):
    """Plot a an annotated power spectrum and model, from a FOOOF object.

    Parameters
    ----------
    fm : FOOOF
        FOOOF object, with model fit, data and settings available.
    plt_log : boolean, optional, default: False
        Whether to plot the frequency values in log10 spacing.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the plots.

    Raises
    ------
    NoModelError
        If there are no model results available to plot.
    """

    # Check that model is available
    if not fm.has_model:
        raise NoModelError("No model is available to plot, can not proceed.")

    # Settings
    fontsize = 15
    lw1 = 4.0
    lw2 = 3.0
    ms1 = 12

    # Create the baseline figure
    ax = check_ax(ax, PLT_FIGSIZES['spectral'])
    fm.plot(plot_peaks='dot-shade-width',
            plt_log=plt_log,
            ax=ax,
            plot_style=None,
            data_kwargs={
                'lw': lw1,
                'alpha': 0.6
            },
            aperiodic_kwargs={
                'lw': lw1,
                'zorder': 10
            },
            model_kwargs={
                'lw': lw1,
                'alpha': 0.5
            },
            peak_kwargs={
                'dot': {
                    'color': PLT_COLORS['periodic'],
                    'ms': ms1,
                    'lw': lw2
                },
                'shade': {
                    'color': PLT_COLORS['periodic']
                },
                'width': {
                    'color': PLT_COLORS['periodic'],
                    'alpha': 0.75,
                    'lw': lw2
                }
            })

    # Get freqs for plotting, and convert to log if needed
    freqs = fm.freqs if not plt_log else np.log10(fm.freqs)

    ## Buffers: for spacing things out on the plot (scaled by plot values)
    x_buff1 = max(freqs) * 0.1
    x_buff2 = max(freqs) * 0.25
    y_buff1 = 0.15 * np.ptp(ax.get_ylim())
    shrink = 0.1

    # There is a bug in annotations for some perpendicular lines, so add small offset
    #   See: https://github.com/matplotlib/matplotlib/issues/12820. Fixed in 3.2.1.
    bug_buff = 0.000001

    if annotate_peaks:

        # Extract largest peak, to annotate, grabbing gaussian params
        gauss = get_band_peak_fm(fm,
                                 fm.freq_range,
                                 attribute='gaussian_params')

        peak_ctr, peak_hgt, peak_wid = gauss
        bw_freqs = [
            peak_ctr - 0.5 * compute_fwhm(peak_wid),
            peak_ctr + 0.5 * compute_fwhm(peak_wid)
        ]

        if plt_log:
            peak_ctr = np.log10(peak_ctr)
            bw_freqs = np.log10(bw_freqs)

        peak_top = fm.power_spectrum[nearest_ind(freqs, peak_ctr)]

        # Annotate Peak CF
        ax.annotate('Center Frequency',
                    xy=(peak_ctr, peak_top),
                    xytext=(peak_ctr, peak_top + np.abs(0.6 * peak_hgt)),
                    verticalalignment='center',
                    horizontalalignment='center',
                    arrowprops=dict(facecolor=PLT_COLORS['periodic'],
                                    shrink=shrink),
                    color=PLT_COLORS['periodic'],
                    fontsize=fontsize)

        # Annotate Peak PW
        ax.annotate('Power',
                    xy=(peak_ctr, peak_top - 0.3 * peak_hgt),
                    xytext=(peak_ctr + x_buff1, peak_top - 0.3 * peak_hgt),
                    verticalalignment='center',
                    arrowprops=dict(facecolor=PLT_COLORS['periodic'],
                                    shrink=shrink),
                    color=PLT_COLORS['periodic'],
                    fontsize=fontsize)

        # Annotate Peak BW
        bw_buff = (peak_ctr - bw_freqs[0]) / 2
        ax.annotate('Bandwidth',
                    xy=(peak_ctr - bw_buff + bug_buff,
                        peak_top - (0.5 * peak_hgt)),
                    xytext=(peak_ctr - bw_buff, peak_top - (1.5 * peak_hgt)),
                    verticalalignment='center',
                    horizontalalignment='right',
                    arrowprops=dict(facecolor=PLT_COLORS['periodic'],
                                    shrink=shrink),
                    color=PLT_COLORS['periodic'],
                    fontsize=fontsize,
                    zorder=20)

    if annotate_aperiodic:

        # Annotate Aperiodic Offset
        #   Add a line to indicate offset, without adjusting plot limits below it
        ax.set_autoscaley_on(False)
        ax.plot([freqs[0], freqs[0]],
                [ax.get_ylim()[0], fm.fooofed_spectrum_[0]],
                color=PLT_COLORS['aperiodic'],
                linewidth=lw2,
                alpha=0.5)
        ax.annotate('Offset',
                    xy=(freqs[0] + bug_buff, fm.power_spectrum[0] - y_buff1),
                    xytext=(freqs[0] - x_buff1,
                            fm.power_spectrum[0] - y_buff1),
                    verticalalignment='center',
                    horizontalalignment='center',
                    arrowprops=dict(facecolor=PLT_COLORS['aperiodic'],
                                    shrink=shrink),
                    color=PLT_COLORS['aperiodic'],
                    fontsize=fontsize)

        # Annotate Aperiodic Knee
        if fm.aperiodic_mode == 'knee':

            # Find the knee frequency point to annotate
            knee_freq = compute_knee_frequency(
                fm.get_params('aperiodic', 'knee'),
                fm.get_params('aperiodic', 'exponent'))
            knee_freq = np.log10(knee_freq) if plt_log else knee_freq
            knee_pow = fm.power_spectrum[nearest_ind(freqs, knee_freq)]

            # Add a dot to the plot indicating the knee frequency
            ax.plot(knee_freq,
                    knee_pow,
                    'o',
                    color=PLT_COLORS['aperiodic'],
                    ms=ms1 * 1.5,
                    alpha=0.7)

            ax.annotate('Knee',
                        xy=(knee_freq, knee_pow),
                        xytext=(knee_freq - x_buff2, knee_pow - y_buff1),
                        verticalalignment='center',
                        arrowprops=dict(facecolor=PLT_COLORS['aperiodic'],
                                        shrink=shrink),
                        color=PLT_COLORS['aperiodic'],
                        fontsize=fontsize)

        # Annotate Aperiodic Exponent
        mid_ind = int(len(freqs) / 2)
        ax.annotate('Exponent',
                    xy=(freqs[mid_ind], fm.power_spectrum[mid_ind]),
                    xytext=(freqs[mid_ind] - x_buff2,
                            fm.power_spectrum[mid_ind] - y_buff1),
                    verticalalignment='center',
                    arrowprops=dict(facecolor=PLT_COLORS['aperiodic'],
                                    shrink=shrink),
                    color=PLT_COLORS['aperiodic'],
                    fontsize=fontsize)

    # Apply style to plot & tune grid styling
    check_n_style(plot_style, ax, plt_log, True)
    ax.grid(True, alpha=0.5)

    # Add labels to plot in the legend
    da_patch = mpatches.Patch(color=PLT_COLORS['data'], label='Original Data')
    ap_patch = mpatches.Patch(color=PLT_COLORS['aperiodic'],
                              label='Aperiodic Parameters')
    pe_patch = mpatches.Patch(color=PLT_COLORS['periodic'],
                              label='Peak Parameters')
    mo_patch = mpatches.Patch(color=PLT_COLORS['model'], label='Full Model')

    handles = [
        da_patch, ap_patch if annotate_aperiodic else None,
        pe_patch if annotate_peaks else None, mo_patch
    ]
    handles = [el for el in handles if el is not None]

    ax.legend(handles=handles, handlelength=1, fontsize='x-large')
コード例 #22
0
ファイル: fm.py プロジェクト: parhalje/fooof
def plot_fm(fm,
            plot_peaks=None,
            plot_aperiodic=True,
            plt_log=False,
            add_legend=True,
            save_fig=False,
            file_name=None,
            file_path=None,
            ax=None,
            data_kwargs=None,
            model_kwargs=None,
            aperiodic_kwargs=None,
            peak_kwargs=None,
            **plot_kwargs):
    """Plot the power spectrum and model fit results from a FOOOF object.

    Parameters
    ----------
    fm : FOOOF
        Object containing a power spectrum and (optionally) results from fitting.
    plot_peaks : None or {'shade', 'dot', 'outline', 'line'}, optional
        What kind of approach to take to plot peaks. If None, peaks are not specifically plotted.
        Can also be a combination of approaches, separated by '-', for example: 'shade-line'.
    plot_aperiodic : boolean, optional, default: True
        Whether to plot the aperiodic component of the model fit.
    plt_log : boolean, optional, default: False
        Whether to plot the frequency values in log10 spacing.
    add_legend : boolean, optional, default: False
        Whether to add a legend describing the plot components.
    save_fig : bool, optional, default: False
        Whether to save out a copy of the plot.
    file_name : str, optional
        Name to give the saved out file.
    file_path : str, optional
        Path to directory to save to. If None, saves to current directory.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    data_kwargs, model_kwargs, aperiodic_kwargs, peak_kwargs : None or dict, optional
        Keyword arguments to pass into the plot call for each plot element.
    **plot_kwargs
        Keyword arguments to pass into the ``style_plot``.

    Notes
    -----
    Since FOOOF objects store power values in log spacing,
    the y-axis (power) is plotted in log spacing by default.
    """

    ax = check_ax(ax, PLT_FIGSIZES['spectral'])

    # Log settings - note that power values in FOOOF objects are already logged
    log_freqs = plt_log
    log_powers = False

    # Plot the data, if available
    if fm.has_data:
        data_defaults = {
            'color': PLT_COLORS['data'],
            'linewidth': 2.0,
            'label': 'Original Spectrum' if add_legend else None
        }
        data_kwargs = check_plot_kwargs(data_kwargs, data_defaults)
        plot_spectra(fm.freqs,
                     fm.power_spectrum,
                     log_freqs,
                     log_powers,
                     ax=ax,
                     **data_kwargs)

    # Add the full model fit, and components (if requested)
    if fm.has_model:
        model_defaults = {
            'color': PLT_COLORS['model'],
            'linewidth': 3.0,
            'alpha': 0.5,
            'label': 'Full Model Fit' if add_legend else None
        }
        model_kwargs = check_plot_kwargs(model_kwargs, model_defaults)
        plot_spectra(fm.freqs,
                     fm.fooofed_spectrum_,
                     log_freqs,
                     log_powers,
                     ax=ax,
                     **model_kwargs)

        # Plot the aperiodic component of the model fit
        if plot_aperiodic:
            aperiodic_defaults = {
                'color': PLT_COLORS['aperiodic'],
                'linewidth': 3.0,
                'alpha': 0.5,
                'linestyle': 'dashed',
                'label': 'Aperiodic Fit' if add_legend else None
            }
            aperiodic_kwargs = check_plot_kwargs(aperiodic_kwargs,
                                                 aperiodic_defaults)
            plot_spectra(fm.freqs,
                         fm._ap_fit,
                         log_freqs,
                         log_powers,
                         ax=ax,
                         **aperiodic_kwargs)

        # Plot the periodic components of the model fit
        if plot_peaks:
            _add_peaks(fm, plot_peaks, plt_log, ax, peak_kwargs)

    # Apply default style to plot
    style_spectrum_plot(ax, log_freqs, True)
コード例 #23
0
def main():

    ## Individual Model Plot

    # Download examples data files needed for this example
    freqs = load_fooof_data('freqs.npy', folder='data')
    spectrum = load_fooof_data('spectrum.npy', folder='data')

    # Initialize and fit an example power spectrum model
    fm = FOOOF(peak_width_limits=[1, 6],
               max_n_peaks=6,
               min_peak_height=0.2,
               verbose=False)
    fm.fit(freqs, spectrum, [3, 40])

    # Save out the report
    fm.save_report('FOOOF_report.png', 'img')

    ## Group Plot

    # Download examples data files needed for this example
    freqs = load_fooof_data('group_freqs.npy', folder='data')
    spectra = load_fooof_data('group_powers.npy', folder='data')

    # Initialize and fit a group of example power spectrum models
    fg = FOOOFGroup(peak_width_limits=[1, 6],
                    max_n_peaks=6,
                    min_peak_height=0.2,
                    verbose=False)
    fg.fit(freqs, spectra, [3, 30])

    # Save out the report
    fg.save_report('FOOOFGroup_report.png', 'img')

    ## Make the icon plot

    # Simulate an example power spectrum
    fs, ps = gen_power_spectrum([4, 35], [0, 1],
                                [[10, 0.3, 1], [22, 0.15, 1.25]],
                                nlv=0.01)

    def custom_style(ax, log_freqs, log_powers):
        """Custom styler-function for the icon plot."""

        # Set the top and right side frame & ticks off
        ax.spines['right'].set_visible(False)
        ax.spines['top'].set_visible(False)

        # Set linewidth of remaining spines
        ax.spines['left'].set_linewidth(10)
        ax.spines['bottom'].set_linewidth(10)
        ax.set_xticks([], [])
        ax.set_yticks([], [])

    # Create and save out the plot
    plot_spectrum(fs,
                  ps,
                  log_freqs=False,
                  log_powers=True,
                  lw=12,
                  alpha=0.8,
                  color='grey',
                  plot_style=custom_style,
                  ax=check_ax(None, [6, 6]))
    plt.tight_layout()
    plt.savefig('img/spectrum.png')

    ## Clean Up

    # Remove the data folder
    shutil.rmtree('data')
コード例 #24
0
ファイル: periodic.py プロジェクト: parhalje/fooof
def plot_peak_fits(peaks,
                   freq_range=None,
                   colors=None,
                   labels=None,
                   ax=None,
                   **plot_kwargs):
    """Plot reconstructions of model peak fits.

    Parameters
    ----------
    peaks : 2d array
        Peak data. Each row is a peak, as [CF, PW, BW].
    freq_range : list of [float, float] , optional
        The frequency range to plot the peak fits across, as [f_min, f_max].
        If not provided, defaults to +/- 4 around given peak center frequencies.
    colors : str or list of str, optional
        Color(s) to plot data.
    labels : list of str, optional
        Label(s) for plotted data, to be added in a legend.
    ax : matplotlib.Axes, optional
        Figure axes upon which to plot.
    **plot_kwargs
        Keyword arguments to pass into the plot call.
    """

    ax = check_ax(ax, plot_kwargs.pop('figsize', PLT_FIGSIZES['params']))

    if isinstance(peaks, list):

        if not colors:
            colors = cycle(plt.rcParams['axes.prop_cycle'].by_key()['color'])

        recursive_plot(
            peaks,
            plot_function=plot_peak_fits,
            ax=ax,
            freq_range=tuple(freq_range) if freq_range else freq_range,
            colors=colors,
            labels=labels,
            **plot_kwargs)

    else:

        if not freq_range:

            # Extract all the CF values, excluding any NaNs
            cfs = peaks[~np.isnan(peaks[:, 0]), 0]

            # Define the frequency range as +/- buffer around the data range
            #   This also doesn't let the plot range drop below 0
            f_buffer = 4
            freq_range = [
                cfs.min() - f_buffer if cfs.min() - f_buffer > 0 else 0,
                cfs.max() + f_buffer
            ]

        # Create the frequency axis, which will be the plot x-axis
        freqs = gen_freqs(freq_range, 0.1)

        colors = colors[0] if isinstance(colors, list) else colors

        avg_vals = np.zeros(shape=[len(freqs)])

        for peak_params in peaks:

            # Create & plot the peak model from parameters
            peak_vals = gaussian_function(freqs, *peak_params)
            ax.plot(freqs, peak_vals, color=colors, alpha=0.35, linewidth=1.25)

            # Collect a running average average peaks
            avg_vals = np.nansum(np.vstack([avg_vals, peak_vals]), axis=0)

        # Plot the average across all components
        avg = avg_vals / peaks.shape[0]
        avg_color = 'black' if not colors else colors
        ax.plot(freqs, avg, color=avg_color, linewidth=3.75, label=labels)

    # Add axis labels
    ax.set_xlabel('Frequency')
    ax.set_ylabel('log(Power)')

    # Set plot limits
    ax.set_xlim(freq_range)
    ax.set_ylim([0, ax.get_ylim()[1]])

    # Apply plot style
    style_param_plot(ax)