Example #1
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')
Example #2
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
Example #3
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')))
Example #4
0
# Fit the FOOOF model.
fm.fit(freqs, spectrum, [3, 40])

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

# Do an initial aperiodic signal fit - a robust background fit (excluding outliers)
#  This recreates an initial fit that isn't ultimately stored in the FOOOF object)
init_bg_fit = gen_background(fm.freqs,
                             fm._robust_bg_fit(fm.freqs, fm.power_spectrum))

# Plot the initial aperiodic 'background' fit
_, ax = plt.subplots(figsize=(12, 10))
plot_spectrum(fm.freqs,
              fm.power_spectrum,
              plt_log,
              label='Original Power Spectrum',
              ax=ax)
plot_spectrum(fm.freqs,
              init_bg_fit,
              plt_log,
              label='Initial Background Fit',
              ax=ax)

###############################################################################
#
# The initial fit, as above, is used to create a flattened spectrum, from which peaks can be extracted.

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

# Flatten the power spectrum, by subtracting out the initial aperiodic fit
Example #5
0
# Settings & parameters for creating a simulated power spectrum
freq_range = [3, 40]  # The frequency range to simulate
aperiodic_params = [1, 1]  # Parameters defining the aperiodic component
periodic_params = [10, 0.3, 1]  # Parameters for any periodic components

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

# Generate a simulated power spectrum
freqs, powers = gen_power_spectrum(freq_range, aperiodic_params,
                                   periodic_params)

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

# Plot the simulated power spectrum
plot_spectrum(freqs, powers, log_freqs=True, log_powers=False)

###################################################################################################
# Simulating With Different Parameters
# ------------------------------------
#
# Power spectra can be simulated with any desired parameters in the power spectrum model.
#
# The aperiodic mode for the simulated power spectrum is inferred from the parameters provided.
# If two parameters are provided, this is interpreted as [offset, exponent] for simulating
# a power spectra with a 'fixed' aperiodic component. If three parameters are provided, as in
# the example below, this is interpreted as [offset, knee, exponent] for a 'knee' spectrum.
#
# Power spectra can also be simulated with any number of peaks. Peaks can be listed in a flat
# list with [center frequency, height, bandwidth] listed for as many peaks as you would
# like to add, or as a list of lists containing the same information.
Example #6
0
fs, ps, _ = gen_group_power_spectra(2, [3, 40], [[0.75, 1.5], [0.25, 1]],
                                    [6, 0.2, 1, 10, 0.3, 1, 25, 0.15, 3])
ps1, ps2 = ps

###################################################################################################
# The FOOOF plotting module has plots for plotting single or multiple
# power spectra, options for plotting in linear or log space, and
# plots for shading frequency regions of interest.
#
# Plotting in FOOOF uses matplotlib. Plotting functions can also take in any
# matplotlib keyword arguments, that will be passed into the plot call.

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

# Create a spectrum plot with a single power spectrum
plot_spectrum(fs, ps2, log_powers=True)

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

# Plot multiple spectra on the same plot
plot_spectra(fs, ps, log_freqs=True, log_powers=True)

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

# Plot a single power spectrum, with a shaded region covering alpha
plot_spectrum_shading(fs, ps1, [8, 12], log_powers=True)

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

# Plot multiple power spectra, with shades covering theta & beta ranges
plot_spectra_shading(fs, ps, [[4, 8], [20, 30]], log_powers=True)
Example #7
0
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)
Example #8
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')
Example #9
0
###################################################################################################
#
# In the topography above, we can see that there is a fair amount of variation
# across the scalp in terms of aperiodic exponent value, and there seems to be some
# spatial structure to it.
#
# To visualize how much the exponent values vary, we can again plot some example power
# spectra, in this case extracting those with the highest and lower exponent values.
#

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

# Compare the power spectra between low and high exponent channels
fig, ax = plt.subplots(figsize=(8, 6))
plot_spectrum(fg.freqs,
              fg.get_fooof(np.argmin(exps)).power_spectrum,
              ax=ax,
              label='Low Exponent')
plot_spectrum(fg.freqs,
              fg.get_fooof(np.argmax(exps)).power_spectrum,
              ax=ax,
              label='High Exponent')

###################################################################################################
# Conclusion
# ----------
#
# In this example, we have seen how to apply power spectrum models to data that is
# managed and processed with MNE.
#

