Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions fooof/core/info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Internal functions to manage info related to FOOOF objects."""

def get_obj_desc():
"""Get dictionary specifying FOOOF object names and kind of attributes.

Returns
-------
attibutes : dict
Mapping of FOOOF object attributes, and what kind of data they are.
"""

attributes = {'results' : ['aperiodic_params_', 'peak_params_',
'r_squared_', 'error_',
'_gaussian_params'],
'settings' : ['peak_width_limits', 'max_n_peaks',
'min_peak_amplitude', 'peak_threshold',
'aperiodic_mode'],
'data' : ['power_spectrum', 'freq_range', 'freq_res'],
'data_info' : ['freq_range', 'freq_res'],
'arrays' : ['freqs', 'power_spectrum', 'aperiodic_params_',
'peak_params_', '_gaussian_params'],
'model_components' : ['_spectrum_flat', '_spectrum_peak_rm',
'_ap_fit', '_peak_fit']}

return attributes


def get_data_indices(aperiodic_mode):
"""Get a dictionary mapping the column labels to indices in FOOOF data (FOOOFResults).

Parameters
----------
aperiodic_mode : {'fixed', 'knee'}
Which approach taken to fit the aperiodic component.

Returns
-------
indices : dict
Mapping for data columns to the column indices in which they appear.
"""

indices = {
'CF' : 0,
'Amp' : 1,
'BW' : 2,
'offset' : 0,
'knee' : 1 if aperiodic_mode == 'knee' else None,
'exponent' : 1 if aperiodic_mode == 'fixed' else 2
}

return indices
5 changes: 3 additions & 2 deletions fooof/core/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import json
from json import JSONDecodeError

from fooof.core.utils import dict_array_to_lst, dict_select_keys, dict_lst_to_array, get_obj_desc
from fooof.core.info import get_obj_desc
from fooof.core.utils import dict_array_to_lst, dict_select_keys, dict_lst_to_array

###################################################################################################
###################################################################################################
Expand Down Expand Up @@ -89,7 +90,7 @@ def save_fm(fm, file_name, file_path=None, append=False,
# Set and select which variables to keep. Use a set to drop any potential overlap
# Note that results also saves frequency information to be able to recreate freq vector
attributes = get_obj_desc()
keep = set((attributes['results'] + attributes['freq_info'] if save_results else []) + \
keep = set((attributes['results'] + attributes['data_info'] if save_results else []) + \
(attributes['settings'] if save_settings else []) + \
(attributes['data'] if save_data else []))
obj_dict = dict_select_keys(obj_dict, keep)
Expand Down
22 changes: 11 additions & 11 deletions fooof/core/strings.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ def gen_wid_warn_str(freq_res, bwl):

output = '\n'.join([
'',
"FOOOF WARNING: Lower-bound peak width limit is < or ~= the frequency resolution: " + \
"{:1.2f} <= {:1.2f}".format(freq_res, bwl),
'FOOOF WARNING: Lower-bound peak width limit is < or ~= the frequency resolution: ' + \
'{:1.2f} <= {:1.2f}'.format(freq_res, bwl),
'\tLower bounds below frequency-resolution have no effect (effective lower bound is freq-res)',
'\tToo low a limit may lead to overfitting noise as small bandwidth peaks.',
'\tWe recommend a lower bound of approximately 2x the frequency resolution.',
Expand Down Expand Up @@ -57,11 +57,11 @@ def gen_settings_str(f_obj, description=False, concise=False):
"""

# Parameter descriptions to print out, if requested
desc = {'aperiodic_mode' : 'The aproach taken to fitting the aperiodic component.',
'peak_width_limits' : 'Enforced limits for peak widths, in Hz.',
desc = {'peak_width_limits' : 'Enforced limits for peak widths, in Hz.',
'max_n_peaks' : 'The maximum number of peaks that can be extracted.',
'min_peak_amplitude' : "Minimum absolute amplitude of a peak, above aperiodic component.",
'peak_threshold' : "Threshold at which to stop searching for peaks."}
'min_peak_amplitude' : 'Minimum absolute amplitude of a peak, above aperiodic component.',
'peak_threshold' : 'Threshold at which to stop searching for peaks.',
'aperiodic_mode' : 'The aproach taken to fitting the aperiodic component.'}

# Clear description for printing if not requested
if not description:
Expand All @@ -77,16 +77,16 @@ def gen_settings_str(f_obj, description=False, concise=False):
'',

# Settings - include descriptions if requested
*[el for el in ['Aperiodic Mode : {}'.format(f_obj.aperiodic_mode),
'{}'.format(desc['aperiodic_mode']),
'Peak Width Limits : {}'.format(f_obj.peak_width_limits),
*[el for el in ['Peak Width Limits : {}'.format(f_obj.peak_width_limits),
'{}'.format(desc['peak_width_limits']),
'Max Number of Peaks : {}'.format(f_obj.max_n_peaks),
'{}'.format(desc['max_n_peaks']),
'Minimum Amplitude : {}'.format(f_obj.min_peak_amplitude),
'{}'.format(desc['min_peak_amplitude']),
'Amplitude Threshold: {}'.format(f_obj.peak_threshold),
'{}'.format(desc['peak_threshold'])] if el != ''],
'{}'.format(desc['peak_threshold']),
'Aperiodic Mode : {}'.format(f_obj.aperiodic_mode),
'{}'.format(desc['aperiodic_mode'])] if el != ''],

