Exemple #1
0
def calc_interacting_param_ratios(data,
                                  low_band=BANDS["theta"],
                                  high_band=BANDS["beta"]):
    """Calculates matrix of absolute ratios from interacting data.

    Parameters
    ----------
    data : custom object ndarray [apc value][frequency vector][psds][syn_params]

    Outputs
    -------
    res : 2D matrix of ratios where each dimension is a varied parameter

    ------------------------
    |           |          |
    |   r_11    |  r_12    |
    |           |          |
    |-----------------------
    |           |          |
    |   r_21    |  r_22    |
    |           |          |
    ------------------------
    """

    fs = gen_freqs(FREQ_RANGE, FREQ_RES)
    ratios = np.zeros(shape=(len(data), len(data[0])))

    for rot_ind, rot_val in enumerate(data):

        for del_ind, del_val in enumerate(data[0]):
            psd = data[rot_ind, del_ind, :]
            ratios[rot_ind, del_ind] = calc_band_ratio(fs, psd, low_band,
                                                       high_band)

    return ratios
Exemple #2
0
def return_fooof_regen(fg):
    """
    Takes a fitted FOOOFGroup model and returns the fitted (modeled) PSDs in
    linear power.
    """
    f_regen = sim.gen_freqs(fg.freq_range, fg.freq_res)
    n_psds = fg.get_params('error').shape[0]
    psds_regen = 10**np.array([
        fg.get_fooof(ind, regenerate=True).fooofed_spectrum_
        for ind in range(n_psds)
    ])
    return f_regen, psds_regen
Exemple #3
0
def test_fooof_check_data():
    """Test FOOOF in with check data mode turned off, including with NaN data."""

    tfm = FOOOF(verbose=False)

    tfm.set_check_data_mode(False)
    assert tfm._check_data is False

    # Add data, with check data turned off
    #   In check data mode, adding data with NaN should run
    freqs = gen_freqs([3, 50], 0.5)
    powers = np.ones_like(freqs) * np.nan
    tfm.add_data(freqs, powers)
    assert tfm.has_data

    # Model fitting should execute, but return a null model fit, given the NaNs, without failing
    tfm.fit()
    assert not tfm.has_model
Exemple #4
0
def combine_fooofs(fooofs):
    """Combine a group of FOOOF and/or FOOOFGroup objects into a single FOOOFGroup object.

    Parameters
    ----------
    fooofs : list of FOOOF or FOOOFGroup
        Objects to be concatenated into a FOOOFGroup.

    Returns
    -------
    fg : FOOOFGroup
        Resultant object from combining inputs.

    Raises
    ------
    IncompatibleSettingsError
        If the input objects have incompatible settings for combining.

    Examples
    --------
    Combine FOOOF objects together (where `fm1`, `fm2` & `fm3` are assumed to be defined and fit):

    >>> fg = combine_fooofs([fm1, fm2, fm3])  # doctest:+SKIP

    Combine FOOOFGroup objects together (where `fg1` & `fg2` are assumed to be defined and fit):

    >>> fg = combine_fooofs([fg1, fg2])  # doctest:+SKIP
    """

    # Compare settings
    if not compare_info(fooofs, 'settings') or not compare_info(
            fooofs, 'meta_data'):
        raise IncompatibleSettingsError(
            "These objects have incompatible settings "
            "or meta data, and so cannot be combined.")

    # Initialize FOOOFGroup object, with settings derived from input objects
    fg = FOOOFGroup(*fooofs[0].get_settings(), verbose=fooofs[0].verbose)

    # Use a temporary store to collect spectra, as we'll only add it if it is consistently present
    #   We check how many frequencies by accessing meta data, in case of no frequency vector
    meta_data = fooofs[0].get_meta_data()
    n_freqs = len(gen_freqs(meta_data.freq_range, meta_data.freq_res))
    temp_power_spectra = np.empty([0, n_freqs])

    # Add FOOOF results from each FOOOF object to group
    for f_obj in fooofs:

        # Add FOOOFGroup object
        if isinstance(f_obj, FOOOFGroup):
            fg.group_results.extend(f_obj.group_results)
            if f_obj.power_spectra is not None:
                temp_power_spectra = np.vstack(
                    [temp_power_spectra, f_obj.power_spectra])

        # Add FOOOF object
        else:
            fg.group_results.append(f_obj.get_results())
            if f_obj.power_spectrum is not None:
                temp_power_spectra = np.vstack(
                    [temp_power_spectra, f_obj.power_spectrum])

    # If the number of collected power spectra is consistent, then add them to object
    if len(fg) == temp_power_spectra.shape[0]:
        fg.power_spectra = temp_power_spectra

    # Set the check data mode, as True if any of the inputs have it on, False otherwise
    fg.set_check_data_mode(
        any([getattr(f_obj, '_check_data') for f_obj in fooofs]))

    # Add data information information
    fg.add_meta_data(fooofs[0].get_meta_data())

    return fg
Exemple #5
0
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)