###################################################################################################
Example #10
0
# ---------------------------------
#
# First we will start with the core plotting function that plots an individual power spectrum.
#
# The :func:`~.plot_spectrum` function takes in an array of frequency values and a 1d array of
# of power values, and plots the corresponding power spectrum.
#
# This function, as all the functions in the plotting module, takes in optional inputs
# `log_freqs` and `log_powers` that control whether the frequency and power axes
# are plotted in log space.
#

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

# Create a spectrum plot with a single power spectrum
plot_spectrum(freqs, powers1, log_powers=True)

###################################################################################################
# Plotting Multiple Power Spectra
# -------------------------------
#
# The :func:`~.plot_spectra` function takes in one or more frequency arrays and one or more
# array of associated power values and plots multiple power spectra.
#
# Note that the inputs for either can be either 2d arrays, or lists of 1d arrays. You can also
# pass in additional optional inputs including `labels`, to specify labels to use in a plot
# legend, and `colors` to specify which colors to plot each spectrum in.
#

###################################################################################################
Example #11
0
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,
            plot_style=style_spectrum_plot,
            data_kwargs=None,
            model_kwargs=None,
            aperiodic_kwargs=None,
            peak_kwargs=None):
    """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.
    plot_style : callable, optional, default: style_spectrum_plot
        A function to call to apply styling & aesthetics to the 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.

    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_kwargs = check_plot_kwargs(data_kwargs, \
            {'color' : PLT_COLORS['data'], 'linewidth' : 2.0,
             'label' : 'Original Spectrum' if add_legend else None})
        plot_spectrum(fm.freqs,
                      fm.power_spectrum,
                      log_freqs,
                      log_powers,
                      ax=ax,
                      plot_style=None,
                      **data_kwargs)

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

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

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

    # Apply style to plot
    check_n_style(plot_style, ax, log_freqs, True)

    # Save out figure, if requested
    if save_fig:
        if not file_name:
            raise ValueError(
                "Input 'file_name' is required to save out the plot.")
        plt.savefig(fpath(file_path, fname(file_name, 'png')))
Example #12
0
#
# Plotted below is an example power spectrum, plotted in semi-log space (log10 power values
# and linear frequencies). This is our data, that we will be trying to model.
#
# In the plot, we see a power spectrum in which there is decreasing power across increasing
# frequencies. In some frequency regions, there is a 'peak' of power, over and above the general
# trend across frequencies. These properties - a pattern of decreasing power across frequencies,
# with overlying peaks - are considered to be hallmarks of neural field data.
#

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

# Plot one of the example power spectra
plot_spectrum(freqs1,
              powers1,
              log_powers=True,
              color='black',
              label='Original Spectrum')

###################################################################################################
# Conceptual Overview
# -------------------
#
# The goal of this module is to fit models to parameterize neural power spectra.
#
# One reason to do so is the idea that there are multiple distinct 'components' within
# neural field data. The model is therefore designed to measure these different
# 'components' of the data.
#
# By components, we mean that we are going to conceptualize neural field data as consisting
# of a combination of periodic (oscillatory) and aperiodic activity. Restated, we could say
# Step 1: Initial Aperiodic Fit
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# We start by taking an initial aperiodic fit. This goal of this fit is to get an initial
# fit that is good enough to get started with the fitting process.
#

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

# Do an initial aperiodic fit - a robust fit, that excludes outliers
#   This recreates an initial fit that isn't ultimately stored in the FOOOF object
init_ap_fit = gen_aperiodic(fm.freqs, fm._robust_ap_fit(fm.freqs, fm.power_spectrum))

# Plot the initial aperiodic fit
_, ax = plt.subplots(figsize=(12, 10))
plot_spectrum(fm.freqs, fm.power_spectrum, plt_log,
              label='Original Power Spectrum', color='black', ax=ax)
plot_spectrum(fm.freqs, init_ap_fit, plt_log, label='Initial Aperiodic Fit',
              color='blue', alpha=0.5, linestyle='dashed', ax=ax)

###################################################################################################
# Step 2: Flatten the Spectrum
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# The initial fit is then used to create a flattened spectrum.
#
# The initial aperiodic fit is subtracted out from the original data, leaving a flattened
# version of the data which no longer contains the aperiodic component.
#

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