# Footer
'',
Expand Down Expand Up @@ -280,7 +280,7 @@ def gen_issue_str(concise=False):
'If FOOOF gives you any weird / bad fits, please let us know!',
'To do so, send us a FOOOF report, and a FOOOF data file, ',
'',
"With a FOOOF object (fm), after fitting, run the following commands:",
'With a FOOOF object (fm), after fitting, run the following commands:',
"fm.create_report('FOOOF_bad_fit_report')",
"fm.save('FOOOF_bad_fit_data', True, True, True)",
'',
Expand Down
47 changes: 0 additions & 47 deletions fooof/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,53 +100,6 @@ def check_array_dim(arr):
return np.empty([0, 3]) if arr.ndim == 1 else arr


def get_obj_desc():
"""Get dictionary specifying FOOOF object names and kind of attributes.

Returns
-------
attibutes : dict
Mapping of FOOOF object attributes, and what kind of data they are.
"""

attributes = {'results' : ['aperiodic_params_', 'peak_params_', 'error_',
'r_squared_', '_gaussian_params'],
'settings' : ['peak_width_limits', 'max_n_peaks', 'min_peak_amplitude',
'peak_threshold', 'aperiodic_mode'],
'data' : ['power_spectrum', 'freq_range', 'freq_res'],
'freq_info' : ['freq_range', 'freq_res'],
'arrays' : ['freqs', 'power_spectrum', 'aperiodic_params_',
'peak_params_', '_gaussian_params']}

return attributes


def get_data_indices(aperiodic_mode):
"""Get a dictionary mapping the column labels to indices in FOOOF data (FOOOFResults).

Parameters
----------
aperiodic_mode : {'fixed', 'knee'}
Which approach taken to fit the aperiodic component.

Returns
-------
indices : dict
Mapping for data columns to the column indices in which they appear.
"""

indices = {
'CF' : 0,
'Amp' : 1,
'BW' : 2,
'offset' : 0,
'knee' : 1 if aperiodic_mode == 'knee' else None,
'exponent' : 1 if aperiodic_mode == 'fixed' else 2
}

return indices


def check_iter(obj, length):
"""Check an object to ensure that it is iterable, and make it iterable if not.

Expand Down
78 changes: 78 additions & 0 deletions fooof/data.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"""Data objects for FOOOF."""

from collections import namedtuple

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

FOOOFSettings = namedtuple('FOOOFSettings', ['peak_width_limits', 'max_n_peaks',
'min_peak_amplitude', 'peak_threshold',
'aperiodic_mode'])
FOOOFSettings.__doc__ = """\
The user defined settings for a FOOOF object.

Attributes
----------
peak_width_limits : tuple of (float, float), optional, default: (0.5, 12.0)
Limits on possible peak width, as (lower_bound, upper_bound).
max_n_peaks : int, optional, default: inf
Maximum number of gaussians to be fit in a single spectrum.
min_peak_amplitude : float, optional, default: 0
Minimum amplitude threshold for a peak to be modeled.
peak_threshold : float, optional, default: 2.0
Threshold for detecting peaks, units of standard deviation.
aperiodic_mode : {'fixed', 'knee'}
Which approach to take for fitting the aperiodic component.
"""


FOOOFDataInfo = namedtuple('FOOOFDataInfo', ['freq_range', 'freq_res'])

FOOOFDataInfo.__doc__ = """\
Data related information for a FOOOF object.

Attributes
----------
freq_range : list of [float, float]
Frequency range of the power spectrum, as [lowest_freq, highest_freq].
freq_res : float
Frequency resolution of the power spectrum.
"""


FOOOFResults = namedtuple('FOOOFResults', ['aperiodic_params', 'peak_params',
'r_squared', 'error', 'gaussian_params'])
FOOOFResults.__doc__ = """\
The resulting parameters and associated data of a FOOOF model fit.

Attributes
----------
aperiodic_params : 1d array
Parameters that define the aperiodic fit. As [Offset, (Knee), Exponent].
The knee parameter is only included if aperiodic is fit with knee.
peak_params : 2d array
Fitted parameter values for the peaks. Each row is a peak, as [CF, Amp, BW].
r_squared : float
R-squared of the fit between the input power spectrum and the full model fit.
error : float
Root mean squared error of the full model fit.
gaussian_params : 2d array
Parameters that define the gaussian fit(s). Each row is a gaussian, as [mean, amp, std].
"""


SynParams = namedtuple('SynParams', ['aperiodic_params', 'gaussian_params', 'nlv'])

SynParams.__doc__ = """\
Stores parameters used to synthesize a single power spectra.

Attributes
----------
aperiodic_params : list, len 2 or 3
Parameters that define the aperiodic fit. As [Offset, (Knee), Exponent].
The knee parameter is only included if aperiodic is fit with knee. Otherwise, length is 2.
gaussian_params : list or list of lists
Fitted parameter values for the peaks. Each list is a peak, as [CF, Amp, BW].
nlv : float
Noise level added to the generated power spectrum.
"""
Loading