efel/settings.py
"""efel Settings class""" """Copyright (c) 2015, EPFL/Blue Brain Project This file is part of eFEL <https://github.com/BlueBrain/eFEL> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3.0 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.""" from dataclasses import dataclass, fields, asdictfrom pathlib import Pathfrom typing import Unionfrom typing_extensions import deprecatedimport logging logger = logging.getLogger(__name__) @dataclassclass Settings: """eFEL settings class. Attributes: Threshold (float): Spike detection threshold (default: -20.0). DerivativeThreshold (float): Threshold value for derivative calculations (default: 10.0). DownDerivativeThreshold (float): Threshold value for downward derivative calculations (default: -12.0). dependencyfile_path (str): Path to the dependency file (default: 'DependencyV5.txt'). spike_skipf (float): Fraction of spikes to skip (default: 0.1). max_spike_skip (int): Maximum number of spikes to skip (default: 2). interp_step (float): Interpolation step (default: 0.1). burst_factor (float): Burst factor (default: 1.5). strict_burst_factor (float): Strict burst factor (default: 2.0). voltage_base_start_perc (float): Voltage base start percentage (default: 0.9). voltage_base_end_perc (float): Voltage base end percentage (default: 1.0). current_base_start_perc (float): Current base start percentage (default: 0.9). current_base_end_perc (float): Current base end percentage (default: 1.0). rise_start_perc (float): Rise start percentage (default: 0.0). rise_end_perc (float): Rise end percentage (default: 1.0). initial_perc (float): Initial percentage (default: 0.1). min_spike_height (float): Minimum spike height (default: 20.0). strict_stiminterval (bool): Strict stimulus interval (default: False). initburst_freq_threshold (int): Initial burst frequency threshold (default: 50). initburst_sahp_start (int): Initial burst SAHP start (default: 5). initburst_sahp_end (int): Initial burst SAHP end (default: 100). DerivativeWindow (int): Derivative window (default: 3). voltage_base_mode (str): Voltage base mode (default: "mean"). current_base_mode (str): Current base mode (default: "mean"). precision_threshold (float): Precision threshold (default: 1e-10). sahp_start (float): SAHP start (default: 5.0). ignore_first_ISI (bool): Ignore first ISI (default: True). impedance_max_freq (float): Impedance maximum frequency (default: 50.0). inactivation_tc_end_skip (int): number of data points to skip before stim end for inactivation_time_constant feature (default: 10). """ Threshold: float = -20.0 DerivativeThreshold: float = 10.0 DownDerivativeThreshold: float = -12.0 dependencyfile_path: str = str( Path(__file__).parent.absolute() / "DependencyV5.txt" ) spike_skipf: float = 0.1 max_spike_skip: int = 2 interp_step: float = 0.1 burst_factor: float = 1.5 strict_burst_factor: float = 2.0 voltage_base_start_perc: float = 0.9 voltage_base_end_perc: float = 1.0 current_base_start_perc: float = 0.9 current_base_end_perc: float = 1.0 rise_start_perc: float = 0.0 rise_end_perc: float = 1.0 initial_perc: float = 0.1 min_spike_height: float = 20.0 strict_stiminterval: bool = False initburst_freq_threshold: int = 50 initburst_sahp_start: int = 5 initburst_sahp_end: int = 100 DerivativeWindow: int = 3 voltage_base_mode: str = "mean" current_base_mode: str = "mean" precision_threshold: float = 1e-10 sahp_start: float = 5.0 ignore_first_ISI: bool = True impedance_max_freq: float = 50.0 AP_phaseslope_range: int = 2 inactivation_tc_end_skip: int = 10 Function `set_setting` has a Cognitive Complexity of 12 (exceeds 5 allowed). Consider refactoring. def set_setting(self, setting_name: str, new_value: Union[int, float, str, bool]) -> None: """Set a certain setting to a new value. Args: setting_name (str): Name of the setting to be modified. new_value (Union[int, float, str, bool]): New value for the setting. Raises: ValueError: If the value is of the wrong type. FileNotFoundError: If the path to the dependency file does not exist (for 'dependencyfile_path' setting). """ if hasattr(self, setting_name): expected_types = {f.name: f.type for f in fields(self)} expected_type = expected_types.get(setting_name) if expected_type is None: raise TypeError(f"type not found for setting '{setting_name}'") try: converted_value = expected_type(new_value) if not isinstance(new_value, expected_type): log_message = ( "Value '%s' of type '%s' for setting '%s' " "has been converted to '%s' of type '%s'." ) % ( new_value, type(new_value).__name__, setting_name, converted_value, expected_type.__name__ ) if expected_type is int and isinstance(new_value, float) and \ new_value != converted_value: logger.warning(log_message) else: logger.debug(log_message) except (ValueError, TypeError): raise ValueError(f"Invalid value for setting '{setting_name}'. " f"Expected type: {expected_type.__name__}.") else: logger.debug("Setting '%s' not found in settings. " "Adding it as a new setting.", setting_name) converted_value = new_value if setting_name == "dependencyfile_path": path = Path(str(converted_value)) if not path.exists(): raise FileNotFoundError(f"Path to dependency file {converted_value}" "doesn't exist") setattr(self, setting_name, converted_value) def reset_to_default(self): """Reset settings to their default values""" default_settings = Settings() for field in default_settings.__dataclass_fields__: setattr(self, field, getattr(default_settings, field)) def __str__(self): attributes = asdict(self) return '\n'.join([f"{key}: {value}" for key, value in attributes.items()])