Skip to content

[ENH] - Update Modes management to use sub-object attributes rather than inheritance #354

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

Merged
merged 28 commits into from
Mar 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
83f3e18
move settings from Results -> Algorithm
TomDonoghue Mar 22, 2025
26f22da
move algo settings to own file
TomDonoghue Mar 22, 2025
aea71d5
move verbose out from results (to base)
TomDonoghue Mar 22, 2025
6d49cc6
add Modes object
TomDonoghue Mar 22, 2025
f74b1de
lints & fixes
TomDonoghue Mar 22, 2025
bf1093d
make check_mode own func
TomDonoghue Mar 22, 2025
39a95c9
use Modes
TomDonoghue Mar 22, 2025
ef8a0d6
move to using Data object attribute
TomDonoghue Mar 22, 2025
2ade775
drop core test folder
TomDonoghue Mar 22, 2025
acfe049
move Results to attribute
TomDonoghue Mar 23, 2025
84292b7
add get_modes
TomDonoghue Mar 23, 2025
9511692
use get_modes
TomDonoghue Mar 23, 2025
97f08b1
add stricter load tests - check obj dirs
TomDonoghue Mar 23, 2025
c3ace21
rename conflicting get_model -> get_component
TomDonoghue Mar 23, 2025
d71c64c
add metrics
TomDonoghue Mar 23, 2025
eb36957
update metrics
TomDonoghue Mar 23, 2025
3f0d5df
remove metrics from results
TomDonoghue Mar 23, 2025
9e55b9f
add Metrics to base
TomDonoghue Mar 23, 2025
6eea9d4
interim update: alias metrics to results
TomDonoghue Mar 23, 2025
748d891
add indexing to Metrics
TomDonoghue Mar 23, 2025
9498554
misc updates for metrics
TomDonoghue Mar 23, 2025
dc82a14
move Algorithm to it's own attribute
TomDonoghue Mar 24, 2025
1541b77
lints
TomDonoghue Mar 24, 2025
665a983
udpate / consolidate for getting initialized object
TomDonoghue Mar 24, 2025
fc906d3
add initialize_model_from_source util func
TomDonoghue Mar 24, 2025
59df03a
use initialize model from source func
TomDonoghue Mar 24, 2025
229e2ab
update get_modes to use data object
TomDonoghue Mar 24, 2025
32cf001
update initialize from to copy modes
TomDonoghue Mar 24, 2025
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
168 changes: 81 additions & 87 deletions specparam/algorithms/algorithm.py
Original file line number Diff line number Diff line change
@@ -1,89 +1,11 @@
"""Define original spectral fitting algorithm object."""
"""Define object to manage algoirthm implementations."""

from specparam.data import ModelSettings
from specparam.modes.items import OBJ_DESC

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

class SettingsDefinition():
"""Defines a set of algorithm settings.

Parameters
----------
settings : dict
Settings definition.
Each key should be a str name of a setting.
Each value should be a dictionary with keys 'type' and 'description', with str values.
"""

def __init__(self, settings):
"""Initialize settings definition."""

self._settings = settings


def _get_settings_subdict(self, field):
"""Helper function to select from settings dictionary."""

return {label : self._settings[label][field] for label in self._settings.keys()}


@property
def names(self):
"""Make property alias for setting names."""

return list(self._settings.keys())


@property
def types(self):
"""Make property alias for setting types."""

return self._get_settings_subdict('type')


@property
def descriptions(self):
"""Make property alias for setting descriptions."""

return self._get_settings_subdict('description')


def make_setting_str(self, name):
"""Make a setting docstring string.

Parameters
----------
name : str
Setting name to make string for.

Returns
-------
str
Setting docstring string.
"""

setting_str = '' + \
' ' + name + ' : ' + self.types[name] + '\n' \
' ' + self.descriptions[name]

return setting_str


def make_docstring(self):
"""Make docstring for all settings.

Returns
-------
str
Docstring for all settings.
"""

pieces = [self.make_setting_str(name) for name in self.names]
pieces = [' Parameters', ' ----------'] + pieces
docstring = '\n'.join(pieces)

return docstring


class AlgorithmDefinition():
"""Defines an algorithm definition description.

Expand Down Expand Up @@ -123,17 +45,89 @@ class Algorithm():
Algorithm information.
"""

def __init__(self, name, description, settings):
def __init__(self, name, description, settings, debug=False):
"""Initialize Algorithm object."""

self.algorithm = AlgorithmDefinition(name, description, settings)

self.set_debug(debug)


def _fit_prechecks():
def _fit_prechecks(self):
"""Prechecks to run before the fit function - if are some, overload this function."""
pass


def _fit():
def _fit(self):
"""Required fit function, to be overloaded."""
pass


def add_settings(self, settings):
"""Add settings into object from a ModelSettings object.

Parameters
----------
settings : ModelSettings
A data object containing the settings for a power spectrum model.
"""

for setting in OBJ_DESC['settings']:
setattr(self, setting, getattr(settings, setting))

self._check_loaded_settings(settings._asdict())


def get_settings(self):
"""Return user defined settings of the current object.

Returns
-------
ModelSettings
Object containing the settings from the current object.
"""

return ModelSettings(**{key : getattr(self, key) \
for key in OBJ_DESC['settings']})


def get_debug(self):
"""Return object debug status."""

return self._debug


def set_debug(self, debug):
"""Set debug state, which controls if an error is raised if model fitting is unsuccessful.

Parameters
----------
debug : bool
Whether to run in debug state.
"""

self._debug = debug


def _check_loaded_settings(self, data):
"""Check if settings added, and update the object as needed.

Parameters
----------
data : dict
A dictionary of data that has been added to the object.
"""

# If settings not loaded from file, clear from object, so that default
# settings, which are potentially wrong for loaded data, aren't kept
if not set(OBJ_DESC['settings']).issubset(set(data.keys())):

# Reset all public settings to None
for setting in OBJ_DESC['settings']:
setattr(self, setting, None)

# Reset internal settings so that they are consistent with what was loaded
# Note that this will set internal settings to None, if public settings unavailable
self._reset_internal_settings()


def _reset_internal_settings(self):
""""Can be overloaded if any resetting needed for internal settings."""
84 changes: 84 additions & 0 deletions specparam/algorithms/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
"""Define an algorithm settings object and related functionality."""

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

class SettingsDefinition():
"""Defines a set of algorithm settings.

Parameters
----------
settings : dict
Settings definition.
Each key should be a str name of a setting.
Each value should be a dictionary with keys 'type' and 'description', with str values.
"""

def __init__(self, settings):
"""Initialize settings definition."""

self._settings = settings


def _get_settings_subdict(self, field):
"""Helper function to select from settings dictionary."""

return {label : self._settings[label][field] for label in self._settings.keys()}


@property
def names(self):
"""Make property alias for setting names."""

return list(self._settings.keys())


@property
def types(self):
"""Make property alias for setting types."""

return self._get_settings_subdict('type')


@property
def descriptions(self):
"""Make property alias for setting descriptions."""

return self._get_settings_subdict('description')


def make_setting_str(self, name):
"""Make a setting docstring string.

Parameters
----------
name : str
Setting name to make string for.

Returns
-------
str
Setting docstring string.
"""

setting_str = '' + \
' ' + name + ' : ' + self.types[name] + '\n' \
' ' + self.descriptions[name]

return setting_str


def make_docstring(self):
"""Make docstring for all settings.

Returns
-------
str
Docstring for all settings.
"""

pieces = [self.make_setting_str(name) for name in self.names]
pieces = [' Parameters', ' ----------'] + pieces
docstring = '\n'.join(pieces)

return docstring
Loading