Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] - Define new object organization (Data / Results / Base / Algorithm) #291

Open
wants to merge 50 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
f484bce
test out base model object
TomDonoghue Jul 19, 2023
a4238ba
small doc tweaks
TomDonoghue Jul 19, 2023
89d45b5
trial a new BaseData object
TomDonoghue Jul 20, 2023
b9fe0e1
continue exploration of BaseData object
TomDonoghue Jul 20, 2023
93450c2
trial out BaseFit object
TomDonoghue Jul 20, 2023
5bc1891
Merge branch 'name' into basemodel
TomDonoghue Jul 22, 2023
f65f012
fix / finish merge
TomDonoghue Jul 25, 2023
188e183
interim test update - use sub objects for group
TomDonoghue Jul 29, 2023
43658fa
interim update: move things around
TomDonoghue Jul 31, 2023
557d157
reorg to use base object & do renames
TomDonoghue Jul 31, 2023
6f6fa3b
updates of tests for new object org
TomDonoghue Jul 31, 2023
a2a0b8e
merge name
TomDonoghue Aug 3, 2023
fea9559
interim merge
TomDonoghue Aug 3, 2023
b548e01
fix merge of get_data & get_model
TomDonoghue Aug 3, 2023
a9060a1
merge data / model checks in get functions
TomDonoghue Aug 3, 2023
50286af
Merge branch 'name' into basemodel
TomDonoghue Aug 3, 2023
327861e
fix merge name
TomDonoghue Sep 13, 2023
85b647a
Merge branch 'main' into basemodel
TomDonoghue Feb 15, 2024
f902ac6
fix merge
TomDonoghue Mar 27, 2024
a1880d0
fix for model object
TomDonoghue Apr 6, 2024
b1963df
reorg where fit funcs are & associated
TomDonoghue Apr 6, 2024
8215331
add base object 2DT
TomDonoghue Apr 7, 2024
063cb1d
add data object 2DT
TomDonoghue Apr 7, 2024
a16b827
add fit object 2DT
TomDonoghue Apr 7, 2024
5526020
move save / load to base objects
TomDonoghue Apr 8, 2024
6bc1f86
add getters to fit obj
TomDonoghue Apr 8, 2024
65ec2b8
move stuff to base / fit
TomDonoghue Apr 8, 2024
fa6298a
rework time obj to use new obj org - move methods
TomDonoghue Apr 8, 2024
83ae693
lints from updates
TomDonoghue Apr 8, 2024
97e0531
update data checks for 3D properly
TomDonoghue Apr 8, 2024
371383f
add base3d
TomDonoghue Apr 9, 2024
f9f1553
add data3d
TomDonoghue Apr 9, 2024
c993ab5
add fit3f
TomDonoghue Apr 9, 2024
4d832f1
rework event to use new objs
TomDonoghue Apr 9, 2024
facd87e
add plot methods to data objects
TomDonoghue Apr 9, 2024
4383b1a
FitObjects -> ResultsObjects
TomDonoghue Apr 10, 2024
6951711
fix up verboseness & warnings
TomDonoghue Apr 10, 2024
20b6dc2
add load funcs & io updates
TomDonoghue Apr 10, 2024
dd621d7
update event reset data for consistency
TomDonoghue Apr 10, 2024
b8927fe
lints
TomDonoghue Apr 10, 2024
9ff8763
bump version number
TomDonoghue Apr 10, 2024
31bb7f9
fix quirk in example
TomDonoghue Apr 10, 2024
ccb376d
add custom css for header
TomDonoghue Apr 30, 2024
41509d8
ignore sphinx build time file
TomDonoghue Apr 30, 2024
42abfed
fix issue of not passing freq_range through in BaseModel
TomDonoghue Apr 30, 2024
944b803
update changelog for 2.0
TomDonoghue May 4, 2024
1b10104
fix line
TomDonoghue May 4, 2024
a7ed4d9
update actions
TomDonoghue Jun 8, 2024
4cea065
Merge pull request #325 from fooof-tools/acts
TomDonoghue Jun 8, 2024
3599dbc
Merge branch 'main' into basemodel
TomDonoghue Aug 3, 2024
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
8 changes: 5 additions & 3 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ jobs:
python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand All @@ -37,4 +37,6 @@ jobs:
run: |
pytest --doctest-modules --ignore=$MODULE_NAME/tests $MODULE_NAME
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,4 @@ doc/auto_examples/*
doc/auto_tutorials/*
doc/auto_motivations/*
doc/generated/*
doc/sg_execution_times.rst
3 changes: 3 additions & 0 deletions doc/_static/my-styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.navbar-form {
margin-right: -75px;
}
88 changes: 88 additions & 0 deletions doc/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,94 @@ This page primarily notes changes for major version updates.
For notes on the specific updates for minor releases, see the
`release page <https://github.com/fooof-tools/fooof/releases>`_.

2.0.0 (in development)
----------------------

WARNING: the specparam 2.0 release is not yet a a stable release, and may still change!

Note that the new `specparam 2.0` version includes a significant refactoring or the internals of the module, and broad changes to the naming of entities (including classes, functions, methods, etc) across the module. As such, this update is a major, breaking change to the module (see below for updates). See below for notes on the major updates, and relationships to previous versions of the module.

Key Updates
~~~~~~~~~~~

The `specparam` 2.0 version contains the following notable feature updates:

- an extension of the module to support time-resolved and event-related analyses

- these analyses are now supported by the ``SpectralTimeModel`` and ``SpectralTimeEventModel`` objects

- an update to procedures for functions that are fit to power spectra

- these updates allow for flexibly using and defining different fit functions [WIP]

- an update to procedures for defining and applying spectral fitting algorithms

- these updates allow for choosing, tuning, and changing the fitting algorithm that is applied [WIP]

- extensions and updates to the module

- this includes updates to parameter management, goodness-of-fit evaluations, visualizations, and more

The above notes the major changes and updates to the module - for further details on the changes, see the
`release page <https://github.com/fooof-tools/fooof/releases>`_.

Relationship to fooof
~~~~~~~~~~~~~~~~~~~~~

As compared to the fooof releases, the specparam module is an extension of the spectral parameterization approach, including the same functionality as the original module, with significant extensions. This means that, for example, if choosing the same fit functions and algorithms in specparam 2.0 as are used in fooof 1.X, the results should be functionally identical.

Notably, there are no changes to the default settings and models in specparam 2.0, such that fitting a spectral model with the default settings in specparam should provide the same as doing the equivalent in fooof 1.X.

Naming Updates
~~~~~~~~~~~~~~

The following functions, objects, and attributes have changed name in the new version:

Model Objects:

- FOOOF -> SpectralModel
- FOOOFGroup -> SpectralGroupModel

Model Object methods & attributes:

- FOOOF.fooofed_spectrum\_ -> SpectralModel.modeled_spectrum\_
- FOOOFGroup.get_fooof -> SpectralGroupModel.get_model

Data objects:

- FOOOFResults -> FitResults
- FOOOFSettings -> ModelSettings
- FOOOFMetaData -> SpectrumMetaData

Functions:

- combine_fooofs -> combine_model_objs
- compare_info -> compare_model_objs
- average_fg -> average_group
- fit_fooof_3d -> fit_models_3d

- get_band_peak_fm -> get_band_peak
- get_band_peak_fg -> get_band_peak_group
- get_band_peak -> get_band_peak_arr
- get_band_peak_group -> get_band_peak_group_arr

- compute_pointwise_error_fm -> compute_pointwise_error
- compute_pointwise_error_fg -> compute_pointwise_error_group
- compute_pointwise_error -> compute_pointwise_error_arr

- save_fm -> save_model
- save_fg -> save_group

- fetch_fooof_data -> fetch_example_data
- load_fooof_data -> load_example_data

- gen_power_spectrum -> sim_power_spectrum
- gen_group_power_spectra -> sim_group_power_spectra

Function inputs:

- fooof_obj -> model_obj

1.1.0
-----

Expand Down
6 changes: 6 additions & 0 deletions doc/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,12 @@
html_copy_source = False
html_show_sourcelink = False

# Add link to custom css
html_static_path = ["_static"]

# Add function for stylesheets path
def setup(app):
app.add_css_file("my-styles.css")

# -- Extension configuration -------------------------------------------------

Expand Down
4 changes: 2 additions & 2 deletions examples/analyses/plot_dev_demo.py
Original file line number Diff line number Diff line change
Expand Up @@ -498,8 +498,8 @@
###################################################################################################

# Initialize model objects for spectral parameterization, with some settings
fg1 = SpectralGroupModel(*settings1)
fg2 = SpectralGroupModel(*settings2)
fg1 = SpectralGroupModel(**settings1._asdict())
fg2 = SpectralGroupModel(**settings2._asdict())

###################################################################################################
#
Expand Down
119 changes: 119 additions & 0 deletions specparam/core/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,125 @@ def save_event(event, file_name, file_path=None, append=False,
save_settings=save_settings, save_data=save_data)


def load_model(file_name, file_path=None, regenerate=True, model=None):
"""Load a SpectralModel object.

Parameters
----------
Parameters
----------
file_name : str
File(s) to load data from.
file_path : str, optional
Path to directory to load from. If None, loads from current directory.
regenerate : bool, optional, default: True
Whether to regenerate the model fit from the loaded data, if data is available.
model : SpectralModel
xx

Returns
-------
model : SpectralModel
Loaded model object with data from file.
"""

# Check for model object, import (avoid circular) and initialize if not
if not model:
from specparam.objs import SpectralModel
model = SpectralModel()

model.load(file_name, file_path, regenerate)

return model


def load_group(file_name, file_path=None, group=None):
"""Load a SpectralGroupModel object.

Parameters
----------
file_name : str
File(s) to load data from.
file_path : str, optional
Path to directory to load from. If None, loads from current directory.
group : SpectralGroupModel
xx

Returns
-------
group : SpectralGroupModel
Loaded model object with data from file.
"""

# Check for model object, import (avoid circular) and initialize if not
if not group:
from specparam.objs import SpectralGroupModel
group = SpectralGroupModel()

group.load(file_name, file_path)

return group


def load_time(file_name, file_path=None, peak_org=None, time=None):
"""Load a SpectralTimeModel object.

Parameters
----------
file_name : str
File(s) to load data from.
file_path : str, optional
Path to directory to load from. If None, loads from current directory.
peak_org : int or Bands, optional
How to organize peaks.
If int, extracts the first n peaks.
If Bands, extracts peaks based on band definitions.

Returns
-------
time : SpectralTimeModel
Loaded model object with data from file.
"""

# Check for model object, import (avoid circular) and initialize if not
if not time:
from specparam.objs import SpectralTimeModel
time = SpectralTimeModel()

time.load(file_name, file_path, peak_org)

return time

def load_event(file_name, file_path=None, peak_org=None, event=None):
"""Load a SpectralTimeEventModel object.

Parameters
----------
file_name : str
File(s) to load data from.
file_path : str, optional
Path to directory to load from. If None, loads from current directory.
peak_org : int or Bands, optional
How to organize peaks.
If int, extracts the first n peaks.
If Bands, extracts peaks based on band definitions.

Returns
-------
event : SpectralTimeEventModel
Loaded model object with data from file.
"""

# Check for model object, import (avoid circular) and initialize if not
if not event:
from specparam.objs import SpectralTimeEventModel
event = SpectralTimeEventModel()

event.load(file_name, file_path, peak_org)

return event


def load_json(file_name, file_path):
"""Load json file.

Expand Down
2 changes: 1 addition & 1 deletion specparam/data/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def get_model_params(fit_results, name, col=None):
if name in ['aperiodic', 'peak', 'gaussian']:
name = name + '_params'

# Extract the request data field from object
# Extract the requested data field from object
out = getattr(fit_results, name)

# Periodic values can be empty arrays and if so, replace with NaN array
Expand Down
2 changes: 1 addition & 1 deletion specparam/objs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Objects sub-module, for model objects and functions that operate on model objects."""

from .fit import SpectralModel
from .model import SpectralModel
from .group import SpectralGroupModel
from .time import SpectralTimeModel
from .event import SpectralTimeEventModel
Expand Down
Loading