diff --git a/python/sdist/amici/adapters/fiddy.py b/python/sdist/amici/adapters/fiddy.py index 573361bbba..d91841ff8d 100644 --- a/python/sdist/amici/adapters/fiddy.py +++ b/python/sdist/amici/adapters/fiddy.py @@ -20,7 +20,6 @@ from fiddy import CachedFunction, Type, fiddy_array from petab.v1.C import LIN, LOG, LOG10 -from amici.importers.petab.v1.parameter_mapping import create_parameter_mapping from amici.sim.sundials import ( AmiciExpData, AmiciModel, @@ -31,6 +30,9 @@ run_simulation, ) from amici.sim.sundials.petab.v1 import LLH, SLLH, create_edatas +from amici.sim.sundials.petab.v1._parameter_mapping import ( + create_parameter_mapping, +) if TYPE_CHECKING: from amici.sim.sundials.petab import PetabSimulationResult, PetabSimulator diff --git a/python/sdist/amici/importers/petab/_cli/import_petab.py b/python/sdist/amici/importers/petab/_cli/import_petab.py index 5cd91591c5..ea4fe430d5 100644 --- a/python/sdist/amici/importers/petab/_cli/import_petab.py +++ b/python/sdist/amici/importers/petab/_cli/import_petab.py @@ -1,7 +1,7 @@ import argparse import petab.v1 as petab -from amici.importers.petab.v1.petab_import import import_model_sbml +from amici.importers.petab.v1._petab_import import import_model_sbml def _parse_cli_args(): diff --git a/python/sdist/amici/importers/petab/_petab_importer.py b/python/sdist/amici/importers/petab/_petab_importer.py index 9f1c056e80..c5c2853bbd 100644 --- a/python/sdist/amici/importers/petab/_petab_importer.py +++ b/python/sdist/amici/importers/petab/_petab_importer.py @@ -26,7 +26,7 @@ from amici.logging import get_logger from amici.sim.jax.petab import JAXProblem -from .v1.sbml_import import _add_global_parameter +from .v1._sbml_import import _add_global_parameter if TYPE_CHECKING: import pysb @@ -329,7 +329,7 @@ def _do_import_sbml(self): for change in self.petab_problem[condition_id].changes } - from .v1.sbml_import import show_model_info + from .v1._sbml_import import show_model_info show_model_info(self.petab_problem.model.sbml_model) sbml_importer = amici.SbmlImporter( diff --git a/python/sdist/amici/importers/petab/v1/__init__.py b/python/sdist/amici/importers/petab/v1/__init__.py index 3844f08735..daeaa86fed 100644 --- a/python/sdist/amici/importers/petab/v1/__init__.py +++ b/python/sdist/amici/importers/petab/v1/__init__.py @@ -4,7 +4,7 @@ # preequilibration PREEQ_INDICATOR_ID = "preequilibration_indicator" -from .petab_import import import_petab_problem +from ._petab_import import import_petab_problem __all__ = [ "import_petab_problem", diff --git a/python/sdist/amici/importers/petab/v1/import_helpers.py b/python/sdist/amici/importers/petab/v1/_import_helpers.py similarity index 100% rename from python/sdist/amici/importers/petab/v1/import_helpers.py rename to python/sdist/amici/importers/petab/v1/_import_helpers.py diff --git a/python/sdist/amici/importers/petab/v1/petab_import.py b/python/sdist/amici/importers/petab/v1/_petab_import.py similarity index 98% rename from python/sdist/amici/importers/petab/v1/petab_import.py rename to python/sdist/amici/importers/petab/v1/_petab_import.py index d15d23a50f..82c74aff24 100644 --- a/python/sdist/amici/importers/petab/v1/petab_import.py +++ b/python/sdist/amici/importers/petab/v1/_petab_import.py @@ -18,16 +18,16 @@ import amici from amici.logging import get_logger -from .import_helpers import ( +from ._import_helpers import ( _can_import_model, _create_model_name, _get_package_name_and_path, check_model, ) -from .sbml_import import import_model_sbml +from ._sbml_import import import_model_sbml try: - from .pysb_import import import_model_pysb + from ._pysb_import import import_model_pysb except ModuleNotFoundError: # pysb not available import_model_pysb = None diff --git a/python/sdist/amici/importers/petab/v1/pysb_import.py b/python/sdist/amici/importers/petab/v1/_pysb_import.py similarity index 99% rename from python/sdist/amici/importers/petab/v1/pysb_import.py rename to python/sdist/amici/importers/petab/v1/_pysb_import.py index 1ec213eec9..82438103d1 100644 --- a/python/sdist/amici/importers/petab/v1/pysb_import.py +++ b/python/sdist/amici/importers/petab/v1/_pysb_import.py @@ -24,11 +24,11 @@ from amici.logging import get_logger, log_execution_time, set_log_level from . import PREEQ_INDICATOR_ID -from .import_helpers import ( +from ._import_helpers import ( get_fixed_parameters, petab_noise_distribution_to_amici, ) -from .util import get_states_in_condition_table +from ._util import get_states_in_condition_table logger = get_logger(__name__, logging.WARNING) diff --git a/python/sdist/amici/importers/petab/v1/sbml_import.py b/python/sdist/amici/importers/petab/v1/_sbml_import.py similarity index 99% rename from python/sdist/amici/importers/petab/v1/sbml_import.py rename to python/sdist/amici/importers/petab/v1/_sbml_import.py index f1953f9592..88add7c1cf 100644 --- a/python/sdist/amici/importers/petab/v1/sbml_import.py +++ b/python/sdist/amici/importers/petab/v1/_sbml_import.py @@ -16,12 +16,12 @@ from amici.logging import log_execution_time, set_log_level from . import PREEQ_INDICATOR_ID -from .import_helpers import ( +from ._import_helpers import ( check_model, get_fixed_parameters, get_observation_model, ) -from .util import get_states_in_condition_table +from ._util import get_states_in_condition_table logger = logging.getLogger(__name__) diff --git a/python/sdist/amici/importers/petab/v1/util.py b/python/sdist/amici/importers/petab/v1/_util.py similarity index 100% rename from python/sdist/amici/importers/petab/v1/util.py rename to python/sdist/amici/importers/petab/v1/_util.py diff --git a/python/sdist/amici/sim/__init__.py b/python/sdist/amici/sim/__init__.py index ac1dee3186..7683c431b7 100644 --- a/python/sdist/amici/sim/__init__.py +++ b/python/sdist/amici/sim/__init__.py @@ -1 +1,3 @@ """Functionality for simulating AMICI models.""" + +from __future__ import annotations diff --git a/python/sdist/amici/sim/_parameter_mapping.py b/python/sdist/amici/sim/_parameter_mapping.py new file mode 100644 index 0000000000..20b325c191 --- /dev/null +++ b/python/sdist/amici/sim/_parameter_mapping.py @@ -0,0 +1,148 @@ +"""Parameter mapping for conditions. + +Only code that is independent of JAX or SUNDIALS objects. +""" + +from __future__ import annotations + +import numbers +from collections.abc import Sequence +from itertools import chain + +from petab.v1 import LIN + +SingleParameterMapping = dict[str, numbers.Number | str] +SingleScaleMapping = dict[str, str] + + +class ParameterMappingForCondition: + """Parameter mapping for condition. + + Contains mappings for free parameters, fixed parameters, and fixed + pre-equilibration parameters, both for parameters and scales. + + In the scale mappings, for each simulation parameter, the scale + on which the value is passed (and potentially gradients are to be + returned) is given. In the parameter mappings, for each simulation + parameter a corresponding optimization parameter (or a numeric value) + is given. + + If a mapping is not passed, the parameter mappings are assumed to be empty, + and if a scale mapping is not passed, all scales are set to linear. + + :param map_sim_var: + Mapping for free simulation parameters. + :param scale_map_sim_var: + Scales for free simulation parameters. + :param map_preeq_fix: + Mapping for fixed pre-equilibration parameters. + :param scale_map_preeq_fix: + Scales for fixed pre-equilibration parameters. + :param map_sim_fix: + Mapping for fixed simulation parameters. + :param scale_map_sim_fix: + Scales for fixed simulation parameters. + """ + + def __init__( + self, + map_sim_var: SingleParameterMapping = None, + scale_map_sim_var: SingleScaleMapping = None, + map_preeq_fix: SingleParameterMapping = None, + scale_map_preeq_fix: SingleScaleMapping = None, + map_sim_fix: SingleParameterMapping = None, + scale_map_sim_fix: SingleScaleMapping = None, + ): + if map_sim_var is None: + map_sim_var = {} + self.map_sim_var = map_sim_var + + if scale_map_sim_var is None: + scale_map_sim_var = {key: LIN for key in map_sim_var} + self.scale_map_sim_var = scale_map_sim_var + + if map_preeq_fix is None: + map_preeq_fix = {} + self.map_preeq_fix = map_preeq_fix + + if scale_map_preeq_fix is None: + scale_map_preeq_fix = {key: LIN for key in map_preeq_fix} + self.scale_map_preeq_fix = scale_map_preeq_fix + + if map_sim_fix is None: + map_sim_fix = {} + self.map_sim_fix = map_sim_fix + + if scale_map_sim_fix is None: + scale_map_sim_fix = {key: LIN for key in map_sim_fix} + self.scale_map_sim_fix = scale_map_sim_fix + + def __repr__(self): + return ( + f"{self.__class__.__name__}(" + f"map_sim_var={repr(self.map_sim_var)}," + f"scale_map_sim_var={repr(self.scale_map_sim_var)}," + f"map_preeq_fix={repr(self.map_preeq_fix)}," + f"scale_map_preeq_fix={repr(self.scale_map_preeq_fix)}," + f"map_sim_fix={repr(self.map_sim_fix)}," + f"scale_map_sim_fix={repr(self.scale_map_sim_fix)})" + ) + + @property + def free_symbols(self) -> set[str]: + """Get IDs of all (symbolic) parameters present in this mapping""" + return { + p + for p in chain( + self.map_sim_var.values(), + self.map_preeq_fix.values(), + self.map_sim_fix.values(), + ) + if isinstance(p, str) + } + + +class ParameterMapping(Sequence): + r"""Parameter mapping for multiple conditions. + + This can be used like a list of :class:`ParameterMappingForCondition`\ s. + + :param parameter_mappings: + List of parameter mappings for specific conditions. + """ + + def __init__( + self, parameter_mappings: list[ParameterMappingForCondition] = None + ): + super().__init__() + if parameter_mappings is None: + parameter_mappings = [] + self.parameter_mappings = parameter_mappings + + def __iter__(self): + yield from self.parameter_mappings + + def __getitem__( + self, item + ) -> ParameterMapping | ParameterMappingForCondition: + result = self.parameter_mappings[item] + if isinstance(result, ParameterMappingForCondition): + return result + return ParameterMapping(result) + + def __len__(self): + return len(self.parameter_mappings) + + def append( + self, parameter_mapping_for_condition: ParameterMappingForCondition + ): + """Append a condition-specific parameter mapping.""" + self.parameter_mappings.append(parameter_mapping_for_condition) + + def __repr__(self): + return f"{self.__class__.__name__}({repr(self.parameter_mappings)})" + + @property + def free_symbols(self) -> set[str]: + """Get IDs of all (symbolic) parameters present in this mapping""" + return set.union(*(mapping.free_symbols for mapping in self)) diff --git a/python/sdist/amici/sim/jax/petab.py b/python/sdist/amici/sim/jax/petab.py index 7a214af567..19ee7e681c 100644 --- a/python/sdist/amici/sim/jax/petab.py +++ b/python/sdist/amici/sim/jax/petab.py @@ -22,10 +22,8 @@ from optimistix import AbstractRootFinder from amici import _module_from_path -from amici.importers.petab.v1.parameter_mapping import ( - ParameterMappingForCondition, -) from amici.logging import get_logger +from amici.sim._parameter_mapping import ParameterMappingForCondition from amici.sim.jax.model import JAXModel, ReturnValue DEFAULT_CONTROLLER_SETTINGS = { diff --git a/python/sdist/amici/sim/sundials/petab/v1/__init__.py b/python/sdist/amici/sim/sundials/petab/v1/__init__.py index fb596f9f2b..519508dcae 100644 --- a/python/sdist/amici/sim/sundials/petab/v1/__init__.py +++ b/python/sdist/amici/sim/sundials/petab/v1/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from ._conditions import ( create_edatas, create_parameterized_edatas, diff --git a/python/sdist/amici/sim/sundials/petab/v1/_conditions.py b/python/sdist/amici/sim/sundials/petab/v1/_conditions.py index 15fa640143..766867c450 100644 --- a/python/sdist/amici/sim/sundials/petab/v1/_conditions.py +++ b/python/sdist/amici/sim/sundials/petab/v1/_conditions.py @@ -19,19 +19,21 @@ TIME, ) -from amici.importers.petab.v1.parameter_mapping import ( +from amici.importers.petab.v1._util import get_states_in_condition_table +from amici.sim._parameter_mapping import ( ParameterMapping, ParameterMappingForCondition, - petab_to_amici_scale, - scale_parameters_dict, - unscale_parameters_dict, ) -from amici.importers.petab.v1.util import get_states_in_condition_table from amici.sim.sundials import ( AmiciModel, ExpData, parameter_scaling_from_int_vector, ) +from amici.sim.sundials.petab.v1._parameter_scaling import ( + petab_to_amici_scale, + scale_parameters_dict, + unscale_parameters_dict, +) logger = logging.getLogger(__name__) @@ -283,7 +285,7 @@ def create_parameterized_edatas( # Get parameter mapping if parameter_mapping is None: - from amici.importers.petab.v1.parameter_mapping import ( + from amici.sim.sundials.petab.v1._parameter_mapping import ( create_parameter_mapping, ) diff --git a/python/sdist/amici/importers/petab/v1/parameter_mapping.py b/python/sdist/amici/sim/sundials/petab/v1/_parameter_mapping.py similarity index 70% rename from python/sdist/amici/importers/petab/v1/parameter_mapping.py rename to python/sdist/amici/sim/sundials/petab/v1/_parameter_mapping.py index 1738f15d1c..53fdae2926 100644 --- a/python/sdist/amici/importers/petab/v1/parameter_mapping.py +++ b/python/sdist/amici/sim/sundials/petab/v1/_parameter_mapping.py @@ -1,5 +1,3 @@ -from __future__ import annotations - """ Parameter mapping ----------------- @@ -16,18 +14,16 @@ the mapping is automatized. """ +from __future__ import annotations + import logging -import numbers import re -from collections.abc import Collection, Iterator, Sequence -from itertools import chain +from collections.abc import Collection, Iterator from typing import Any -import numpy as np import pandas as pd import petab.v1 as petab import sympy as sp -from petab.v1.C import * # noqa: F403 from petab.v1.C import ( ESTIMATE, LIN, @@ -39,11 +35,14 @@ from petab.v1.models import MODEL_TYPE_PYSB, MODEL_TYPE_SBML from sympy.abc import _clash +from amici.importers.petab.v1 import PREEQ_INDICATOR_ID +from amici.importers.petab.v1._util import get_states_in_condition_table from amici.importers.sbml import get_species_initial -from amici.sim.sundials import AmiciModel, ParameterScaling - -from . import PREEQ_INDICATOR_ID -from .util import get_states_in_condition_table +from amici.sim._parameter_mapping import ( + ParameterMapping, + ParameterMappingForCondition, +) +from amici.sim.sundials import AmiciModel try: import pysb @@ -53,258 +52,6 @@ logger = logging.getLogger(__name__) -SingleParameterMapping = dict[str, numbers.Number | str] -SingleScaleMapping = dict[str, str] - - -class ParameterMappingForCondition: - """Parameter mapping for condition. - - Contains mappings for free parameters, fixed parameters, and fixed - pre-equilibration parameters, both for parameters and scales. - - In the scale mappings, for each simulation parameter, the scale - on which the value is passed (and potentially gradients are to be - returned) is given. In the parameter mappings, for each simulation - parameter a corresponding optimization parameter (or a numeric value) - is given. - - If a mapping is not passed, the parameter mappings are assumed to be empty, - and if a scale mapping is not passed, all scales are set to linear. - - :param map_sim_var: - Mapping for free simulation parameters. - :param scale_map_sim_var: - Scales for free simulation parameters. - :param map_preeq_fix: - Mapping for fixed pre-equilibration parameters. - :param scale_map_preeq_fix: - Scales for fixed pre-equilibration parameters. - :param map_sim_fix: - Mapping for fixed simulation parameters. - :param scale_map_sim_fix: - Scales for fixed simulation parameters. - """ - - def __init__( - self, - map_sim_var: SingleParameterMapping = None, - scale_map_sim_var: SingleScaleMapping = None, - map_preeq_fix: SingleParameterMapping = None, - scale_map_preeq_fix: SingleScaleMapping = None, - map_sim_fix: SingleParameterMapping = None, - scale_map_sim_fix: SingleScaleMapping = None, - ): - if map_sim_var is None: - map_sim_var = {} - self.map_sim_var = map_sim_var - - if scale_map_sim_var is None: - scale_map_sim_var = {key: LIN for key in map_sim_var} - self.scale_map_sim_var = scale_map_sim_var - - if map_preeq_fix is None: - map_preeq_fix = {} - self.map_preeq_fix = map_preeq_fix - - if scale_map_preeq_fix is None: - scale_map_preeq_fix = {key: LIN for key in map_preeq_fix} - self.scale_map_preeq_fix = scale_map_preeq_fix - - if map_sim_fix is None: - map_sim_fix = {} - self.map_sim_fix = map_sim_fix - - if scale_map_sim_fix is None: - scale_map_sim_fix = {key: LIN for key in map_sim_fix} - self.scale_map_sim_fix = scale_map_sim_fix - - def __repr__(self): - return ( - f"{self.__class__.__name__}(" - f"map_sim_var={repr(self.map_sim_var)}," - f"scale_map_sim_var={repr(self.scale_map_sim_var)}," - f"map_preeq_fix={repr(self.map_preeq_fix)}," - f"scale_map_preeq_fix={repr(self.scale_map_preeq_fix)}," - f"map_sim_fix={repr(self.map_sim_fix)}," - f"scale_map_sim_fix={repr(self.scale_map_sim_fix)})" - ) - - @property - def free_symbols(self) -> set[str]: - """Get IDs of all (symbolic) parameters present in this mapping""" - return { - p - for p in chain( - self.map_sim_var.values(), - self.map_preeq_fix.values(), - self.map_sim_fix.values(), - ) - if isinstance(p, str) - } - - -class ParameterMapping(Sequence): - r"""Parameter mapping for multiple conditions. - - This can be used like a list of :class:`ParameterMappingForCondition`\ s. - - :param parameter_mappings: - List of parameter mappings for specific conditions. - """ - - def __init__( - self, parameter_mappings: list[ParameterMappingForCondition] = None - ): - super().__init__() - if parameter_mappings is None: - parameter_mappings = [] - self.parameter_mappings = parameter_mappings - - def __iter__(self): - yield from self.parameter_mappings - - def __getitem__( - self, item - ) -> ParameterMapping | ParameterMappingForCondition: - result = self.parameter_mappings[item] - if isinstance(result, ParameterMappingForCondition): - return result - return ParameterMapping(result) - - def __len__(self): - return len(self.parameter_mappings) - - def append( - self, parameter_mapping_for_condition: ParameterMappingForCondition - ): - """Append a condition-specific parameter mapping.""" - self.parameter_mappings.append(parameter_mapping_for_condition) - - def __repr__(self): - return f"{self.__class__.__name__}({repr(self.parameter_mappings)})" - - @property - def free_symbols(self) -> set[str]: - """Get IDs of all (symbolic) parameters present in this mapping""" - return set.union(*(mapping.free_symbols for mapping in self)) - - -def petab_to_amici_scale(petab_scale: str) -> int: - """Convert petab scale id to amici scale id.""" - if petab_scale == LIN: - return ParameterScaling.none - if petab_scale == LOG10: - return ParameterScaling.log10 - if petab_scale == LOG: - return ParameterScaling.ln - raise ValueError(f"PEtab scale not recognized: {petab_scale}") - - -def amici_to_petab_scale(amici_scale: int) -> str: - """Convert amici scale id to petab scale id.""" - if amici_scale == ParameterScaling.none: - return LIN - if amici_scale == ParameterScaling.log10: - return LOG10 - if amici_scale == ParameterScaling.ln: - return LOG - raise ValueError(f"AMICI scale not recognized: {amici_scale}") - - -def scale_parameter(value: numbers.Number, petab_scale: str) -> numbers.Number: - """Bring parameter from linear scale to target scale. - - :param value: - Value to scale - :param petab_scale: - Target scale of ``value`` - - :return: - ``value`` on target scale - """ - if petab_scale == LIN: - return value - if petab_scale == LOG10: - return np.log10(value) - if petab_scale == LOG: - return np.log(value) - raise ValueError( - f"Unknown parameter scale {petab_scale}. " - f"Must be from {(LIN, LOG, LOG10)}" - ) - - -def unscale_parameter( - value: numbers.Number, petab_scale: str -) -> numbers.Number: - """Bring parameter from scale to linear scale. - - :param value: - Value to scale - :param petab_scale: - Target scale of ``value`` - - :return: - ``value`` on linear scale - """ - if petab_scale == LIN: - return value - if petab_scale == LOG10: - return np.power(10, value) - if petab_scale == LOG: - return np.exp(value) - raise ValueError( - f"Unknown parameter scale {petab_scale}. " - f"Must be from {(LIN, LOG, LOG10)}" - ) - - -def scale_parameters_dict( - value_dict: dict[Any, numbers.Number], petab_scale_dict: dict[Any, str] -) -> None: - """ - Bring parameters from linear scale to target scale. - - Bring values in ``value_dict`` from linear scale to the scale - provided in ``petab_scale_dict`` (in-place). - Both arguments are expected to have the same length and matching keys. - - :param value_dict: - Values to scale - - :param petab_scale_dict: - Target scales of ``values`` - """ - if value_dict.keys() != petab_scale_dict.keys(): - raise AssertionError("Keys don't match.") - - for key, value in value_dict.items(): - value_dict[key] = scale_parameter(value, petab_scale_dict[key]) - - -def unscale_parameters_dict( - value_dict: dict[Any, numbers.Number], petab_scale_dict: dict[Any, str] -) -> None: - """ - Bring parameters from target scale to linear scale. - - Bring values in ``value_dict`` from linear scale to the scale - provided in ``petab_scale_dict`` (in-place). - Both arguments are expected to have the same length and matching keys. - - :param value_dict: - Values to scale - - :param petab_scale_dict: - Target scales of ``values`` - """ - if value_dict.keys() != petab_scale_dict.keys(): - raise AssertionError("Keys don't match.") - - for key, value in value_dict.items(): - value_dict[key] = unscale_parameter(value, petab_scale_dict[key]) - def create_parameter_mapping( petab_problem: petab.Problem, diff --git a/python/sdist/amici/sim/sundials/petab/v1/_parameter_scaling.py b/python/sdist/amici/sim/sundials/petab/v1/_parameter_scaling.py new file mode 100644 index 0000000000..20e56199e7 --- /dev/null +++ b/python/sdist/amici/sim/sundials/petab/v1/_parameter_scaling.py @@ -0,0 +1,125 @@ +from __future__ import annotations + +import numbers +from typing import Any + +import numpy as np +from petab.v1 import LIN, LOG, LOG10 + +from amici._installation.amici import ParameterScaling + + +def petab_to_amici_scale(petab_scale: str) -> int: + """Convert petab scale id to amici scale id.""" + if petab_scale == LIN: + return ParameterScaling.none + if petab_scale == LOG10: + return ParameterScaling.log10 + if petab_scale == LOG: + return ParameterScaling.ln + raise ValueError(f"PEtab scale not recognized: {petab_scale}") + + +def amici_to_petab_scale(amici_scale: int) -> str: + """Convert amici scale id to petab scale id.""" + if amici_scale == ParameterScaling.none: + return LIN + if amici_scale == ParameterScaling.log10: + return LOG10 + if amici_scale == ParameterScaling.ln: + return LOG + raise ValueError(f"AMICI scale not recognized: {amici_scale}") + + +def scale_parameter(value: numbers.Number, petab_scale: str) -> numbers.Number: + """Bring parameter from linear scale to target scale. + + :param value: + Value to scale + :param petab_scale: + Target scale of ``value`` + + :return: + ``value`` on target scale + """ + if petab_scale == LIN: + return value + if petab_scale == LOG10: + return np.log10(value) + if petab_scale == LOG: + return np.log(value) + raise ValueError( + f"Unknown parameter scale {petab_scale}. " + f"Must be from {(LIN, LOG, LOG10)}" + ) + + +def unscale_parameter( + value: numbers.Number, petab_scale: str +) -> numbers.Number: + """Bring parameter from scale to linear scale. + + :param value: + Value to scale + :param petab_scale: + Target scale of ``value`` + + :return: + ``value`` on linear scale + """ + if petab_scale == LIN: + return value + if petab_scale == LOG10: + return np.power(10, value) + if petab_scale == LOG: + return np.exp(value) + raise ValueError( + f"Unknown parameter scale {petab_scale}. " + f"Must be from {(LIN, LOG, LOG10)}" + ) + + +def scale_parameters_dict( + value_dict: dict[Any, numbers.Number], petab_scale_dict: dict[Any, str] +) -> None: + """ + Bring parameters from linear scale to target scale. + + Bring values in ``value_dict`` from linear scale to the scale + provided in ``petab_scale_dict`` (in-place). + Both arguments are expected to have the same length and matching keys. + + :param value_dict: + Values to scale + + :param petab_scale_dict: + Target scales of ``values`` + """ + if value_dict.keys() != petab_scale_dict.keys(): + raise AssertionError("Keys don't match.") + + for key, value in value_dict.items(): + value_dict[key] = scale_parameter(value, petab_scale_dict[key]) + + +def unscale_parameters_dict( + value_dict: dict[Any, numbers.Number], petab_scale_dict: dict[Any, str] +) -> None: + """ + Bring parameters from target scale to linear scale. + + Bring values in ``value_dict`` from linear scale to the scale + provided in ``petab_scale_dict`` (in-place). + Both arguments are expected to have the same length and matching keys. + + :param value_dict: + Values to scale + + :param petab_scale_dict: + Target scales of ``values`` + """ + if value_dict.keys() != petab_scale_dict.keys(): + raise AssertionError("Keys don't match.") + + for key, value in value_dict.items(): + value_dict[key] = unscale_parameter(value, petab_scale_dict[key]) diff --git a/python/sdist/amici/sim/sundials/petab/v1/_petab_problem.py b/python/sdist/amici/sim/sundials/petab/v1/_petab_problem.py index 063dc1b2b9..bbfa4e2e6d 100644 --- a/python/sdist/amici/sim/sundials/petab/v1/_petab_problem.py +++ b/python/sdist/amici/sim/sundials/petab/v1/_petab_problem.py @@ -9,11 +9,13 @@ from petab.v1.C import PREEQUILIBRATION_CONDITION_ID, SIMULATION_CONDITION_ID import amici -from amici.importers.petab.v1.parameter_mapping import create_parameter_mapping from amici.sim.sundials.petab.v1._conditions import ( create_edatas, fill_in_parameters, ) +from amici.sim.sundials.petab.v1._parameter_mapping import ( + create_parameter_mapping, +) class PetabProblem: diff --git a/python/sdist/amici/sim/sundials/petab/v1/_simulations.py b/python/sdist/amici/sim/sundials/petab/v1/_simulations.py index 8d95f5528a..314d6981cb 100644 --- a/python/sdist/amici/sim/sundials/petab/v1/_simulations.py +++ b/python/sdist/amici/sim/sundials/petab/v1/_simulations.py @@ -17,11 +17,8 @@ from petab.v1.C import * # noqa: F403 import amici -from amici.importers.petab.v1.parameter_mapping import ( - ParameterMapping, - create_parameter_mapping, -) from amici.logging import get_logger, log_execution_time +from amici.sim._parameter_mapping import ParameterMapping from amici.sim.sundials import ( AMICI_SUCCESS, AmiciExpData, @@ -35,6 +32,9 @@ create_edatas, fill_in_parameters, ) +from amici.sim.sundials.petab.v1._parameter_mapping import ( + create_parameter_mapping, +) logger = get_logger(__name__) diff --git a/python/sdist/amici/sim/sundials/petab/v1/_simulator.py b/python/sdist/amici/sim/sundials/petab/v1/_simulator.py index bc606f4095..ef899aa379 100644 --- a/python/sdist/amici/sim/sundials/petab/v1/_simulator.py +++ b/python/sdist/amici/sim/sundials/petab/v1/_simulator.py @@ -18,7 +18,7 @@ import pandas as pd import petab.v1 as petab -from amici.importers.petab.v1.petab_import import import_petab_problem +from amici.importers.petab.v1._petab_import import import_petab_problem from amici.sim.sundials import AmiciModel, SensitivityMethod from ._simulations import RDATAS, rdatas_to_measurement_df, simulate_petab diff --git a/python/tests/adapters/test_fiddy.py b/python/tests/adapters/test_fiddy.py index 00769cc6dc..fa5750d4c0 100644 --- a/python/tests/adapters/test_fiddy.py +++ b/python/tests/adapters/test_fiddy.py @@ -2,15 +2,13 @@ from pathlib import Path -import amici -import amici.importers.petab.v1.petab_import -import amici.sim.sundials.petab.v1._simulations import numpy as np import pytest from amici.adapters.fiddy import ( run_simulation_to_cached_functions, simulate_petab_to_cached_functions, ) +from amici.importers.petab.v1 import import_petab_problem from amici.sim.sundials import SensitivityOrder, SteadyStateSensitivityMode from fiddy import MethodId, Type, get_derivative from fiddy.derivative_check import NumpyIsCloseDerivativeCheck @@ -41,9 +39,7 @@ def lotka_volterra() -> tuple[v1.Problem, np.ndarray]: def test_run_amici_simulation_to_functions(problem_generator): petab_problem, point = problem_generator() timepoints = sorted(set(petab_problem.measurement_df.time)) - amici_model = amici.importers.petab.v1.petab_import.import_petab_problem( - petab_problem - ) + amici_model = import_petab_problem(petab_problem) amici_model.set_timepoints(timepoints) amici_solver = amici_model.create_solver() @@ -108,9 +104,7 @@ def test_run_amici_simulation_to_functions(problem_generator): @pytest.mark.parametrize("scaled_parameters", (False, True)) def test_simulate_petab_to_functions(problem_generator, scaled_parameters): petab_problem, point = problem_generator() - amici_model = amici.importers.petab.v1.petab_import.import_petab_problem( - petab_problem - ) + amici_model = import_petab_problem(petab_problem) amici_solver = amici_model.create_solver() if amici_model.get_name() == "simple": diff --git a/python/tests/test_parameter_mapping.py b/python/tests/test_parameter_mapping.py index 5b9276dcaa..ae02d4a57b 100644 --- a/python/tests/test_parameter_mapping.py +++ b/python/tests/test_parameter_mapping.py @@ -1,6 +1,6 @@ """Test for ``amici.parameter_mapping``""" -from amici.importers.petab.v1.parameter_mapping import ( +from amici.sim._parameter_mapping import ( ParameterMapping, ParameterMappingForCondition, ) diff --git a/python/tests/test_petab_import.py b/python/tests/test_petab_import.py index 80add649e9..3d043a2c4b 100644 --- a/python/tests/test_petab_import.py +++ b/python/tests/test_petab_import.py @@ -73,7 +73,7 @@ def test_get_fixed_parameters(get_fixed_parameters_model): p8: not fixed (rate rule target) p9: not fixed (assignment rule target) """ - from amici.importers.petab.v1.sbml_import import ( + from amici.importers.petab.v1._sbml_import import ( _get_fixed_parameters_sbml as get_fixed_parameters, ) from petab.v1.models.sbml_model import SbmlModel @@ -116,7 +116,7 @@ def test_get_fixed_parameters(get_fixed_parameters_model): @skip_on_valgrind def test_default_output_parameters(simple_sbml_model, tempdir): - from amici.importers.petab.v1.petab_import import import_model_sbml + from amici.importers.petab.v1._petab_import import import_model_sbml from petab.v1.models.sbml_model import SbmlModel sbml_doc, sbml_model = simple_sbml_model diff --git a/tests/performance/test.py b/tests/performance/test.py index da5b2bd741..a0b61c80b2 100755 --- a/tests/performance/test.py +++ b/tests/performance/test.py @@ -11,7 +11,7 @@ import amici.exporters.sundials.de_export import amici.importers.sbml import petab.v1 as petab -from amici.importers.petab.v1.petab_import import import_model_sbml +from amici.importers.petab.v1._petab_import import import_model_sbml from amici.sim.sundials import ( AMICI_SUCCESS, ExpData,