From 491b4f80d3d1730aedc50cdcff7c1fbfe534bcf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Wed, 12 Nov 2025 11:48:39 +0000 Subject: [PATCH 01/23] refactor model components --- python/sdist/amici/constants.py | 2 +- python/sdist/amici/de_model.py | 18 +++---- python/sdist/amici/de_model_components.py | 48 ++++++++----------- python/sdist/amici/importers/pysb/__init__.py | 8 ++-- python/sdist/amici/importers/sbml/__init__.py | 27 ++++++----- python/sdist/amici/importers/sbml/splines.py | 2 +- python/tests/test_sciml.py | 6 +-- 7 files changed, 54 insertions(+), 57 deletions(-) diff --git a/python/sdist/amici/constants.py b/python/sdist/amici/constants.py index 346dc1c9ab..fdd7e59aee 100644 --- a/python/sdist/amici/constants.py +++ b/python/sdist/amici/constants.py @@ -23,7 +23,7 @@ class SymbolId(str, enum.Enum): SPECIES = "species" ALGEBRAIC_STATE = "algebraic_state" ALGEBRAIC_EQUATION = "algebraic_equation" - PARAMETER = "parameter" + FREE_PARAMETER = "parameter" FIXED_PARAMETER = "fixed_parameter" OBSERVABLE = "observable" EXPRESSION = "expression" diff --git a/python/sdist/amici/de_model.py b/python/sdist/amici/de_model.py index 445b4b068d..9582ec78bc 100644 --- a/python/sdist/amici/de_model.py +++ b/python/sdist/amici/de_model.py @@ -19,11 +19,12 @@ AlgebraicEquation, AlgebraicState, ConservationLaw, - Constant, DifferentialState, Event, EventObservable, Expression, + FixedParameter, + FreeParameter, LogLikelihood, LogLikelihoodRZ, LogLikelihoodY, @@ -32,7 +33,6 @@ NoiseParameter, Observable, ObservableParameter, - Parameter, Sigma, SigmaY, SigmaZ, @@ -228,8 +228,8 @@ def __init__( self._event_observables: list[EventObservable] = [] self._sigma_ys: list[SigmaY] = [] self._sigma_zs: list[SigmaZ] = [] - self._parameters: list[Parameter] = [] - self._constants: list[Constant] = [] + self._parameters: list[FreeParameter] = [] + self._constants: list[FixedParameter] = [] self._log_likelihood_ys: list[LogLikelihoodY] = [] self._log_likelihood_zs: list[LogLikelihoodZ] = [] self._log_likelihood_rzs: list[LogLikelihoodRZ] = [] @@ -354,11 +354,11 @@ def observables(self) -> list[Observable]: """Get all observables.""" return self._observables - def parameters(self) -> list[Parameter]: + def parameters(self) -> list[FreeParameter]: """Get all parameters.""" return self._parameters - def constants(self) -> list[Constant]: + def constants(self) -> list[FixedParameter]: """Get all constants.""" return self._constants @@ -589,8 +589,8 @@ def add_component( if type(component) not in { Observable, Expression, - Parameter, - Constant, + FreeParameter, + FixedParameter, DifferentialState, AlgebraicState, AlgebraicEquation, @@ -2630,7 +2630,7 @@ def _process_hybridization(self, hybridization: dict) -> None: for out_var, parts in outputs.items(): comp = parts["comp"] # remove output from model components - if isinstance(comp, Parameter): + if isinstance(comp, FreeParameter): self._parameters.remove(comp) elif isinstance(comp, Expression): self._expressions.remove(comp) diff --git a/python/sdist/amici/de_model_components.py b/python/sdist/amici/de_model_components.py index e460497718..b87abb4c14 100644 --- a/python/sdist/amici/de_model_components.py +++ b/python/sdist/amici/de_model_components.py @@ -19,7 +19,7 @@ __all__ = [ "ConservationLaw", - "Constant", + "FixedParameter", "Event", "Expression", "LogLikelihoodY", @@ -29,7 +29,7 @@ "NoiseParameter", "Observable", "ObservableParameter", - "Parameter", + "FreeParameter", "SigmaY", "SigmaZ", "DifferentialState", @@ -550,10 +550,9 @@ class SigmaZ(Sigma): class Expression(ModelQuantity): """ - An Expression is a recurring elements in symbolic formulas. Specifying - this may yield more compact expression which may lead to substantially - shorter model compilation times, but may also reduce model simulation time. - Abbreviated by ``w``. + A derived model variable that summarizes recurring elements in symbolic formulas. Specifying this may yield more + compact expression which may lead to substantially shorter model compilation times, but may also reduce model + simulation time. Abbreviated by ``w``. """ def __init__(self, symbol: sp.Symbol, name: str, value: sp.Expr): @@ -572,10 +571,9 @@ def __init__(self, symbol: sp.Symbol, name: str, value: sp.Expr): super().__init__(symbol, name, value) -class Parameter(ModelQuantity): +class FreeParameter(ModelQuantity): """ - A Parameter is a free variable in the model with respect to which - sensitivities may be computed, abbreviated by ``p``. + A model variable with respect to which sensitivities may be computed, abbreviated by ``p``. """ def __init__(self, symbol: sp.Symbol, name: str, value: numbers.Number): @@ -595,10 +593,9 @@ def __init__(self, symbol: sp.Symbol, name: str, value: numbers.Number): super().__init__(symbol, name, value) -class Constant(ModelQuantity): +class FixedParameter(ModelQuantity): """ - A Constant is a fixed variable in the model with respect to which - sensitivities cannot be computed, abbreviated by ``k``. + A model variable with respect to which sensitivities cannot be computed, abbreviated by ``k``. """ def __init__(self, symbol: sp.Symbol, name: str, value: numbers.Number): @@ -619,8 +616,8 @@ def __init__(self, symbol: sp.Symbol, name: str, value: numbers.Number): class NoiseParameter(ModelQuantity): """ - A NoiseParameter is an input variable for the computation of ``sigma`` that can be specified in a data-point - specific manner, abbreviated by ``np``. Only used for jax models. + An input variable for the computation of ``sigma`` that can be specified in a data-point specific manner, + abbreviated by ``np``. Only used for jax models. """ def __init__(self, symbol: sp.Symbol, name: str): @@ -639,8 +636,8 @@ def __init__(self, symbol: sp.Symbol, name: str): class ObservableParameter(ModelQuantity): """ - A NoiseParameter is an input variable for the computation of ``y`` that can be specified in a data-point specific - manner, abbreviated by ``op``. Only used for jax models. + An input variable for the computation of ``y`` that can be specified in a data-point specific manner, abbreviated + by ``op``. Only used for jax models. """ def __init__(self, symbol: sp.Symbol, name: str): @@ -659,10 +656,9 @@ def __init__(self, symbol: sp.Symbol, name: str): class LogLikelihood(ModelQuantity): """ - A LogLikelihood defines the distance between measurements and - experiments for a particular observable. The final LogLikelihood value - in the simulation will be the sum of all specified LogLikelihood - instances evaluated at all timepoints, abbreviated by ``Jy``. + Defines the distance between measurements and experiments for a particular observable. The final LogLikelihood value + in the simulation will be the sum of all specified LogLikelihood instances evaluated at all timepoints, abbreviated + by ``Jy``. """ def __init__(self, symbol: sp.Symbol, name: str, value: sp.Expr): @@ -706,11 +702,9 @@ class LogLikelihoodRZ(LogLikelihood): class Event(ModelQuantity): """ - An Event defines either a SBML event or a root of the argument of a - Heaviside function. The Heaviside functions will be tracked via the - vector ``h`` during simulation and are needed to inform the solver - about a discontinuity in either the right-hand side or the states - themselves, causing a reinitialization of the solver. + Defines either a SBML event or a root of the argument of a Heaviside function. The Heaviside functions will be + tracked via the vector ``h`` during simulation and are needed to inform the solver about a discontinuity in either + the right-hand side or the states themselves, causing a reinitialization of the solver. """ def __init__( @@ -901,8 +895,8 @@ def updates_state(self) -> bool: SymbolId.SPECIES: DifferentialState, SymbolId.ALGEBRAIC_STATE: AlgebraicState, SymbolId.ALGEBRAIC_EQUATION: AlgebraicEquation, - SymbolId.PARAMETER: Parameter, - SymbolId.FIXED_PARAMETER: Constant, + SymbolId.FREE_PARAMETER: FreeParameter, + SymbolId.FIXED_PARAMETER: FixedParameter, SymbolId.OBSERVABLE: Observable, SymbolId.EVENT_OBSERVABLE: EventObservable, SymbolId.SIGMAY: SigmaY, diff --git a/python/sdist/amici/importers/pysb/__init__.py b/python/sdist/amici/importers/pysb/__init__.py index 8728af88cc..12ef4cd91b 100644 --- a/python/sdist/amici/importers/pysb/__init__.py +++ b/python/sdist/amici/importers/pysb/__init__.py @@ -25,15 +25,15 @@ import amici from amici.de_model import DEModel from amici.de_model_components import ( - Constant, DifferentialState, Event, Expression, + FixedParameter, + FreeParameter, LogLikelihoodY, NoiseParameter, Observable, ObservableParameter, - Parameter, SigmaY, ) from amici.importers.utils import ( @@ -559,14 +559,14 @@ def _process_pysb_parameters( for par in pysb_model.parameters: args = [par, f"{par.name}"] if par.name in constant_parameters: - comp = Constant + comp = FixedParameter args.append(par.value) elif jax and re.match(r"noiseParameter\d+", par.name): comp = NoiseParameter elif jax and re.match(r"observableParameter\d+", par.name): comp = ObservableParameter else: - comp = Parameter + comp = FreeParameter args.append(par.value) ode_model.add_component(comp(*args)) diff --git a/python/sdist/amici/importers/sbml/__init__.py b/python/sdist/amici/importers/sbml/__init__.py index 913608f920..81429dbfeb 100644 --- a/python/sdist/amici/importers/sbml/__init__.py +++ b/python/sdist/amici/importers/sbml/__init__.py @@ -1102,12 +1102,12 @@ def _process_rate_rules(self): name = str(variable) del self.compartments[variable] - elif variable in self.symbols[SymbolId.PARAMETER]: + elif variable in self.symbols[SymbolId.FREE_PARAMETER]: init = self._sympify( - self.symbols[SymbolId.PARAMETER][variable]["value"], + self.symbols[SymbolId.FREE_PARAMETER][variable]["value"], ) - name = self.symbols[SymbolId.PARAMETER][variable]["name"] - del self.symbols[SymbolId.PARAMETER][variable] + name = self.symbols[SymbolId.FREE_PARAMETER][variable]["name"] + del self.symbols[SymbolId.FREE_PARAMETER][variable] # parameter with initial assignment, cannot use # self.initial_assignments as it is not filled at this @@ -1254,7 +1254,7 @@ def _process_parameters( ] loop_settings = { - SymbolId.PARAMETER: {"var": parameters, "name": "parameter"}, + SymbolId.FREE_PARAMETER: {"var": parameters, "name": "parameter"}, SymbolId.FIXED_PARAMETER: { "var": fixed_parameters, "name": "fixed_parameter", @@ -1276,9 +1276,9 @@ def _process_parameters( # Set of symbols in initial assignments that still allows handling them # via amici expressions - syms_allowed_in_expr_ia = set(self.symbols[SymbolId.PARAMETER]) | set( - self.symbols[SymbolId.FIXED_PARAMETER] - ) + syms_allowed_in_expr_ia = set( + self.symbols[SymbolId.FREE_PARAMETER] + ) | set(self.symbols[SymbolId.FIXED_PARAMETER]) for par in self.sbml.getListOfParameters(): if ( @@ -1416,7 +1416,7 @@ def _process_rules(self) -> None: # substitute symbols that must not occur in the definition of x0 # allowed symbols: amici model parameters and time allowed_syms = ( - set(self.symbols[SymbolId.PARAMETER]) + set(self.symbols[SymbolId.FREE_PARAMETER]) | set(self.symbols[SymbolId.FIXED_PARAMETER]) | {sbml_time_symbol} ) @@ -1540,7 +1540,10 @@ def _process_rule_algebraic(self, rule: libsbml.AlgebraicRule): symbol_id, source_symbols = next( ( (symbol_id, self.symbols[symbol_id]) - for symbol_id in (SymbolId.PARAMETER, SymbolId.SPECIES) + for symbol_id in ( + SymbolId.FREE_PARAMETER, + SymbolId.SPECIES, + ) if var in self.symbols[symbol_id] ), ) @@ -1661,7 +1664,7 @@ def _convert_event_assignment_parameter_targets_to_species(self): ) parameter_def = None for symbol_id in { - SymbolId.PARAMETER, + SymbolId.FREE_PARAMETER, SymbolId.FIXED_PARAMETER, SymbolId.EXPRESSION, }: @@ -2170,7 +2173,7 @@ def _process_initial_assignments(self): self.symbols[SymbolId.SPECIES], self.compartments, self.symbols[SymbolId.EXPRESSION], - self.symbols[SymbolId.PARAMETER], + self.symbols[SymbolId.FREE_PARAMETER], self.symbols[SymbolId.FIXED_PARAMETER], ): continue diff --git a/python/sdist/amici/importers/sbml/splines.py b/python/sdist/amici/importers/sbml/splines.py index 8b7a88df35..9d015da823 100644 --- a/python/sdist/amici/importers/sbml/splines.py +++ b/python/sdist/amici/importers/sbml/splines.py @@ -1355,7 +1355,7 @@ def _from_annotation( def parameters(self, importer: sbml.SbmlImporter) -> set[sp.Symbol]: """Returns the SBML parameters used by this spline""" return self._parameters().intersection( - set(importer.symbols[SymbolId.PARAMETER].keys()) + set(importer.symbols[SymbolId.FREE_PARAMETER].keys()) ) def _parameters(self) -> set[sp.Symbol]: diff --git a/python/tests/test_sciml.py b/python/tests/test_sciml.py index 5756abe1e9..4b4baf9eb2 100644 --- a/python/tests/test_sciml.py +++ b/python/tests/test_sciml.py @@ -379,16 +379,16 @@ def mock_de_model(self): from amici.de_model_components import ( DifferentialState, Expression, + FreeParameter, Observable, - Parameter, ) model = DEModel() # Add some parameters model._parameters = [ - Parameter(sp.Symbol("p1"), "param1", sp.Float(1.0)), - Parameter(sp.Symbol("p2"), "param2", sp.Float(2.0)), + FreeParameter(sp.Symbol("p1"), "param1", sp.Float(1.0)), + FreeParameter(sp.Symbol("p2"), "param2", sp.Float(2.0)), ] # Add some expressions From 39578739dddafc934bc710e1a93044b998fa1443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Wed, 12 Nov 2025 12:24:59 +0000 Subject: [PATCH 02/23] fix argument names --- .../example_performance_optimization.ipynb | 44 +++++------------- .../ExampleExperimentalConditions.ipynb | 6 +-- .../ExampleEquilibrationLogic.ipynb | 14 +++--- .../GettingStartedExtended.ipynb | 10 ++--- include/amici/edata.h | 2 +- python/sdist/amici/importers/pysb/__init__.py | 41 +++++++++-------- python/sdist/amici/importers/sbml/__init__.py | 45 ++++++++++--------- python/sdist/amici/petab/petab_importer.py | 4 +- python/sdist/amici/petab/pysb_import.py | 6 +-- python/sdist/amici/petab/sbml_import.py | 2 +- python/sdist/amici/testing/models.py | 12 ++--- python/tests/conftest.py | 8 ++-- .../test_compare_conservation_laws_sbml.py | 6 +-- python/tests/test_events.py | 4 +- python/tests/test_jax.py | 2 +- python/tests/test_preequilibration.py | 4 +- python/tests/test_sbml_import.py | 12 ++--- .../test_sbml_import_special_functions.py | 2 +- 18 files changed, 99 insertions(+), 125 deletions(-) diff --git a/doc/examples/example_large_models/example_performance_optimization.ipynb b/doc/examples/example_large_models/example_performance_optimization.ipynb index a8c7d43c2c..4f359a6d79 100644 --- a/doc/examples/example_large_models/example_performance_optimization.ipynb +++ b/doc/examples/example_large_models/example_performance_optimization.ipynb @@ -62,18 +62,17 @@ ] }, { - "cell_type": "markdown", - "id": "b772af14", "metadata": {}, + "cell_type": "markdown", "source": [ "## Model import\n", "\n", "### Symbolic processing\n", "\n", - "#### Parameters as constants\n", + "#### Fixing parameters\n", "\n", - "By default, AMICI will generate sensitivity equations with respect to all model parameters. If it is clear upfront, that sensitivities with respect to certain parameters will not be required, their IDs can be passed to [amici.importers.sbml.SbmlImporter.sbml2amici](https://amici.readthedocs.io/en/latest/generated/amici.importers.sbml.SbmlImporter.html#amici.importers.sbml.SbmlImporter.sbml2amici) or [amici.importers.pysb.pysb2amici](https://amici.readthedocs.io/en/latest/generated/amici.importers.pysb.html?highlight=pysb2amici#amici.importers.pysb.pysb2amici) via the `constant_parameters` argument to not generate the respective equations. This will reduce CPU time and RAM requirements during import and simulation.\n", - "The PEtab import will automatically pass all parameters with `petab.ESTIMATE==False` as `constant_parameters` arguments.\n", + "By default, AMICI will generate sensitivity equations with respect to all model parameters. If it is clear upfront, that sensitivities with respect to certain parameters will not be required, their IDs can be passed to [amici.importers.sbml.SbmlImporter.sbml2amici](https://amici.readthedocs.io/en/latest/generated/amici.importers.sbml.SbmlImporter.html#amici.importers.sbml.SbmlImporter.sbml2amici) or [amici.importers.pysb.pysb2amici](https://amici.readthedocs.io/en/latest/generated/amici.importers.pysb.html?highlight=pysb2amici#amici.importers.pysb.pysb2amici) via the `fixed_parameters` argument to not generate the respective equations. This will reduce CPU time and RAM requirements during import and simulation.\n", + "The PEtab import will automatically pass all parameters with `petab.ESTIMATE==False` as `fixed_parameters` arguments.\n", "\n", "See also the following section for the case that no sensitivities are required at all.\n", "\n", @@ -89,34 +88,14 @@ "# vs.\n", "/usr/bin/time -v amici_import_petab \"$petab_yaml\" --no-compile --no-sensitivities\n", "```" - ] + ], + "id": "7cd172d417bb986" }, { - "cell_type": "code", - "execution_count": 2, - "id": "4f3af02d", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "speedup: 1.25x\n" - ] - } - ], + "cell_type": "code", + "outputs": [], + "execution_count": null, "source": [ "figsize(4, 4)\n", "plt.bar([\"True\", \"False\"], [873.54, 697.85])\n", @@ -128,7 +107,8 @@ "plt.show()\n", "\n", "print(f\"speedup: {873.54 / 697.85:.2f}x\")" - ] + ], + "id": "5f3428b85510d206" }, { "cell_type": "markdown", @@ -497,7 +477,7 @@ "\n", "### Sensitivities w.r.t. a subset of parameters\n", "\n", - "If only sensitivities with respect to a subset of model parameters are of interest to you (see also *Parameters as constants* above), you can speed up the simulation by selecting the relevant parameter indices via [amici.Model.setParameterList](https://amici.readthedocs.io/en/latest/generated/amici.amici.Model.html#amici.amici.Model.setParameterList).\n" + "If only sensitivities with respect to a subset of model parameters are of interest to you (see also *Fixing parameters* above), you can speed up the simulation by selecting the relevant parameter indices via [amici.Model.setParameterList](https://amici.readthedocs.io/en/latest/generated/amici.amici.Model.html#amici.amici.Model.setParameterList).\n" ] }, { diff --git a/doc/examples/example_presimulation/ExampleExperimentalConditions.ipynb b/doc/examples/example_presimulation/ExampleExperimentalConditions.ipynb index 24627af62e..766e30ee46 100644 --- a/doc/examples/example_presimulation/ExampleExperimentalConditions.ipynb +++ b/doc/examples/example_presimulation/ExampleExperimentalConditions.ipynb @@ -219,9 +219,7 @@ { "cell_type": "markdown", "metadata": {}, - "source": [ - "Now the model is ready for compilation using [sbml2amici](https://amici.readthedocs.io/en/latest/generated/amici.sbml_import.SbmlImporter.html#amici.sbml_import.SbmlImporter.sbml2amici). Note that we here pass `fixedParameters` as arguments to `constant_parameters`, which ensures that amici is aware that we want to have them as `fixedParameters`:" - ] + "source": "Now the model is ready for compilation using [sbml2amici](https://amici.readthedocs.io/en/latest/generated/amici.sbml_import.SbmlImporter.html#amici.sbml_import.SbmlImporter.sbml2amici). Note that we here pass `fixed_parameters`, which ensures faster compilation by disabling sensitivity calculations for these parameters:" }, { "cell_type": "code", @@ -234,7 +232,7 @@ " model_output_dir,\n", " verbose=False,\n", " observation_model=observables,\n", - " constant_parameters=fixed_parameters,\n", + " fixed_parameters=fixed_parameters,\n", ")\n", "# load the generated module\n", "model_module = amici.import_model_module(model_name, model_output_dir)" diff --git a/doc/examples/example_steady_states/ExampleEquilibrationLogic.ipynb b/doc/examples/example_steady_states/ExampleEquilibrationLogic.ipynb index 4b1cc32213..013f3b3447 100644 --- a/doc/examples/example_steady_states/ExampleEquilibrationLogic.ipynb +++ b/doc/examples/example_steady_states/ExampleEquilibrationLogic.ipynb @@ -79,10 +79,10 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": {}, + "cell_type": "code", "outputs": [], + "execution_count": null, "source": [ "# Import necessary libraries and define the model\n", "import os\n", @@ -165,16 +165,16 @@ ] }, { - "cell_type": "code", - "execution_count": null, "metadata": {}, + "cell_type": "code", "outputs": [], + "execution_count": null, "source": [ "# Import the model\n", "sbml_importer = amici.SbmlImporter(antimony2sbml(ant_model), from_file=False)\n", "\n", "# specify observables and constant parameters\n", - "constant_parameters = [\"synthesis_substrate\", \"init_enzyme\"]\n", + "fixed_parameters = [\"synthesis_substrate\", \"init_enzyme\"]\n", "observation_model = [\n", " MC(id_=\"observable_product\", name=\"\", formula=\"product\"),\n", " MC(id_=\"observable_substrate\", name=\"\", formula=\"substrate\"),\n", @@ -188,7 +188,7 @@ " model_name,\n", " model_output_dir,\n", " observation_model=observation_model,\n", - " constant_parameters=constant_parameters,\n", + " fixed_parameters=fixed_parameters,\n", " compute_conservation_laws=False,\n", ")\n", "\n", @@ -198,7 +198,7 @@ " model_reduced_name,\n", " model_reduced_output_dir,\n", " observation_model=observation_model,\n", - " constant_parameters=constant_parameters,\n", + " fixed_parameters=fixed_parameters,\n", ")" ] }, diff --git a/doc/examples/getting_started_extended/GettingStartedExtended.ipynb b/doc/examples/getting_started_extended/GettingStartedExtended.ipynb index 5449baf957..80d219cc3f 100644 --- a/doc/examples/getting_started_extended/GettingStartedExtended.ipynb +++ b/doc/examples/getting_started_extended/GettingStartedExtended.ipynb @@ -134,9 +134,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "### Constant parameters\n", + "### Fixed parameters\n", "\n", - "Constant parameters, i.e. parameters with respect to which no sensitivities are to be computed (these are often parameters specifying a certain experimental condition) are provided as a list of parameter names." + "Fixed parameters, i.e. parameters with respect to which no sensitivities are to be computed (these are often parameters specifying a certain experimental condition) are provided as a list of parameter names." ] }, { @@ -144,9 +144,7 @@ "execution_count": 4, "metadata": {}, "outputs": [], - "source": [ - "constant_parameters = [\"k0\"]" - ] + "source": "fixed_parameters = [\"k0\"]" }, { "cell_type": "markdown", @@ -335,7 +333,7 @@ " model_output_dir,\n", " verbose=logging.INFO,\n", " observation_model=observation_model,\n", - " constant_parameters=constant_parameters,\n", + " fixed_parameters=fixed_parameters,\n", ")" ] }, diff --git a/include/amici/edata.h b/include/amici/edata.h index f060c917f0..05db142507 100644 --- a/include/amici/edata.h +++ b/include/amici/edata.h @@ -58,7 +58,7 @@ class ExpData : public SimulationParameters { * @param nztrue Number of event outputs * @param nmaxevent Maximal number of events to track * @param ts Timepoints (dimension: nt) - * @param fixed_parameters Model constants (dimension: nk) + * @param fixed_parameters Model variables excluded from sensitivity analysis (dimension: nk) */ ExpData( int nytrue, int nztrue, int nmaxevent, std::vector ts, diff --git a/python/sdist/amici/importers/pysb/__init__.py b/python/sdist/amici/importers/pysb/__init__.py index 12ef4cd91b..cb44744cc1 100644 --- a/python/sdist/amici/importers/pysb/__init__.py +++ b/python/sdist/amici/importers/pysb/__init__.py @@ -150,7 +150,7 @@ def pysb2amici( model: pysb.Model, output_dir: str | Path | None = None, observation_model: list[MeasurementChannel] = None, - constant_parameters: list[str] = None, + fixed_parameters: list[str] = None, verbose: int | bool = False, assume_pow_positivity: bool = False, compiler: str = None, @@ -196,9 +196,8 @@ def pysb2amici( ``MeasurementChannel.formula`` is expected to be ``None``. Event-observables are not supported. - :param constant_parameters: - list of :class:`pysb.core.Parameter` names that should be mapped as - fixed parameters + :param fixed_parameters: + list of :class:`pysb.core.Parameter` to be excluded from sensitivity analysis :param verbose: verbosity level for logging, True/False default to :attr:`logging.DEBUG`/:attr:`logging.ERROR` @@ -248,15 +247,15 @@ def pysb2amici( """ if observation_model is None: observation_model = [] - if constant_parameters is None: - constant_parameters = [] + if fixed_parameters is None: + fixed_parameters = [] model_name = model_name or model.name output_dir = output_dir or amici.get_model_dir(model_name) set_log_level(logger, verbose) ode_model = ode_model_from_pysb_importer( model, - constant_parameters=constant_parameters, + fixed_parameters=fixed_parameters, observation_model=observation_model, compute_conservation_laws=compute_conservation_laws, simplify=simplify, @@ -300,7 +299,7 @@ def pysb2amici( @log_execution_time("creating ODE model", logger) def ode_model_from_pysb_importer( model: pysb.Model, - constant_parameters: list[str] = None, + fixed_parameters: list[str] = None, observation_model: list[MeasurementChannel] = None, compute_conservation_laws: bool = True, simplify: Callable = sp.powsimp, @@ -319,7 +318,7 @@ def ode_model_from_pysb_importer( :param model: see :func:`amici.importers.pysb.pysb2amici` - :param constant_parameters: + :param fixed_parameters: see :func:`amici.importers.pysb.pysb2amici` :param observation_model: @@ -356,8 +355,8 @@ def ode_model_from_pysb_importer( cache_simplify=cache_simplify, ) - if constant_parameters is None: - constant_parameters = [] + if fixed_parameters is None: + fixed_parameters = [] if observation_model is None: observation_model = [] @@ -366,7 +365,7 @@ def ode_model_from_pysb_importer( pysb.bng.generate_equations(model, verbose=verbose) _process_pysb_species(model, ode) - _process_pysb_parameters(model, ode, constant_parameters, jax) + _process_pysb_parameters(model, ode, fixed_parameters, jax) if compute_conservation_laws: if events: raise NotImplementedError( @@ -396,7 +395,7 @@ def ode_model_from_pysb_importer( for channel in observation_model.values() ) - _process_stoichiometric_matrix(model, ode, constant_parameters) + _process_stoichiometric_matrix(model, ode, fixed_parameters) ode.generate_basic_variables() @@ -405,7 +404,7 @@ def ode_model_from_pysb_importer( @log_execution_time("processing PySB stoich. matrix", logger) def _process_stoichiometric_matrix( - pysb_model: pysb.Model, ode_model: DEModel, constant_parameters: list[str] + pysb_model: pysb.Model, ode_model: DEModel, fixed_parameters: list[str] ) -> None: """ Exploits the PySB stoichiometric matrix to generate xdot derivatives @@ -416,8 +415,8 @@ def _process_stoichiometric_matrix( :param ode_model: DEModel instance - :param constant_parameters: - list of constant parameters + :param fixed_parameters: + list of model variables excluded from sensitivity analysis """ x = ode_model.sym("x") @@ -471,7 +470,7 @@ def get_cached_index(symbol, sarray, index_cache): values = dflux_dw_dict # dp elif isinstance(fs, pysb.Parameter): - if fs.name in constant_parameters: + if fs.name in fixed_parameters: continue var = p idx_cache = p_idx @@ -537,7 +536,7 @@ def _process_pysb_species(pysb_model: pysb.Model, ode_model: DEModel) -> None: def _process_pysb_parameters( pysb_model: pysb.Model, ode_model: DEModel, - constant_parameters: list[str], + fixed_parameters: list[str], jax: bool = False, ) -> None: """ @@ -547,8 +546,8 @@ def _process_pysb_parameters( :param pysb_model: pysb model - :param constant_parameters: - list of Parameters that should be constants + :param fixed_parameters: + model variables excluded from sensitivity analysis :param jax: if set to ``True``, the generated model will be compatible JAX export @@ -558,7 +557,7 @@ def _process_pysb_parameters( """ for par in pysb_model.parameters: args = [par, f"{par.name}"] - if par.name in constant_parameters: + if par.name in fixed_parameters: comp = FixedParameter args.append(par.value) elif jax and re.match(r"noiseParameter\d+", par.name): diff --git a/python/sdist/amici/importers/sbml/__init__.py b/python/sdist/amici/importers/sbml/__init__.py index 81429dbfeb..508bd83503 100644 --- a/python/sdist/amici/importers/sbml/__init__.py +++ b/python/sdist/amici/importers/sbml/__init__.py @@ -276,7 +276,7 @@ def sbml2amici( self, model_name: str, output_dir: str | Path = None, - constant_parameters: Iterable[str] = None, + fixed_parameters: Iterable[str] = None, observation_model: list[MeasurementChannel] = None, verbose: int | bool = logging.ERROR, assume_pow_positivity: bool = False, @@ -315,8 +315,8 @@ def sbml2amici( Directory where the generated model package will be stored. Defaults to :func:`amici.get_model_dir`. - :param constant_parameters: - list of SBML Ids identifying constant parameters + :param fixed_parameters: + SBML Ids to be excluded from sensitivity analysis :param observation_model: The different measurement channels that make up the observation @@ -386,7 +386,7 @@ def sbml2amici( set_log_level(logger, verbose) ode_model = self._build_ode_model( - constant_parameters=constant_parameters, + fixed_parameters=fixed_parameters, observation_model=observation_model, verbose=verbose, compute_conservation_laws=compute_conservation_laws, @@ -526,7 +526,7 @@ def sbml2jax( def _build_ode_model( self, - constant_parameters: Iterable[str] = None, + fixed_parameters: Iterable[str] = None, observation_model: list[MeasurementChannel] = None, verbose: int | bool = logging.ERROR, compute_conservation_laws: bool = True, @@ -539,12 +539,10 @@ def _build_ode_model( See :py:func:`sbml2amici` for parameters. """ - constant_parameters = ( - list(constant_parameters) if constant_parameters else [] - ) + fixed_parameters = list(fixed_parameters) if fixed_parameters else [] hardcode_symbols = set(hardcode_symbols) if hardcode_symbols else {} - if invalid := (set(constant_parameters) & set(hardcode_symbols)): + if invalid := (set(fixed_parameters) & set(hardcode_symbols)): raise ValueError( "The following parameters were selected as both constant " f"and hard-coded which is not allowed: {invalid}" @@ -552,7 +550,7 @@ def _build_ode_model( self._reset_symbols() self._process_sbml( - constant_parameters=constant_parameters, + fixed_parameters=fixed_parameters, hardcode_symbols=hardcode_symbols, ) @@ -695,14 +693,14 @@ def _build_ode_model( @log_execution_time("importing SBML", logger) def _process_sbml( self, - constant_parameters: list[str] = None, + fixed_parameters: list[str] = None, hardcode_symbols: Sequence[str] = None, ) -> None: """ Read parameters, species, reactions, and so on from SBML model - :param constant_parameters: - SBML Ids identifying constant parameters + :param fixed_parameters: + SBML Ids to be excluded from sensitivity analysis :param hardcode_symbols: Parameter IDs to be replaced by their values in the generated model. """ @@ -711,7 +709,7 @@ def _process_sbml( self.check_support() self._gather_locals(hardcode_symbols=hardcode_symbols) self._process_parameters( - constant_parameters=constant_parameters, + fixed_parameters=fixed_parameters, hardcode_symbols=hardcode_symbols, ) self._process_compartments() @@ -1193,21 +1191,24 @@ def _process_annotations(self) -> None: @log_execution_time("processing SBML parameters", logger) def _process_parameters( self, - constant_parameters: list[str] = None, + fixed_parameters: list[str] = None, hardcode_symbols: Sequence[str] = None, ) -> None: """ Get parameter information from SBML model. - :param constant_parameters: - SBML Ids identifying constant parameters + :param fixed_parameters: + SBML Ids to be excluded from sensitivity analysis + + :param hardcode_symbols: + Parameter IDs to be replaced by their values in the generated model. """ - if constant_parameters is None: - constant_parameters = [] + if fixed_parameters is None: + fixed_parameters = [] # Ensure specified constant parameters exist in the model - for parameter in constant_parameters: + for parameter in fixed_parameters: if not self.sbml.getParameter(parameter): raise KeyError( f"Cannot make {parameter} a constant parameter: " @@ -1225,7 +1226,7 @@ def _process_parameters( fixed_parameters = [ parameter for parameter in self.sbml.getListOfParameters() - if parameter.getId() in constant_parameters + if parameter.getId() in fixed_parameters ] for parameter in fixed_parameters: ia_math = par_id_to_ia.get(parameter.getId()) @@ -1244,7 +1245,7 @@ def _process_parameters( parameters = [ parameter for parameter in self.sbml.getListOfParameters() - if parameter.getId() not in constant_parameters + if parameter.getId() not in fixed_parameters and ( (ia_math := par_id_to_ia.get(parameter.getId())) is None or ia_math.is_Number diff --git a/python/sdist/amici/petab/petab_importer.py b/python/sdist/amici/petab/petab_importer.py index 044b12f445..1a776d0a7c 100644 --- a/python/sdist/amici/petab/petab_importer.py +++ b/python/sdist/amici/petab/petab_importer.py @@ -394,7 +394,7 @@ def _do_import_sbml(self): model_name=self._module_name, output_dir=self.outdir, observation_model=observation_model, - constant_parameters=fixed_parameters, + fixed_parameters=fixed_parameters, allow_reinit_fixpar_initcond=allow_reinit_fixpar_initcond, verbose=self._verbose, compile=self._compile, @@ -474,7 +474,7 @@ def _do_import_pysb( model_name=self._module_name, output_dir=self.outdir, verbose=True, - constant_parameters=fixed_parameters, + fixed_parameters=fixed_parameters, observation_model=observation_model, pysb_model_has_obs_and_noise=True, compile=self._compile, diff --git a/python/sdist/amici/petab/pysb_import.py b/python/sdist/amici/petab/pysb_import.py index e4e4bcc8e4..b3e42f9b51 100644 --- a/python/sdist/amici/petab/pysb_import.py +++ b/python/sdist/amici/petab/pysb_import.py @@ -272,9 +272,7 @@ def import_model_pysb( f"column: {x}" ) - constant_parameters = ( - get_fixed_parameters(petab_problem) + fixed_parameters - ) + fixed_parameters = get_fixed_parameters(petab_problem) + fixed_parameters if petab_problem.observable_df is None: observation_model = [] @@ -311,7 +309,7 @@ def import_model_pysb( output_dir=model_output_dir, model_name=model_name, verbose=True, - constant_parameters=constant_parameters, + fixed_parameters=fixed_parameters, observation_model=observation_model, pysb_model_has_obs_and_noise=True, **kwargs, diff --git a/python/sdist/amici/petab/sbml_import.py b/python/sdist/amici/petab/sbml_import.py index 1c85a25eda..f0e57ed9a0 100644 --- a/python/sdist/amici/petab/sbml_import.py +++ b/python/sdist/amici/petab/sbml_import.py @@ -405,7 +405,7 @@ def import_model_sbml( model_name=model_name, output_dir=model_output_dir, observation_model=observation_model, - constant_parameters=fixed_parameters, + fixed_parameters=fixed_parameters, allow_reinit_fixpar_initcond=allow_reinit_fixpar_initcond, verbose=verbose, **kwargs, diff --git a/python/sdist/amici/testing/models.py b/python/sdist/amici/testing/models.py index b80aa79e73..b52145d628 100644 --- a/python/sdist/amici/testing/models.py +++ b/python/sdist/amici/testing/models.py @@ -115,7 +115,7 @@ def import_model_robertson(outdir: Path = None) -> Model: antimony2amici( robertson_ant, - constant_parameters=["k1"], + fixed_parameters=["k1"], observation_model=[ MeasurementChannel(id_="obs_x1", formula="x1"), MeasurementChannel(id_="obs_x2", formula="1e4 * x2"), @@ -138,7 +138,7 @@ def import_model_calvetti(outdir: Path = None) -> Model: antimony2amici( calvetti_ant, - constant_parameters=["V1ss", "R1ss", "V2ss", "R2ss", "V3ss", "R3ss"], + fixed_parameters=["V1ss", "R1ss", "V2ss", "R2ss", "V3ss", "R3ss"], observation_model=[ MeasurementChannel(id_="obs_V1", formula="V1"), MeasurementChannel(id_="obs_V2", formula="V2"), @@ -248,7 +248,7 @@ def import_model_neuron(outdir: Path = None) -> AmiciModel: MeasurementChannel(id_="y1", name="v", formula="v"), MeasurementChannel(id_="z1", event_id="event_1", formula="time"), ], - constant_parameters=constants, + fixed_parameters=constants, output_dir=outdir, ) return model @@ -325,7 +325,7 @@ def import_model_events(outdir: Path = None) -> AmiciModel: MeasurementChannel(id_="z1", event_id="event_1", formula="time"), MeasurementChannel(id_="z2", event_id="event_2", formula="time"), ], - constant_parameters=constants, + fixed_parameters=constants, output_dir=outdir, ) return model @@ -415,7 +415,7 @@ def import_model_jakstat(outdir: Path = None) -> AmiciModel: spline.add_to_sbml_model(sbml_model, auto_add=False) SbmlImporter(sbml_model).sbml2amici( - constant_parameters=["Omega_cyt", "Omega_nuc"], + fixed_parameters=["Omega_cyt", "Omega_nuc"], observation_model=[ MeasurementChannel( id_="obs_pSTAT", @@ -507,7 +507,7 @@ def import_model_steadystate(outdir: Path = None) -> AmiciModel: antimony2amici( ant_str, - constant_parameters=["k1", "k2", "k3", "k4"], + fixed_parameters=["k1", "k2", "k3", "k4"], observation_model=[ MeasurementChannel(id_="obs_x1", formula="x1"), MeasurementChannel(id_="obs_x2", formula="x2"), diff --git a/python/tests/conftest.py b/python/tests/conftest.py index 731b1ec1d2..8816eb3d75 100644 --- a/python/tests/conftest.py +++ b/python/tests/conftest.py @@ -32,7 +32,7 @@ def sbml_example_presimulation_module(): sbml_importer = amici.SbmlImporter(MODEL_PRESIMULATION_XML) - constant_parameters = ["DRUG_0", "KIN_0"] + fixed_parameters = ["DRUG_0", "KIN_0"] observables = amici.assignment_rules_to_observables( sbml_importer.sbml, # the libsbml model object @@ -46,7 +46,7 @@ def sbml_example_presimulation_module(): output_dir=outdir, verbose=False, observation_model=observables, - constant_parameters=constant_parameters, + fixed_parameters=fixed_parameters, ) yield amici.import_model_module( @@ -60,7 +60,7 @@ def pysb_example_presimulation_module(): pysb = pytest.importorskip("pysb") from amici.importers.pysb import pysb2amici - constant_parameters = ["DRUG_0", "KIN_0"] + fixed_parameters = ["DRUG_0", "KIN_0"] pysb.SelfExporter.cleanup() # reset pysb pysb.SelfExporter.do_export = True @@ -83,7 +83,7 @@ def pysb_example_presimulation_module(): outdir, verbose=True, observation_model=[MeasurementChannel("pPROT_obs")], - constant_parameters=constant_parameters, + fixed_parameters=fixed_parameters, ) yield amici.import_model_module(model.name, outdir) diff --git a/python/tests/test_compare_conservation_laws_sbml.py b/python/tests/test_compare_conservation_laws_sbml.py index 481e7a0343..1e726be60f 100644 --- a/python/tests/test_compare_conservation_laws_sbml.py +++ b/python/tests/test_compare_conservation_laws_sbml.py @@ -85,7 +85,7 @@ def models(): model_name_cl = model_output_dir_cl = "model_constant_species_cl" # Define constants, observables, sigmas - constant_parameters = ["synthesis_substrate", "init_enzyme"] + fixed_parameters = ["synthesis_substrate", "init_enzyme"] observation_model = [ MC("observable_product", formula="product", sigma=1.0, name=""), MC("observable_substrate", formula="substrate", sigma=1.0, name=""), @@ -95,13 +95,13 @@ def models(): sbml_importer.sbml2amici( model_name_cl, model_output_dir_cl, - constant_parameters=constant_parameters, + fixed_parameters=fixed_parameters, observation_model=observation_model, ) sbml_importer.sbml2amici( model_name, model_output_dir, - constant_parameters=constant_parameters, + fixed_parameters=fixed_parameters, observation_model=observation_model, compute_conservation_laws=False, ) diff --git a/python/tests/test_events.py b/python/tests/test_events.py index e78a7a93a4..c546d06373 100644 --- a/python/tests/test_events.py +++ b/python/tests/test_events.py @@ -760,7 +760,7 @@ def test_handling_of_fixed_time_point_event_triggers(tempdir): antimony2amici( ant_model, # test with constant parameters and non-constant parameters! - constant_parameters=["four"], + fixed_parameters=["four"], model_name=module_name, output_dir=tempdir, ) @@ -1213,7 +1213,7 @@ def test_preeq_presim_preserve_heaviside_state(tempdir): E2: at some_time >= 10 and time < 1, t0 = true: target2 = target2 + 1; """, - constant_parameters=["k1"], + fixed_parameters=["k1"], model_name=model_name, output_dir=tempdir, ) diff --git a/python/tests/test_jax.py b/python/tests/test_jax.py index 1f335db4c8..5e47699026 100644 --- a/python/tests/test_jax.py +++ b/python/tests/test_jax.py @@ -98,7 +98,7 @@ def test_dimerization(): outdir, verbose=True, observation_model=[MC("a_obs"), MC("b_obs")], - constant_parameters=["ksyn_a", "ksyn_b"], + fixed_parameters=["ksyn_a", "ksyn_b"], ) pysb2jax( model, diff --git a/python/tests/test_preequilibration.py b/python/tests/test_preequilibration.py index 22074dcf0d..0c30a3a34b 100644 --- a/python/tests/test_preequilibration.py +++ b/python/tests/test_preequilibration.py @@ -723,7 +723,7 @@ def test_preequilibration_t0(tempdir): ant_str, model_name=module_name, output_dir=tempdir, - constant_parameters=["preeq_indicator"], + fixed_parameters=["preeq_indicator"], ) model_module = amici.import_model_module( module_name=module_name, module_path=tempdir @@ -786,7 +786,7 @@ def test_preequilibration_events(tempdir): ant_str, model_name=module_name, output_dir=tempdir, - constant_parameters=["is_preeq"], + fixed_parameters=["is_preeq"], ) model_module = amici.import_model_module( module_name=module_name, module_path=tempdir diff --git a/python/tests/test_sbml_import.py b/python/tests/test_sbml_import.py index 136f5ef7a6..4e3aa5654c 100644 --- a/python/tests/test_sbml_import.py +++ b/python/tests/test_sbml_import.py @@ -244,7 +244,7 @@ def model_steadystate_module(): sbml_importer.sbml2amici( model_name=module_name, output_dir=outdir, - constant_parameters=["k0"], + fixed_parameters=["k0"], observation_model=list(observables.values()), ) @@ -303,7 +303,7 @@ def test_presimulation_events(tempdir): at time >= -one and presim_indicator == 1: presim_target_1 = presim_target_1 + one at time >= one and presim_indicator == 0: mainsim_target = mainsim_target + 1 """, - constant_parameters=["presim_indicator"], + fixed_parameters=["presim_indicator"], model_name=model_name, output_dir=tempdir, ) @@ -576,7 +576,7 @@ def model_test_likelihoods(tempdir): sbml_importer.sbml2amici( model_name=module_name, output_dir=tempdir, - constant_parameters=["k0"], + fixed_parameters=["k0"], observation_model=observation_model, ) @@ -664,7 +664,7 @@ def test_likelihoods_error(): sbml_importer.sbml2amici( model_name=module_name, output_dir=outdir, - constant_parameters=["k0"], + fixed_parameters=["k0"], observation_model=[ MC("o1", formula="x1", noise_distribution="nörmal") ], @@ -855,7 +855,7 @@ def test_hardcode_parameters(): assert ode_model.differential_states()[0].get_dt().name == "p1" ode_model = sbml_importer._build_ode_model( - constant_parameters=[], + fixed_parameters=[], hardcode_symbols=["p1"], ) assert str(ode_model.parameters()) == "[]" @@ -867,7 +867,7 @@ def test_hardcode_parameters(): with pytest.raises(ValueError): sbml_importer._build_ode_model( # mutually exclusive - constant_parameters=["p1"], + fixed_parameters=["p1"], hardcode_symbols=["p1"], ) diff --git a/python/tests/test_sbml_import_special_functions.py b/python/tests/test_sbml_import_special_functions.py index bf58be6f55..4b961151f5 100644 --- a/python/tests/test_sbml_import_special_functions.py +++ b/python/tests/test_sbml_import_special_functions.py @@ -30,7 +30,7 @@ def model_special_likelihoods(): sbml_importer.sbml2amici( model_name=module_name, output_dir=outdir, - constant_parameters=["k0"], + fixed_parameters=["k0"], observation_model=[ MC("o1", formula="100*10^x1", noise_distribution="binomial"), MC( From f9bc1d5e127d64d2a4ea35db632e64981e8604cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Wed, 12 Nov 2025 12:26:43 +0000 Subject: [PATCH 03/23] Update de_model_components.py --- python/sdist/amici/de_model_components.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/sdist/amici/de_model_components.py b/python/sdist/amici/de_model_components.py index b87abb4c14..c48e2d28c6 100644 --- a/python/sdist/amici/de_model_components.py +++ b/python/sdist/amici/de_model_components.py @@ -573,7 +573,7 @@ def __init__(self, symbol: sp.Symbol, name: str, value: sp.Expr): class FreeParameter(ModelQuantity): """ - A model variable with respect to which sensitivities may be computed, abbreviated by ``p``. + A model variable with respect to which sensitivities can be computed, abbreviated by ``p``. """ def __init__(self, symbol: sp.Symbol, name: str, value: numbers.Number): From c86cb3f421938f09125261e3f81fd2ca0ae82fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Wed, 12 Nov 2025 13:11:13 +0000 Subject: [PATCH 04/23] refactor de_model --- python/sdist/amici/de_model.py | 120 ++++++++++------------ python/tests/petab_/test_petab_problem.py | 6 +- python/tests/test_sbml_import.py | 10 +- python/tests/test_sciml.py | 2 +- 4 files changed, 64 insertions(+), 74 deletions(-) diff --git a/python/sdist/amici/de_model.py b/python/sdist/amici/de_model.py index 9582ec78bc..030999704b 100644 --- a/python/sdist/amici/de_model.py +++ b/python/sdist/amici/de_model.py @@ -83,98 +83,91 @@ class DEModel: sensitivity computation. :ivar _differential_states: - list of differential state variables + differential state variables :ivar _algebraic_states: - list of algebraic state variables + algebraic state variables :ivar _observables: - list of observables + observables :ivar _event_observables: - list of event observables + event observables :ivar _sigma_ys: - list of sigmas for observables + sigmas for observables :ivar _sigma_zs: - list of sigmas for event observables + sigmas for event observables - :ivar _parameters: - list of parameters + :ivar _free_parameters: + parameters included in sensitivity analysis + + :ivar _fixed_parameters: + parameters excluded from sensitivity analysis :ivar _log_likelihood_ys: - list of loglikelihoods for observables + loglikelihoods for observables :ivar _log_likelihood_zs: - list of loglikelihoods for event observables + loglikelihoods for event observables :ivar _log_likelihood_rzs: - list of loglikelihoods for event observable regularizations + loglikelihoods for event observable regularizations :ivar _expressions: - list of expressions instances + expressions instances :ivar _conservation_laws: - list of conservation laws + conservation laws :ivar _symboldim_funs: - define functions that compute model dimensions, these - are functions as the underlying symbolic expressions have not been - populated at compile time + define functions that compute model dimensions, these are functions as the underlying symbolic expressions have + not been populated at compile time :ivar _eqs: - carries symbolic formulas of the symbolic variables of the model + symbolic formulas of the symbolic variables of the model :ivar _sparseeqs: - carries linear list of all symbolic formulas for sparsified - variables + linear list of all symbolic formulas for sparsified variables :ivar _vals: - carries numeric values of symbolic identifiers of the symbolic - variables of the model + numeric values of symbolic identifiers of the symbolic variables of the model :ivar _names: - carries the names of symbolic identifiers of the symbolic variables - of the model + the names of symbolic identifiers of the symbolic variables of the model :ivar _syms: - carries symbolic identifiers of the symbolic variables of the - model + symbolic identifiers of the symbolic variables of the model :ivar _sparsesyms: - carries linear list of all symbols for sparsified - variables + linear list of all symbols for sparsified variables :ivar _colptrs: - carries column pointers for sparsified variables. See - SUNMatrixContent_Sparse definition in ``sunmatrix/sunmatrix_sparse.h`` + column pointers for sparsified variables. See SUNMatrixContent_Sparse definition in + ``sunmatrix/sunmatrix_sparse.h`` :ivar _rowvals: - carries row values for sparsified variables. See - SUNMatrixContent_Sparse definition in ``sunmatrix/sunmatrix_sparse.h`` + row values for sparsified variables. See SUNMatrixContent_Sparse definition in ``sunmatrix/sunmatrix_sparse.h`` :ivar _equation_prototype: - defines the attribute from which an equation should be generated via - list comprehension (see :meth:`OEModel._generate_equation`) + attribute from which an equation should be generated via list comprehension + (see :meth:`OEModel._generate_equation`) :ivar _variable_prototype: - defines the attribute from which a variable should be generated via - list comprehension (see :meth:`DEModel._generate_symbol`) + attribute from which a variable should be generated via list comprehension + (see :meth:`DEModel._generate_symbol`) :ivar _value_prototype: - defines the attribute from which a value should be generated via - list comprehension (see :meth:`DEModel._generate_value`) + attribute from which a value should be generated via list comprehension (see :meth:`DEModel._generate_value`) :ivar _total_derivative_prototypes: - defines how a total derivative equation is computed for an equation, - key defines the name and values should be arguments for - :meth:`DEModel.totalDerivative` + defines how a total derivative equation is computed for an equation, key defines the name and values should be + arguments for :meth:`DEModel.totalDerivative` :ivar _lock_total_derivative: - add chainvariables to this set when computing total derivative from - a partial derivative call to enforce a partial derivative in the - next recursion. prevents infinite recursion + add chainvariables to this set when computing total derivative from a partial derivative call to enforce a + partial derivative in the next recursion. prevents infinite recursion :ivar _simplify: If not None, this function will be used to simplify symbolic @@ -182,22 +175,19 @@ class DEModel: To apply multiple simplifications, wrap them in a lambda expression. :ivar _x0_fixedParameters_idx: - Index list of subset of states for which x0_fixedParameters was - computed + Index list of subset of states for which x0_fixedParameters was computed :ivar _w_recursion_depth: recursion depth in w, quantified as nilpotency of dwdw :ivar _has_quadratic_nllh: - whether all observables have a gaussian noise model, i.e. whether - res and FIM make sense. + whether all observables have a gaussian noise model, i.e. whether res and FIM make sense. :ivar _static_indices: - dict of lists of indices of static variables for different - model entities. + indices of static variables for different model entities. :ivar _z2event: - list of event indices for each event observable + event indices for each event observable """ def __init__( @@ -228,8 +218,8 @@ def __init__( self._event_observables: list[EventObservable] = [] self._sigma_ys: list[SigmaY] = [] self._sigma_zs: list[SigmaZ] = [] - self._parameters: list[FreeParameter] = [] - self._constants: list[FixedParameter] = [] + self._free_parameters: list[FreeParameter] = [] + self._fixed_parameters: list[FixedParameter] = [] self._log_likelihood_ys: list[LogLikelihoodY] = [] self._log_likelihood_zs: list[LogLikelihoodZ] = [] self._log_likelihood_rzs: list[LogLikelihoodRZ] = [] @@ -278,8 +268,8 @@ def __init__( "x_rdata": self.states, "y": self.observables, "z": self.event_observables, - "p": self.parameters, - "k": self.constants, + "p": self.free_parameters, + "k": self.fixed_parameters, "w": self.expressions, "sigmay": self.sigma_ys, "sigmaz": self.sigma_zs, @@ -288,8 +278,8 @@ def __init__( "op": self.observable_parameters, } self._value_prototype: dict[str, Callable] = { - "p": self.parameters, - "k": self.constants, + "p": self.free_parameters, + "k": self.fixed_parameters, } self._total_derivative_prototypes: dict[ str, dict[str, str | list[str]] @@ -354,13 +344,13 @@ def observables(self) -> list[Observable]: """Get all observables.""" return self._observables - def parameters(self) -> list[FreeParameter]: + def free_parameters(self) -> list[FreeParameter]: """Get all parameters.""" - return self._parameters + return self._free_parameters - def constants(self) -> list[FixedParameter]: + def fixed_parameters(self) -> list[FixedParameter]: """Get all constants.""" - return self._constants + return self._fixed_parameters def expressions(self) -> list[Expression]: """Get all expressions.""" @@ -1212,7 +1202,7 @@ def _generate_symbol(self, name: str) -> None: f"s{tcl.get_id()}__{par.get_id()}", real=True, ) - for par in self._parameters + for par in self._free_parameters ] if self.conservation_law_has_multispecies(tcl) else [0] * self.num_par() @@ -2334,7 +2324,7 @@ def state_has_fixed_parameter_initial_condition(self, ix: int) -> bool: if not isinstance(ic, sp.Basic): return False return any( - fp in (c.get_sym() for c in self._constants) + fp in (c.get_sym() for c in self._fixed_parameters) for fp in ic.free_symbols ) @@ -2553,7 +2543,7 @@ def _components(self) -> list[ModelQuantity]: self._algebraic_states + self._algebraic_equations + self._conservation_laws - + self._constants + + self._fixed_parameters + self._differential_states + self._event_observables + self._events @@ -2562,7 +2552,7 @@ def _components(self) -> list[ModelQuantity]: + self._log_likelihood_zs + self._log_likelihood_rzs + self._observables - + self._parameters + + self._free_parameters + self._sigma_ys + self._sigma_zs + self._splines @@ -2631,7 +2621,7 @@ def _process_hybridization(self, hybridization: dict) -> None: comp = parts["comp"] # remove output from model components if isinstance(comp, FreeParameter): - self._parameters.remove(comp) + self._free_parameters.remove(comp) elif isinstance(comp, Expression): self._expressions.remove(comp) elif isinstance(comp, DifferentialState): diff --git a/python/tests/petab_/test_petab_problem.py b/python/tests/petab_/test_petab_problem.py index 35c1fa7d34..a1e4a2f806 100644 --- a/python/tests/petab_/test_petab_problem.py +++ b/python/tests/petab_/test_petab_problem.py @@ -29,7 +29,7 @@ def test_amici_petab_problem_pregenerate(): {app.model.get_parameter_ids()[0]: 0.12345}, scaled_parameters=True ) for edata in edatas: - assert edata.parameters[0] == 0.12345 + assert edata.free_parameters[0] == 0.12345 @skip_on_valgrind @@ -54,10 +54,10 @@ def test_amici_petab_problem_on_demand(): ) # previously generated ExpDatas are not updated for edata in edatas: - assert edata.parameters[0] != 0.12345 + assert edata.free_parameters[0] != 0.12345 # but newly generated ExpDatas are for edata in app.get_edatas(): - assert edata.parameters[0] == 0.12345 + assert edata.free_parameters[0] == 0.12345 some_sim_condition = ( petab_problem.measurement_df.simulationConditionId.iloc[0] diff --git a/python/tests/test_sbml_import.py b/python/tests/test_sbml_import.py index 4e3aa5654c..5e576c6b60 100644 --- a/python/tests/test_sbml_import.py +++ b/python/tests/test_sbml_import.py @@ -851,14 +851,14 @@ def test_hardcode_parameters(): assert sbml_model.getParameter("p1").getValue() != 0 ode_model = sbml_importer._build_ode_model() - assert str(ode_model.parameters()) == "[p1]" + assert str(ode_model.free_parameters()) == "[p1]" assert ode_model.differential_states()[0].get_dt().name == "p1" ode_model = sbml_importer._build_ode_model( fixed_parameters=[], hardcode_symbols=["p1"], ) - assert str(ode_model.parameters()) == "[]" + assert str(ode_model.free_parameters()) == "[]" assert ( ode_model.differential_states()[0].get_dt() == sbml_model.getParameter("p1").getValue() @@ -1182,9 +1182,9 @@ def test_time_dependent_initial_assignment(compute_conservation_laws: bool): # "species", because differential state assert symbol_with_assumptions("x1") in si.symbols[SymbolId.SPECIES].keys() - assert "p0" in [p.get_id() for p in de_model.parameters()] - assert "p1" not in [p.get_id() for p in de_model.parameters()] - assert "p2" not in [p.get_id() for p in de_model.parameters()] + assert "p0" in [p.get_id() for p in de_model.free_parameters()] + assert "p1" not in [p.get_id() for p in de_model.free_parameters()] + assert "p2" not in [p.get_id() for p in de_model.free_parameters()] assert list(de_model.sym("x_rdata")) == [ symbol_with_assumptions("p2"), diff --git a/python/tests/test_sciml.py b/python/tests/test_sciml.py index 4b4baf9eb2..24a9bca30a 100644 --- a/python/tests/test_sciml.py +++ b/python/tests/test_sciml.py @@ -386,7 +386,7 @@ def mock_de_model(self): model = DEModel() # Add some parameters - model._parameters = [ + model._free_parameters = [ FreeParameter(sp.Symbol("p1"), "param1", sp.Float(1.0)), FreeParameter(sp.Symbol("p2"), "param2", sp.Float(2.0)), ] From 346e04d6fd8973d9b2673e07a6dd4a1754a955f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Wed, 12 Nov 2025 13:29:04 +0000 Subject: [PATCH 05/23] refactor cpp code --- doc/examples/example_errors.ipynb | 4 +- include/amici/simulation_parameters.h | 46 +++++++++++----------- python/sdist/amici/adapters/fiddy.py | 2 +- python/sdist/amici/debugging/__init__.py | 4 +- python/sdist/amici/gradient_check.py | 10 ++--- python/sdist/amici/pandas.py | 6 +-- python/sdist/amici/petab/conditions.py | 2 +- python/sdist/amici/petab/petab_importer.py | 2 +- python/tests/test_jax.py | 4 +- python/tests/test_preequilibration.py | 2 +- src/edata.cpp | 12 +++--- src/hdf5.cpp | 6 +-- 12 files changed, 51 insertions(+), 49 deletions(-) diff --git a/doc/examples/example_errors.ipynb b/doc/examples/example_errors.ipynb index 184954b0fb..acc4b439a7 100644 --- a/doc/examples/example_errors.ipynb +++ b/doc/examples/example_errors.ipynb @@ -627,7 +627,9 @@ "unscaled_parameter = dict(\n", " zip(\n", " amici_model.get_parameter_ids(),\n", - " starmap(amici.unscale_parameter, zip(edata.parameters, edata.pscale)),\n", + " starmap(\n", + " amici.unscale_parameter, zip(edata.free_parameters, edata.pscale)\n", + " ),\n", " )\n", ")\n", "print(dict((p, unscaled_parameter[p]) for p in (\"Kd\", \"Kp\", \"n_par\")))" diff --git a/include/amici/simulation_parameters.h b/include/amici/simulation_parameters.h index f68670afc9..9d10ae005e 100644 --- a/include/amici/simulation_parameters.h +++ b/include/amici/simulation_parameters.h @@ -23,15 +23,15 @@ class SimulationParameters { /** * @brief Constructor - * @param fixedParameters Model constants - * @param parameters Model parameters + * @param fixed_parameters Model parameters excluded from sensitivity analysis + * @param free_parameters Model parameters included in sensitivity analysis */ SimulationParameters( - std::vector fixedParameters, std::vector parameters + std::vector fixed_parameters, std::vector free_parameters ) - : fixed_parameters(std::move(fixedParameters)) - , parameters(std::move(parameters)) - , pscale(std::vector(this->parameters.size(), ParameterScaling::none)) { + : fixed_parameters(std::move(fixed_parameters)) + , free_parameters(std::move(free_parameters)) + , pscale(std::vector(this->free_parameters.size(), ParameterScaling::none)) { } #ifndef SWIGPYTHON @@ -49,33 +49,33 @@ class SimulationParameters { */ /** * @brief Constructor - * @param fixedParameters Model constants - * @param parameters Model parameters + * @param fixed_parameters Model parameters excluded from sensitivity analysis + * @param free_parameters Model parameters included in sensitivity analysis * @param plist Model parameter indices w.r.t. which sensitivities are to be * computed */ SimulationParameters( - std::vector fixedParameters, std::vector parameters, + std::vector fixed_parameters, std::vector free_parameters, std::vector plist ) - : fixed_parameters(std::move(fixedParameters)) - , parameters(std::move(parameters)) - , pscale(std::vector(this->parameters.size(), ParameterScaling::none)) + : fixed_parameters(std::move(fixed_parameters)) + , free_parameters(std::move(free_parameters)) + , pscale(std::vector(this->free_parameters.size(), ParameterScaling::none)) , plist(std::move(plist)) {} /** * @brief Constructor * @param timepoints Timepoints for which simulation results are requested - * @param fixedParameters Model constants - * @param parameters Model parameters + * @param fixed_parameters Model parameters excluded from sensitivity analysis + * @param free_parameters Model parameters included in sensitivity analysis */ SimulationParameters( - std::vector timepoints, std::vector fixedParameters, - std::vector parameters + std::vector timepoints, std::vector fixed_parameters, + std::vector free_parameters ) - : fixed_parameters(std::move(fixedParameters)) - , parameters(std::move(parameters)) - , pscale(std::vector(this->parameters.size(), ParameterScaling::none)) + : fixed_parameters(std::move(fixed_parameters)) + , free_parameters(std::move(free_parameters)) + , pscale(std::vector(this->free_parameters.size(), ParameterScaling::none)) , timepoints(std::move(timepoints)) {} #endif @@ -145,12 +145,12 @@ class SimulationParameters { std::vector fixed_parameters_presimulation; /** - * @brief Model parameters + * @brief Model free_parameters * * Vector of size Model::np() or empty with parameter scaled according to * SimulationParameter::pscale. */ - std::vector parameters; + std::vector free_parameters; /** * @brief Initial state @@ -202,8 +202,8 @@ class SimulationParameters { * @brief Duration of pre-simulation. * * If this is > 0, presimulation will be performed from - * (model->t0 - t_presim) to model->t0 using the fixedParameters in - * fixedParametersPresimulation + * (model->t0 - t_presim) to model->t0 using the fixed_parameters in + * fixed_parameters_presimulation */ realtype t_presim{0.0}; diff --git a/python/sdist/amici/adapters/fiddy.py b/python/sdist/amici/adapters/fiddy.py index 3a21b02012..e90778e0b4 100644 --- a/python/sdist/amici/adapters/fiddy.py +++ b/python/sdist/amici/adapters/fiddy.py @@ -139,7 +139,7 @@ def run_simulation_to_cached_functions( amici_solver = amici_model.create_solver() if parameter_ids is None: parameter_ids = amici_model.get_parameter_ids() - if amici_edata is not None and amici_edata.parameters is not None: + if amici_edata is not None and amici_edata.free_parameters is not None: raise NotImplementedError( "Customization of parameter values inside AMICI ExpData." ) diff --git a/python/sdist/amici/debugging/__init__.py b/python/sdist/amici/debugging/__init__.py index fbeb553bf8..656ae9c6ca 100644 --- a/python/sdist/amici/debugging/__init__.py +++ b/python/sdist/amici/debugging/__init__.py @@ -35,8 +35,8 @@ def get_model_for_preeq(model: amici.Model, edata: amici.ExpData): model.set_fixed_parameters(edata.fixed_parameters_pre_equilibration) if edata.pscale: model.set_parameter_scale(edata.pscale) - if edata.parameters: - model.set_parameters(edata.parameters) + if edata.free_parameters: + model.set_parameters(edata.free_parameters) if edata.plist: model.set_parameter_list(edata.plist) model.set_initial_state(edata.x0) diff --git a/python/sdist/amici/gradient_check.py b/python/sdist/amici/gradient_check.py index 38dd439f7b..2c7cdba47b 100644 --- a/python/sdist/amici/gradient_check.py +++ b/python/sdist/amici/gradient_check.py @@ -75,11 +75,11 @@ def check_finite_difference( og_plist = model.get_parameter_list() if edata: og_eplist = edata.plist - og_eparameters = edata.parameters + og_eparameters = edata.free_parameters edata.plist = plist # we always set parameters via the model below - edata.parameters = [] + edata.free_parameters = [] pscale = ( edata.pscale if len(edata.pscale) else model.get_parameter_scale() ) @@ -150,7 +150,7 @@ def check_finite_difference( model.set_parameter_list(og_plist) if edata: edata.plist = og_eplist - edata.parameters = og_eparameters + edata.free_parameters = og_eparameters def check_derivatives( @@ -179,8 +179,8 @@ def check_derivatives( are zero :param skip_fields: list of fields to skip """ - if edata and edata.parameters: - p = np.array(edata.parameters) + if edata and edata.free_parameters: + p = np.array(edata.free_parameters) else: p = np.array(model.get_parameters()) diff --git a/python/sdist/amici/pandas.py b/python/sdist/amici/pandas.py index 51451ac07b..7166494b30 100644 --- a/python/sdist/amici/pandas.py +++ b/python/sdist/amici/pandas.py @@ -418,8 +418,8 @@ def _fill_conditions_dict( for i_par, par in enumerate( _get_names_or_ids(model, "parameter", by_id=by_id) ): - if len(edata.parameters): - datadict[par] = edata.parameters[i_par] + if len(edata.free_parameters): + datadict[par] = edata.free_parameters[i_par] else: datadict[par] = model.get_parameters()[i_par] @@ -736,7 +736,7 @@ def construct_edata_from_data_frame( ) # fill in parameters - edata.parameters = ( + edata.free_parameters = ( condition[_get_names_or_ids(model, "parameter", by_id=by_id)] .astype(float) .values diff --git a/python/sdist/amici/petab/conditions.py b/python/sdist/amici/petab/conditions.py index 38e7603d13..0630c9928f 100644 --- a/python/sdist/amici/petab/conditions.py +++ b/python/sdist/amici/petab/conditions.py @@ -202,7 +202,7 @@ def _get_par(model_par, value, mapping): ] if parameters: - edata.parameters = np.asarray(parameters, dtype=float) + edata.free_parameters = np.asarray(parameters, dtype=float) if scales: edata.pscale = amici.parameter_scaling_from_int_vector(scales) diff --git a/python/sdist/amici/petab/petab_importer.py b/python/sdist/amici/petab/petab_importer.py index 1a776d0a7c..e87bc1503b 100644 --- a/python/sdist/amici/petab/petab_importer.py +++ b/python/sdist/amici/petab/petab_importer.py @@ -1037,7 +1037,7 @@ def apply_override(placeholder: str, override: sp.Basic): apply_override(placeholder, override) # TODO: set all unused placeholders to NaN to make it easier to spot problems? - edata.parameters = par_vals + edata.free_parameters = par_vals if self._debug: logger.debug("ExperimentManager.apply_parameters:") diff --git a/python/tests/test_jax.py b/python/tests/test_jax.py index 5e47699026..28b1ab539c 100644 --- a/python/tests/test_jax.py +++ b/python/tests/test_jax.py @@ -132,7 +132,7 @@ def _test_model(amici_module, jax_module, ts, p, k): amici_model.set_parameters(np.asarray(p, dtype=np.float64)) amici_model.set_fixed_parameters(np.asarray(k, dtype=np.float64)) edata = amici.ExpData(sol_amici_ref, 1.0, 1.0) - edata.parameters = amici_model.get_parameters() + edata.free_parameters = amici_model.get_parameters() edata.fixed_parameters = amici_model.get_fixed_parameters() edata.pscale = amici_model.get_parameter_scale() amici_solver = amici_model.create_solver() @@ -185,7 +185,7 @@ def check_fields_jax( ts_posteq = np.array([]) par_dict = { - **dict(zip(parameter_ids, edata.parameters)), + **dict(zip(parameter_ids, edata.free_parameters)), **dict(zip(fixed_parameter_ids, edata.fixed_parameters)), } diff --git a/python/tests/test_preequilibration.py b/python/tests/test_preequilibration.py index 0c30a3a34b..db90a44ffe 100644 --- a/python/tests/test_preequilibration.py +++ b/python/tests/test_preequilibration.py @@ -279,7 +279,7 @@ def test_parameter_in_expdata(preeq_fixture): model.set_parameter_list([i for i in reversed(model.get_parameter_list())]) # set ExpData parameters - edata.parameters = model.get_parameters() + edata.free_parameters = model.get_parameters() # perturb model parameters model.set_parameters(tuple(p * 2 for p in model.get_parameters())) diff --git a/src/edata.cpp b/src/edata.cpp index d626deaa20..0b4f3f2e94 100644 --- a/src/edata.cpp +++ b/src/edata.cpp @@ -32,13 +32,13 @@ ExpData::ExpData( ExpData::ExpData( int const nytrue, int const nztrue, int const nmaxevent, - std::vector ts, std::vector fixedParameters + std::vector ts, std::vector fixed_parameters ) : SimulationParameters(ts) , nytrue_(nytrue) , nztrue_(nztrue) , nmaxevent_(nmaxevent) { - this->fixed_parameters = std::move(fixedParameters); + this->fixed_parameters = std::move(fixed_parameters); apply_dimensions(); } @@ -459,14 +459,14 @@ void ConditionContext::apply_condition( // this needs to be set in the model before handling initial state // sensitivities, which may be unscaled using model parameter values - if (!edata->parameters.empty()) { - if (edata->parameters.size() != (unsigned)model_->np()) + if (!edata->free_parameters.empty()) { + if (edata->free_parameters.size() != (unsigned)model_->np()) throw AmiException( "Number of parameters (%d) in model does not" " match ExpData (%zd).", - model_->np(), edata->parameters.size() + model_->np(), edata->free_parameters.size() ); - model_->set_parameters(edata->parameters); + model_->set_parameters(edata->free_parameters); } if (!edata->x0.empty()) { diff --git a/src/hdf5.cpp b/src/hdf5.cpp index 9c40d5a4a3..f613bfdef9 100644 --- a/src/hdf5.cpp +++ b/src/hdf5.cpp @@ -206,7 +206,7 @@ std::unique_ptr read_exp_data_from_hdf5( } if (location_exists(file, hdf5Root + "/parameters")) { - edata->parameters + edata->free_parameters = get_double_1d_dataset(file, hdf5Root + "/parameters"); } @@ -321,9 +321,9 @@ void write_exp_data_to_hdf5( "reinitializeFixedParameterInitialStates", &int_attr, 1 ); - if (!edata.parameters.empty()) + if (!edata.free_parameters.empty()) create_and_write_double_1d_dataset( - file, hdf5Location + "/parameters", edata.parameters + file, hdf5Location + "/parameters", edata.free_parameters ); if (!edata.x0.empty()) From 7bed4aac9a63d1cc8e447486953abca02ca85a35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Wed, 12 Nov 2025 13:47:58 +0000 Subject: [PATCH 06/23] fixups cpp --- include/amici/serialization.h | 2 +- python/tests/test_edata.py | 4 ++-- src/model.cpp | 38 +++++++++++++++++------------------ src/simulation_parameters.cpp | 2 +- swig/edata.i | 4 ++-- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/include/amici/serialization.h b/include/amici/serialization.h index fd19d2107c..d441fd1597 100644 --- a/include/amici/serialization.h +++ b/include/amici/serialization.h @@ -169,7 +169,7 @@ void serialize( ar & s.fixed_parameters; ar & s.fixed_parameters_pre_equilibration; ar & s.fixed_parameters_presimulation; - ar & s.parameters; + ar & s.free_parameters; ar & s.x0; ar & s.sx0; ar & s.pscale; diff --git a/python/tests/test_edata.py b/python/tests/test_edata.py index 1501898f7a..a6e9a81583 100644 --- a/python/tests/test_edata.py +++ b/python/tests/test_edata.py @@ -35,12 +35,12 @@ def test_edata_sensi_unscaling(model_units_module): # noqa: F811 edata0 = amici.ExpData(model) edata0.pscale = amici_parameter_scales_log10 - edata0.parameters = parameters0 + edata0.free_parameters = parameters0 edata0.sx0 = sx0 edata1 = amici.ExpData(model) edata1.pscale = amici_parameter_scales_log10 - edata1.parameters = parameters1 + edata1.free_parameters = parameters1 edata1.sx0 = sx0 rdata0 = amici.run_simulation(model, solver, edata0) diff --git a/src/model.cpp b/src/model.cpp index 398a24342d..88da63d296 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -190,7 +190,7 @@ Model::Model( model_dimensions.validate(); Expects( model_dimensions.np - == gsl::narrow(simulation_parameters_.parameters.size()) + == gsl::narrow(simulation_parameters_.free_parameters.size()) ); Expects( model_dimensions.nk @@ -204,7 +204,7 @@ Model::Model( ); unscale_parameters( - simulation_parameters_.parameters, simulation_parameters_.pscale, + simulation_parameters_.free_parameters, simulation_parameters_.pscale, state_.unscaled_parameters ); state_.fixed_parameters = simulation_parameters_.fixed_parameters; @@ -500,7 +500,7 @@ void Model::set_parameter_scale(ParameterScaling pscale) { ); scale_parameters( state_.unscaled_parameters, simulation_parameters_.pscale, - simulation_parameters_.parameters + simulation_parameters_.free_parameters ); sx0data_.clear(); } @@ -508,7 +508,7 @@ void Model::set_parameter_scale(ParameterScaling pscale) { void Model::set_parameter_scale( std::vector const& pscaleVec ) { - if (pscaleVec.size() != simulation_parameters_.parameters.size()) + if (pscaleVec.size() != simulation_parameters_.free_parameters.size()) throw AmiException( "Dimension mismatch. Size of parameter scaling does " "not match number of model parameters." @@ -516,7 +516,7 @@ void Model::set_parameter_scale( simulation_parameters_.pscale = pscaleVec; scale_parameters( state_.unscaled_parameters, simulation_parameters_.pscale, - simulation_parameters_.parameters + simulation_parameters_.free_parameters ); sx0data_.clear(); } @@ -526,7 +526,7 @@ std::vector const& Model::get_unscaled_parameters() const { } std::vector const& Model::get_parameters() const { - return simulation_parameters_.parameters; + return simulation_parameters_.free_parameters; } realtype Model::get_parameter_by_id(std::string const& par_id) const { @@ -535,7 +535,7 @@ realtype Model::get_parameter_by_id(std::string const& par_id) const { "Could not access parameters by id as they are not set" ); return get_value_by_id( - get_parameter_ids(), simulation_parameters_.parameters, par_id, + get_parameter_ids(), simulation_parameters_.free_parameters, par_id, "parameters", "id" ); } @@ -546,7 +546,7 @@ realtype Model::get_parameter_by_name(std::string const& par_name) const { "Could not access parameters by name as they are not set" ); return get_value_by_id( - get_parameter_names(), simulation_parameters_.parameters, par_name, + get_parameter_names(), simulation_parameters_.free_parameters, par_name, "parameters", "name" ); } @@ -557,10 +557,10 @@ void Model::set_parameters(std::vector const& p) { "Dimension mismatch. Size of parameters does not " "match number of model parameters." ); - simulation_parameters_.parameters = p; - state_.unscaled_parameters.resize(simulation_parameters_.parameters.size()); + simulation_parameters_.free_parameters = p; + state_.unscaled_parameters.resize(simulation_parameters_.free_parameters.size()); unscale_parameters( - simulation_parameters_.parameters, simulation_parameters_.pscale, + simulation_parameters_.free_parameters, simulation_parameters_.pscale, state_.unscaled_parameters ); } @@ -587,11 +587,11 @@ void Model::set_parameter_by_id( ); set_value_by_id( - get_parameter_ids(), simulation_parameters_.parameters, value, par_id, + get_parameter_ids(), simulation_parameters_.free_parameters, value, par_id, "parameter", "id" ); unscale_parameters( - simulation_parameters_.parameters, simulation_parameters_.pscale, + simulation_parameters_.free_parameters, simulation_parameters_.pscale, state_.unscaled_parameters ); } @@ -604,11 +604,11 @@ int Model::set_parameters_by_id_regex( "Could not access parameters by id as they are not set" ); int n_found = set_value_by_id_regex( - get_parameter_ids(), simulation_parameters_.parameters, value, + get_parameter_ids(), simulation_parameters_.free_parameters, value, par_id_regex, "parameter", "id" ); unscale_parameters( - simulation_parameters_.parameters, simulation_parameters_.pscale, + simulation_parameters_.free_parameters, simulation_parameters_.pscale, state_.unscaled_parameters ); return n_found; @@ -623,11 +623,11 @@ void Model::set_parameter_by_name( ); set_value_by_id( - get_parameter_names(), simulation_parameters_.parameters, value, + get_parameter_names(), simulation_parameters_.free_parameters, value, par_name, "parameter", "name" ); unscale_parameters( - simulation_parameters_.parameters, simulation_parameters_.pscale, + simulation_parameters_.free_parameters, simulation_parameters_.pscale, state_.unscaled_parameters ); } @@ -654,12 +654,12 @@ int Model::set_parameters_by_name_regex( ); int n_found = set_value_by_id_regex( - get_parameter_names(), simulation_parameters_.parameters, value, + get_parameter_names(), simulation_parameters_.free_parameters, value, par_name_regex, "parameter", "name" ); unscale_parameters( - simulation_parameters_.parameters, simulation_parameters_.pscale, + simulation_parameters_.free_parameters, simulation_parameters_.pscale, state_.unscaled_parameters ); return n_found; diff --git a/src/simulation_parameters.cpp b/src/simulation_parameters.cpp index 65abaaf983..b6b586bead 100644 --- a/src/simulation_parameters.cpp +++ b/src/simulation_parameters.cpp @@ -15,7 +15,7 @@ bool operator==(SimulationParameters const& a, SimulationParameters const& b) { a.fixed_parameters_presimulation, b.fixed_parameters_presimulation ) - && is_equal(a.parameters, b.parameters) && (a.plist == b.plist) + && is_equal(a.free_parameters, b.free_parameters) && (a.plist == b.plist) && (a.pscale == b.pscale) && (a.reinitialize_fixed_parameter_initial_states == b.reinitialize_fixed_parameter_initial_states) diff --git a/swig/edata.i b/swig/edata.i index 257b4cefd4..545deacffa 100644 --- a/swig/edata.i +++ b/swig/edata.i @@ -68,8 +68,8 @@ def _edata_repr(self: "ExpData"): custom_simulation_settings.append(f"{len(self.reinitialization_state_idxs_sim)} reinitialized states (simulation)") if self.reinitialize_fixed_parameter_initial_states and self.reinitialization_state_idxs_presim: custom_simulation_settings.append(f"{len(self.reinitialization_state_idxs_presim)} reinitialized states (presimulation)") - if self.parameters: - custom_simulation_settings.append(f"parameters") + if self.free_parameters: + custom_simulation_settings.append(f"free parameters") if self.x0: custom_simulation_settings.append(f"initial states") if self.sx0: From 089ac008131f5f2184215d93f991195e386bd144 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Wed, 12 Nov 2025 16:46:24 +0000 Subject: [PATCH 07/23] fixup id confusion --- python/sdist/amici/importers/sbml/__init__.py | 18 +++++++++--------- swig/edata.i | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/python/sdist/amici/importers/sbml/__init__.py b/python/sdist/amici/importers/sbml/__init__.py index 508bd83503..7c1602e4ef 100644 --- a/python/sdist/amici/importers/sbml/__init__.py +++ b/python/sdist/amici/importers/sbml/__init__.py @@ -709,7 +709,7 @@ def _process_sbml( self.check_support() self._gather_locals(hardcode_symbols=hardcode_symbols) self._process_parameters( - fixed_parameters=fixed_parameters, + fixed_parameter_ids=fixed_parameters, hardcode_symbols=hardcode_symbols, ) self._process_compartments() @@ -1191,24 +1191,24 @@ def _process_annotations(self) -> None: @log_execution_time("processing SBML parameters", logger) def _process_parameters( self, - fixed_parameters: list[str] = None, - hardcode_symbols: Sequence[str] = None, + fixed_parameter_ids: list[str] | None = None, + hardcode_symbols: Sequence[str] | None = None, ) -> None: """ Get parameter information from SBML model. - :param fixed_parameters: + :param fixed_parameter_ids: SBML Ids to be excluded from sensitivity analysis :param hardcode_symbols: Parameter IDs to be replaced by their values in the generated model. """ - if fixed_parameters is None: - fixed_parameters = [] + if fixed_parameter_ids is None: + fixed_parameter_ids = [] # Ensure specified constant parameters exist in the model - for parameter in fixed_parameters: + for parameter in fixed_parameter_ids: if not self.sbml.getParameter(parameter): raise KeyError( f"Cannot make {parameter} a constant parameter: " @@ -1226,7 +1226,7 @@ def _process_parameters( fixed_parameters = [ parameter for parameter in self.sbml.getListOfParameters() - if parameter.getId() in fixed_parameters + if parameter.getId() in fixed_parameter_ids ] for parameter in fixed_parameters: ia_math = par_id_to_ia.get(parameter.getId()) @@ -1245,7 +1245,7 @@ def _process_parameters( parameters = [ parameter for parameter in self.sbml.getListOfParameters() - if parameter.getId() not in fixed_parameters + if parameter.getId() not in fixed_parameter_ids and ( (ia_math := par_id_to_ia.get(parameter.getId())) is None or ia_math.is_Number diff --git a/swig/edata.i b/swig/edata.i index 545deacffa..a760b14838 100644 --- a/swig/edata.i +++ b/swig/edata.i @@ -56,13 +56,13 @@ def _edata_repr(self: "ExpData"): if self.pscale: custom_simulation_settings.append(f"parameter scales") if self.fixed_parameters: - custom_simulation_settings.append(f"constants") + custom_simulation_settings.append(f"fixed parameters") if self.fixed_parameters_pre_equilibration: custom_simulation_settings.append(f"pre-equilibration condition") if self.t_presim: tmp = f"pre-simulation condition (t={self.t_presim})" if self.fixed_parameters_presimulation: - tmp += " with custom constants" + tmp += " with custom fixed parameters" custom_simulation_settings.append(tmp) if self.reinitialize_fixed_parameter_initial_states and self.reinitialization_state_idxs_sim: custom_simulation_settings.append(f"{len(self.reinitialization_state_idxs_sim)} reinitialized states (simulation)") From fbe975b71d6e100a9635aa76a9e83a92860fe96b Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 12 Nov 2025 18:50:44 +0100 Subject: [PATCH 08/23] fixup --- swig/amici.i | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swig/amici.i b/swig/amici.i index 311d347494..9fb32953da 100644 --- a/swig/amici.i +++ b/swig/amici.i @@ -157,7 +157,7 @@ wrap_unique_ptr(ExpDataPtr, amici::ExpData) %naturalvar amici::SimulationParameters::x0; %naturalvar amici::SimulationParameters::sx0; -%naturalvar amici::SimulationParameters::parameters; +%naturalvar amici::SimulationParameters::free_parameters; %naturalvar amici::SimulationParameters::pscale; %naturalvar amici::SimulationParameters::plist; %naturalvar amici::SimulationParameters::fixed_parameters; From d1435eca5707f6e2461e803527e9364735e72fd1 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Wed, 12 Nov 2025 19:21:28 +0100 Subject: [PATCH 09/23] doc --- doc/glossary.rst | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/doc/glossary.rst b/doc/glossary.rst index 942ab048f6..a3a88cdc24 100644 --- a/doc/glossary.rst +++ b/doc/glossary.rst @@ -27,10 +27,20 @@ Glossary fixed parameters In AMICI, *fixed parameters* are parameters with respect to which no - sensitivities are computed. They usually correspond to experimental - conditions. For fixed parameters, different values can be set for + sensitivities are computed. The values of fixed parameters can changed. + "fixed" here refers to the fact that these parameters are fixed + in context of parameter estimation. + Fixed parameters encode, for example, experimental conditions. + For fixed parameters, different values can be set for :term:`pre-equilibration`, :term:`pre-simulation` and the main simulation. See also :term:`simulation periods`. + See also :term:`free parameters`. + + free parameters + In AMICI, *free parameters* are parameters with respect to which + sensitivities are computed. These are typically the parameters that + are estimated in a parameter estimation problem. + See also :term:`fixed parameters`. IDAS `IDAS `_ is a From f1d947fff93f306b881b61e9ff81d5eada2af458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Thu, 13 Nov 2025 09:29:33 +0000 Subject: [PATCH 10/23] get_parameter_names --- .../example_splines/ExampleSplines.ipynb | 6 +++--- include/amici/model.h | 10 +++++----- models/model_calvetti_py/model_calvetti_py.h | 8 ++++---- models/model_events_py/model_events_py.h | 8 ++++---- .../model_jakstat_adjoint_py.h | 8 ++++---- .../model_nested_events_py.h | 8 ++++---- models/model_neuron_py/model_neuron_py.h | 8 ++++---- models/model_robertson_py/model_robertson_py.h | 8 ++++---- .../model_steadystate_py.h | 8 ++++---- .../sundials/templates/model_header.template.h | 8 ++++---- python/tests/test_sbml_import.py | 2 +- src/model.cpp | 18 +++++++++--------- tests/cpp/testfunctions.h | 2 +- 13 files changed, 51 insertions(+), 51 deletions(-) diff --git a/doc/examples/example_splines/ExampleSplines.ipynb b/doc/examples/example_splines/ExampleSplines.ipynb index 53358d0fc9..5b2080eac1 100644 --- a/doc/examples/example_splines/ExampleSplines.ipynb +++ b/doc/examples/example_splines/ExampleSplines.ipynb @@ -589,9 +589,9 @@ "source": [ "# Sensitivities with respect to the spline values can be computed\n", "fig, ax = plt.subplots()\n", - "ax.plot(rdata[\"t\"], rdata.sx[:, 0], label=model.get_parameter_names()[0])\n", - "ax.plot(rdata[\"t\"], rdata.sx[:, 1], label=model.get_parameter_names()[1])\n", - "ax.plot(rdata[\"t\"], rdata.sx[:, 2], label=model.get_parameter_names()[2])\n", + "ax.plot(rdata[\"t\"], rdata.sx[:, 0], label=model.get_free_parameter_names()[0])\n", + "ax.plot(rdata[\"t\"], rdata.sx[:, 1], label=model.get_free_parameter_names()[1])\n", + "ax.plot(rdata[\"t\"], rdata.sx[:, 2], label=model.get_free_parameter_names()[2])\n", "ax.set_xlabel(\"time\")\n", "ax.set_ylabel(\"sensitivity\")\n", "ax.legend();" diff --git a/include/amici/model.h b/include/amici/model.h index 1fc7bd1f78..f3b9d90083 100644 --- a/include/amici/model.h +++ b/include/amici/model.h @@ -565,18 +565,18 @@ class Model : public AbstractModel, public ModelDimensions { virtual std::string get_name() const; /** - * @brief Report whether the model has parameter names set. + * @brief Report whether the model has free parameter names set. * - * @return Boolean indicating whether parameter names were set. Also returns + * @return Boolean indicating whether freeparameter names were set. Also returns * `true` if the number of corresponding variables is just zero. */ - virtual bool has_parameter_names() const; + virtual bool has_free_parameter_names() const; /** - * @brief Get names of the model parameters. + * @brief Get names of the free model parameters. * @return The parameter names */ - virtual std::vector get_parameter_names() const; + virtual std::vector get_free_parameter_names() const; /** * @brief Report whether the model has state names set. diff --git a/models/model_calvetti_py/model_calvetti_py.h b/models/model_calvetti_py/model_calvetti_py.h index 97de93af24..e6a1682aa0 100644 --- a/models/model_calvetti_py/model_calvetti_py.h +++ b/models/model_calvetti_py/model_calvetti_py.h @@ -14,7 +14,7 @@ class Solver; namespace model_model_calvetti_py { -extern std::array parameter_names; +extern std::array free_parameter_names; extern std::array fixed_parameter_names; extern std::array state_names; extern std::array observable_names; @@ -424,9 +424,9 @@ class Model_model_calvetti_py : public amici::Model_DAE { * @brief Get names of the model parameters * @return the names */ - std::vector get_parameter_names() const override { - return std::vector(parameter_names.begin(), - parameter_names.end()); + std::vector get_free_parameter_names() const override { + return std::vector(free_parameter_names.begin(), + free_parameter_names.end()); } /** diff --git a/models/model_events_py/model_events_py.h b/models/model_events_py/model_events_py.h index f452c05132..b8c5170485 100644 --- a/models/model_events_py/model_events_py.h +++ b/models/model_events_py/model_events_py.h @@ -14,7 +14,7 @@ class Solver; namespace model_model_events_py { -extern std::array parameter_names; +extern std::array free_parameter_names; extern std::array fixed_parameter_names; extern std::array state_names; extern std::array observable_names; @@ -446,9 +446,9 @@ class Model_model_events_py : public amici::Model_ODE { * @brief Get names of the model parameters * @return the names */ - std::vector get_parameter_names() const override { - return std::vector(parameter_names.begin(), - parameter_names.end()); + std::vector get_free_parameter_names() const override { + return std::vector(free_parameter_names.begin(), + free_parameter_names.end()); } /** diff --git a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h index 1520bbcf02..7c9c7fd2db 100644 --- a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h +++ b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h @@ -14,7 +14,7 @@ class Solver; namespace model_model_jakstat_adjoint_py { -extern std::array parameter_names; +extern std::array free_parameter_names; extern std::array fixed_parameter_names; extern std::array state_names; extern std::array observable_names; @@ -419,9 +419,9 @@ class Model_model_jakstat_adjoint_py : public amici::Model_ODE { * @brief Get names of the model parameters * @return the names */ - std::vector get_parameter_names() const override { - return std::vector(parameter_names.begin(), - parameter_names.end()); + std::vector get_free_parameter_names() const override { + return std::vector(free_parameter_names.begin(), + free_parameter_names.end()); } /** diff --git a/models/model_nested_events_py/model_nested_events_py.h b/models/model_nested_events_py/model_nested_events_py.h index b90345495f..65157e7d4a 100644 --- a/models/model_nested_events_py/model_nested_events_py.h +++ b/models/model_nested_events_py/model_nested_events_py.h @@ -14,7 +14,7 @@ class Solver; namespace model_model_nested_events_py { -extern std::array parameter_names; +extern std::array free_parameter_names; extern std::array fixed_parameter_names; extern std::array state_names; extern std::array observable_names; @@ -419,9 +419,9 @@ class Model_model_nested_events_py : public amici::Model_ODE { * @brief Get names of the model parameters * @return the names */ - std::vector get_parameter_names() const override { - return std::vector(parameter_names.begin(), - parameter_names.end()); + std::vector get_free_parameter_names() const override { + return std::vector(free_parameter_names.begin(), + free_parameter_names.end()); } /** diff --git a/models/model_neuron_py/model_neuron_py.h b/models/model_neuron_py/model_neuron_py.h index dbbcc5b663..a30664dac7 100644 --- a/models/model_neuron_py/model_neuron_py.h +++ b/models/model_neuron_py/model_neuron_py.h @@ -14,7 +14,7 @@ class Solver; namespace model_model_neuron_py { -extern std::array parameter_names; +extern std::array free_parameter_names; extern std::array fixed_parameter_names; extern std::array state_names; extern std::array observable_names; @@ -441,9 +441,9 @@ class Model_model_neuron_py : public amici::Model_ODE { * @brief Get names of the model parameters * @return the names */ - std::vector get_parameter_names() const override { - return std::vector(parameter_names.begin(), - parameter_names.end()); + std::vector get_free_parameter_names() const override { + return std::vector(free_parameter_names.begin(), + free_parameter_names.end()); } /** diff --git a/models/model_robertson_py/model_robertson_py.h b/models/model_robertson_py/model_robertson_py.h index 174b8e9c56..305983e545 100644 --- a/models/model_robertson_py/model_robertson_py.h +++ b/models/model_robertson_py/model_robertson_py.h @@ -14,7 +14,7 @@ class Solver; namespace model_model_robertson_py { -extern std::array parameter_names; +extern std::array free_parameter_names; extern std::array fixed_parameter_names; extern std::array state_names; extern std::array observable_names; @@ -403,9 +403,9 @@ class Model_model_robertson_py : public amici::Model_DAE { * @brief Get names of the model parameters * @return the names */ - std::vector get_parameter_names() const override { - return std::vector(parameter_names.begin(), - parameter_names.end()); + std::vector get_free_parameter_names() const override { + return std::vector(free_parameter_names.begin(), + free_parameter_names.end()); } /** diff --git a/models/model_steadystate_py/model_steadystate_py.h b/models/model_steadystate_py/model_steadystate_py.h index 67b160e8fd..955eebf40c 100644 --- a/models/model_steadystate_py/model_steadystate_py.h +++ b/models/model_steadystate_py/model_steadystate_py.h @@ -14,7 +14,7 @@ class Solver; namespace model_model_steadystate_py { -extern std::array parameter_names; +extern std::array free_parameter_names; extern std::array fixed_parameter_names; extern std::array state_names; extern std::array observable_names; @@ -403,9 +403,9 @@ class Model_model_steadystate_py : public amici::Model_ODE { * @brief Get names of the model parameters * @return the names */ - std::vector get_parameter_names() const override { - return std::vector(parameter_names.begin(), - parameter_names.end()); + std::vector get_free_parameter_names() const override { + return std::vector(free_parameter_names.begin(), + free_parameter_names.end()); } /** diff --git a/python/sdist/amici/exporters/sundials/templates/model_header.template.h b/python/sdist/amici/exporters/sundials/templates/model_header.template.h index ca95459a65..69360edb38 100644 --- a/python/sdist/amici/exporters/sundials/templates/model_header.template.h +++ b/python/sdist/amici/exporters/sundials/templates/model_header.template.h @@ -14,7 +14,7 @@ class Solver; namespace model_TPL_MODELNAME { -extern std::array parameter_names; +extern std::array free_parameter_names; extern std::array fixed_parameter_names; extern std::array state_names; extern std::array observable_names; @@ -291,9 +291,9 @@ class Model_TPL_MODELNAME : public amici::Model_TPL_MODEL_TYPE_UPPER { * @brief Get names of the model parameters * @return the names */ - std::vector get_parameter_names() const override { - return std::vector(parameter_names.begin(), - parameter_names.end()); + std::vector get_free_parameter_names() const override { + return std::vector(free_parameter_names.begin(), + free_parameter_names.end()); } /** diff --git a/python/tests/test_sbml_import.py b/python/tests/test_sbml_import.py index 5e576c6b60..288c7aedae 100644 --- a/python/tests/test_sbml_import.py +++ b/python/tests/test_sbml_import.py @@ -795,7 +795,7 @@ def _test_set_parameters_by_dict(model_module): assert model.get_parameters() == old_parameter_values # Same for by-name - parameter_names = model.get_parameter_names() + parameter_names = model.get_free_parameter_names() change_par_name = parameter_names[-1] model.set_parameter_by_name({change_par_name: new_par_val}) assert model.get_parameter_by_name(change_par_name) == new_par_val diff --git a/src/model.cpp b/src/model.cpp index 88da63d296..78ef4cd0ee 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -541,12 +541,12 @@ realtype Model::get_parameter_by_id(std::string const& par_id) const { } realtype Model::get_parameter_by_name(std::string const& par_name) const { - if (!has_parameter_names()) + if (!has_free_parameter_names()) throw AmiException( "Could not access parameters by name as they are not set" ); return get_value_by_id( - get_parameter_names(), simulation_parameters_.free_parameters, par_name, + get_free_parameter_names(), simulation_parameters_.free_parameters, par_name, "parameters", "name" ); } @@ -617,13 +617,13 @@ int Model::set_parameters_by_id_regex( void Model::set_parameter_by_name( std::string const& par_name, realtype const value ) { - if (!has_parameter_names()) + if (!has_free_parameter_names()) throw AmiException( "Could not access parameters by name as they are not set" ); set_value_by_id( - get_parameter_names(), simulation_parameters_.free_parameters, value, + get_free_parameter_names(), simulation_parameters_.free_parameters, value, par_name, "parameter", "name" ); unscale_parameters( @@ -648,13 +648,13 @@ void Model::set_parameter_by_name( int Model::set_parameters_by_name_regex( std::string const& par_name_regex, realtype value ) { - if (!has_parameter_names()) + if (!has_free_parameter_names()) throw AmiException( "Could not access parameters by name as they are not set" ); int n_found = set_value_by_id_regex( - get_parameter_names(), simulation_parameters_.free_parameters, value, + get_free_parameter_names(), simulation_parameters_.free_parameters, value, par_name_regex, "parameter", "name" ); @@ -760,11 +760,11 @@ int Model::set_fixed_parameters_by_name_regex( std::string Model::get_name() const { return ""; } -bool Model::has_parameter_names() const { - return np() == 0 || !get_parameter_names().empty(); +bool Model::has_free_parameter_names() const { + return np() == 0 || !get_free_parameter_names().empty(); } -std::vector Model::get_parameter_names() const { return {}; } +std::vector Model::get_free_parameter_names() const { return {}; } bool Model::has_state_names() const { return nx_rdata == 0 || !get_state_names().empty(); diff --git a/tests/cpp/testfunctions.h b/tests/cpp/testfunctions.h index fea4ad0726..eda3c3848a 100644 --- a/tests/cpp/testfunctions.h +++ b/tests/cpp/testfunctions.h @@ -147,7 +147,7 @@ class Model_Test : public Model { throw AmiException("not implemented"); } - std::vector get_parameter_names() const override { + std::vector get_free_parameter_names() const override { return getVariableNames("p", np()); } From 40190b46b1b398e321314ded4169fe910b37c484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Thu, 13 Nov 2025 18:00:19 +0000 Subject: [PATCH 11/23] free parameter ids --- doc/examples/example_errors.ipynb | 2 +- .../GettingStartedExtended.ipynb | 6 +-- include/amici/model.h | 4 +- models/model_calvetti_py/main.cpp | 4 +- models/model_calvetti_py/model_calvetti_py.h | 8 ++-- models/model_dirac_py/main.cpp | 4 +- models/model_dirac_py/model_dirac_py.h | 8 ++-- models/model_events_py/main.cpp | 4 +- models/model_jakstat_adjoint_py/main.cpp | 4 +- .../model_jakstat_adjoint_py.h | 8 ++-- models/model_nested_events_py/main.cpp | 4 +- .../model_nested_events_py.h | 6 +-- models/model_neuron_py/main.cpp | 4 +- models/model_neuron_py/model_neuron_py.h | 8 ++-- models/model_robertson_py/main.cpp | 4 +- .../model_robertson_py/model_robertson_py.h | 8 ++-- models/model_steadystate_py/main.cpp | 4 +- .../model_steadystate_py.h | 8 ++-- python/sdist/amici/adapters/fiddy.py | 41 +++++++++-------- .../sundials/templates/main.template.cpp | 4 +- .../templates/model_header.template.h | 8 ++-- python/sdist/amici/gradient_check.py | 4 +- python/sdist/amici/numpy.py | 4 +- python/sdist/amici/petab/conditions.py | 6 +-- python/sdist/amici/petab/import_helpers.py | 2 +- python/sdist/amici/petab/parameter_mapping.py | 2 +- python/sdist/amici/petab/petab_importer.py | 24 +++++----- python/sdist/amici/petab/simulations.py | 6 ++- python/tests/adapters/test_fiddy.py | 10 ++--- python/tests/petab_/test_petab_problem.py | 10 +++-- python/tests/splines_utils.py | 2 +- python/tests/test_events.py | 6 +-- python/tests/test_jax.py | 13 +++--- python/tests/test_preequilibration.py | 2 +- python/tests/test_sbml_import.py | 8 ++-- python/tests/test_swig_interface.py | 8 ++-- python/tests/util.py | 2 +- src/model.cpp | 44 +++++++++---------- tests/cpp/testfunctions.h | 2 +- tests/sbml/testSBMLSuite.py | 2 +- tests/sbml/utils.py | 2 +- 41 files changed, 162 insertions(+), 148 deletions(-) diff --git a/doc/examples/example_errors.ipynb b/doc/examples/example_errors.ipynb index acc4b439a7..cc080d167a 100644 --- a/doc/examples/example_errors.ipynb +++ b/doc/examples/example_errors.ipynb @@ -626,7 +626,7 @@ "\n", "unscaled_parameter = dict(\n", " zip(\n", - " amici_model.get_parameter_ids(),\n", + " amici_model.get_free_parameter_ids(),\n", " starmap(\n", " amici.unscale_parameter, zip(edata.free_parameters, edata.pscale)\n", " ),\n", diff --git a/doc/examples/getting_started_extended/GettingStartedExtended.ipynb b/doc/examples/getting_started_extended/GettingStartedExtended.ipynb index 80d219cc3f..94c6463039 100644 --- a/doc/examples/getting_started_extended/GettingStartedExtended.ipynb +++ b/doc/examples/getting_started_extended/GettingStartedExtended.ipynb @@ -371,7 +371,7 @@ "model = model_module.get_model()\n", "\n", "print(\"Model name: \", model.get_name())\n", - "print(\"Model parameters: \", model.get_parameter_ids())\n", + "print(\"Model parameters: \", model.get_free_parameter_ids())\n", "print(\"Model outputs: \", model.get_observable_ids())\n", "print(\"Model state variables: \", model.get_state_ids())" ] @@ -415,7 +415,7 @@ "print(\n", " \"Simulation was run using model default parameters as specified in the SBML model:\"\n", ")\n", - "print(dict(zip(model.get_parameter_ids(), model.get_parameters())))" + "print(dict(zip(model.get_free_parameter_ids(), model.get_parameters())))" ] }, { @@ -1113,7 +1113,7 @@ "model = model_module.get_model()\n", "p_orig = np.array(model.get_parameters())\n", "p_orig[\n", - " list(model.get_parameter_ids()).index(\"observable_x1withsigma_sigma\")\n", + " list(model.get_free_parameter_ids()).index(\"observable_x1withsigma_sigma\")\n", "] = 0.1 # Change default parameter\n", "model.set_parameters(p_orig)\n", "model.set_parameter_scale(amici.ParameterScaling.none)\n", diff --git a/include/amici/model.h b/include/amici/model.h index f3b9d90083..0c7e8cd84e 100644 --- a/include/amici/model.h +++ b/include/amici/model.h @@ -642,13 +642,13 @@ class Model : public AbstractModel, public ModelDimensions { * @return Boolean indicating whether parameter IDs were set. Also returns * `true` if the number of corresponding variables is just zero. */ - virtual bool has_parameter_ids() const; + virtual bool has_free_parameter_ids() const; /** * @brief Get IDs of the model parameters. * @return Parameter IDs */ - virtual std::vector get_parameter_ids() const; + virtual std::vector get_free_parameter_ids() const; /** * @brief Report whether the model has state IDs set. diff --git a/models/model_calvetti_py/main.cpp b/models/model_calvetti_py/main.cpp index 41cbc62010..d6969550af 100644 --- a/models/model_calvetti_py/main.cpp +++ b/models/model_calvetti_py/main.cpp @@ -74,13 +74,13 @@ int main() { // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_parameter_ids(); + auto free_parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx for (int i_state = 0; i_state < rdata->nx_rdata; ++i_state) { std::cout << "\td(" << state_ids[i_state] << ")/d(" - << parameter_ids[model->plist(i_nplist)] << ") = "; + << free_parameter_ids[model->plist(i_nplist)] << ") = "; // rdata->sx is a flat 3D array in row-major ordering std::cout << rdata->sx diff --git a/models/model_calvetti_py/model_calvetti_py.h b/models/model_calvetti_py/model_calvetti_py.h index e6a1682aa0..a6e78635a5 100644 --- a/models/model_calvetti_py/model_calvetti_py.h +++ b/models/model_calvetti_py/model_calvetti_py.h @@ -20,7 +20,7 @@ extern std::array state_names; extern std::array observable_names; extern std::array observable_scalings; extern std::array expression_names; -extern std::array parameter_ids; +extern std::array free_parameter_ids; extern std::array fixed_parameter_ids; extern std::array state_ids; extern std::array observable_ids; @@ -481,9 +481,9 @@ class Model_model_calvetti_py : public amici::Model_DAE { * @brief Get ids of the model parameters * @return the ids */ - std::vector get_parameter_ids() const override { - return std::vector(parameter_ids.begin(), - parameter_ids.end()); + std::vector get_free_parameter_ids() const override { + return std::vector(free_parameter_ids.begin(), + free_parameter_ids.end()); } /** diff --git a/models/model_dirac_py/main.cpp b/models/model_dirac_py/main.cpp index 41cbc62010..d6969550af 100644 --- a/models/model_dirac_py/main.cpp +++ b/models/model_dirac_py/main.cpp @@ -74,13 +74,13 @@ int main() { // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_parameter_ids(); + auto free_parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx for (int i_state = 0; i_state < rdata->nx_rdata; ++i_state) { std::cout << "\td(" << state_ids[i_state] << ")/d(" - << parameter_ids[model->plist(i_nplist)] << ") = "; + << free_parameter_ids[model->plist(i_nplist)] << ") = "; // rdata->sx is a flat 3D array in row-major ordering std::cout << rdata->sx diff --git a/models/model_dirac_py/model_dirac_py.h b/models/model_dirac_py/model_dirac_py.h index d0c73abcc5..c9a25268e8 100644 --- a/models/model_dirac_py/model_dirac_py.h +++ b/models/model_dirac_py/model_dirac_py.h @@ -20,7 +20,7 @@ extern std::array state_names; extern std::array observable_names; extern std::array observable_scalings; extern std::array expression_names; -extern std::array parameter_ids; +extern std::array free_parameter_ids; extern std::array fixed_parameter_ids; extern std::array state_ids; extern std::array observable_ids; @@ -468,9 +468,9 @@ class Model_model_dirac_py : public amici::Model_ODE { * @brief Get ids of the model parameters * @return the ids */ - std::vector get_parameter_ids() const override { - return std::vector(parameter_ids.begin(), - parameter_ids.end()); + std::vector get_free_parameter_ids() const override { + return std::vector(free_parameter_ids.begin(), + free_parameter_ids.end()); } /** diff --git a/models/model_events_py/main.cpp b/models/model_events_py/main.cpp index 41cbc62010..d6969550af 100644 --- a/models/model_events_py/main.cpp +++ b/models/model_events_py/main.cpp @@ -74,13 +74,13 @@ int main() { // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_parameter_ids(); + auto free_parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx for (int i_state = 0; i_state < rdata->nx_rdata; ++i_state) { std::cout << "\td(" << state_ids[i_state] << ")/d(" - << parameter_ids[model->plist(i_nplist)] << ") = "; + << free_parameter_ids[model->plist(i_nplist)] << ") = "; // rdata->sx is a flat 3D array in row-major ordering std::cout << rdata->sx diff --git a/models/model_jakstat_adjoint_py/main.cpp b/models/model_jakstat_adjoint_py/main.cpp index 41cbc62010..d6969550af 100644 --- a/models/model_jakstat_adjoint_py/main.cpp +++ b/models/model_jakstat_adjoint_py/main.cpp @@ -74,13 +74,13 @@ int main() { // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_parameter_ids(); + auto free_parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx for (int i_state = 0; i_state < rdata->nx_rdata; ++i_state) { std::cout << "\td(" << state_ids[i_state] << ")/d(" - << parameter_ids[model->plist(i_nplist)] << ") = "; + << free_parameter_ids[model->plist(i_nplist)] << ") = "; // rdata->sx is a flat 3D array in row-major ordering std::cout << rdata->sx diff --git a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h index 7c9c7fd2db..06ccd44eff 100644 --- a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h +++ b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h @@ -20,7 +20,7 @@ extern std::array state_names; extern std::array observable_names; extern std::array observable_scalings; extern std::array expression_names; -extern std::array parameter_ids; +extern std::array free_parameter_ids; extern std::array fixed_parameter_ids; extern std::array state_ids; extern std::array observable_ids; @@ -476,9 +476,9 @@ class Model_model_jakstat_adjoint_py : public amici::Model_ODE { * @brief Get ids of the model parameters * @return the ids */ - std::vector get_parameter_ids() const override { - return std::vector(parameter_ids.begin(), - parameter_ids.end()); + std::vector get_free_parameter_ids() const override { + return std::vector(free_parameter_ids.begin(), + free_parameter_ids.end()); } /** diff --git a/models/model_nested_events_py/main.cpp b/models/model_nested_events_py/main.cpp index 41cbc62010..d6969550af 100644 --- a/models/model_nested_events_py/main.cpp +++ b/models/model_nested_events_py/main.cpp @@ -74,13 +74,13 @@ int main() { // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_parameter_ids(); + auto free_parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx for (int i_state = 0; i_state < rdata->nx_rdata; ++i_state) { std::cout << "\td(" << state_ids[i_state] << ")/d(" - << parameter_ids[model->plist(i_nplist)] << ") = "; + << free_parameter_ids[model->plist(i_nplist)] << ") = "; // rdata->sx is a flat 3D array in row-major ordering std::cout << rdata->sx diff --git a/models/model_nested_events_py/model_nested_events_py.h b/models/model_nested_events_py/model_nested_events_py.h index 65157e7d4a..e9d70ea315 100644 --- a/models/model_nested_events_py/model_nested_events_py.h +++ b/models/model_nested_events_py/model_nested_events_py.h @@ -476,9 +476,9 @@ class Model_model_nested_events_py : public amici::Model_ODE { * @brief Get ids of the model parameters * @return the ids */ - std::vector get_parameter_ids() const override { - return std::vector(parameter_ids.begin(), - parameter_ids.end()); + std::vector get_free_parameter_ids() const override { + return std::vector(free_parameter_ids.begin(), + free_parameter_ids.end()); } /** diff --git a/models/model_neuron_py/main.cpp b/models/model_neuron_py/main.cpp index 41cbc62010..d6969550af 100644 --- a/models/model_neuron_py/main.cpp +++ b/models/model_neuron_py/main.cpp @@ -74,13 +74,13 @@ int main() { // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_parameter_ids(); + auto free_parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx for (int i_state = 0; i_state < rdata->nx_rdata; ++i_state) { std::cout << "\td(" << state_ids[i_state] << ")/d(" - << parameter_ids[model->plist(i_nplist)] << ") = "; + << free_parameter_ids[model->plist(i_nplist)] << ") = "; // rdata->sx is a flat 3D array in row-major ordering std::cout << rdata->sx diff --git a/models/model_neuron_py/model_neuron_py.h b/models/model_neuron_py/model_neuron_py.h index a30664dac7..501011aa7f 100644 --- a/models/model_neuron_py/model_neuron_py.h +++ b/models/model_neuron_py/model_neuron_py.h @@ -20,7 +20,7 @@ extern std::array state_names; extern std::array observable_names; extern std::array observable_scalings; extern std::array expression_names; -extern std::array parameter_ids; +extern std::array free_parameter_ids; extern std::array fixed_parameter_ids; extern std::array state_ids; extern std::array observable_ids; @@ -498,9 +498,9 @@ class Model_model_neuron_py : public amici::Model_ODE { * @brief Get ids of the model parameters * @return the ids */ - std::vector get_parameter_ids() const override { - return std::vector(parameter_ids.begin(), - parameter_ids.end()); + std::vector get_free_parameter_ids() const override { + return std::vector(free_parameter_ids.begin(), + free_parameter_ids.end()); } /** diff --git a/models/model_robertson_py/main.cpp b/models/model_robertson_py/main.cpp index 41cbc62010..d6969550af 100644 --- a/models/model_robertson_py/main.cpp +++ b/models/model_robertson_py/main.cpp @@ -74,13 +74,13 @@ int main() { // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_parameter_ids(); + auto free_parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx for (int i_state = 0; i_state < rdata->nx_rdata; ++i_state) { std::cout << "\td(" << state_ids[i_state] << ")/d(" - << parameter_ids[model->plist(i_nplist)] << ") = "; + << free_parameter_ids[model->plist(i_nplist)] << ") = "; // rdata->sx is a flat 3D array in row-major ordering std::cout << rdata->sx diff --git a/models/model_robertson_py/model_robertson_py.h b/models/model_robertson_py/model_robertson_py.h index 305983e545..4e35a64e2d 100644 --- a/models/model_robertson_py/model_robertson_py.h +++ b/models/model_robertson_py/model_robertson_py.h @@ -20,7 +20,7 @@ extern std::array state_names; extern std::array observable_names; extern std::array observable_scalings; extern std::array expression_names; -extern std::array parameter_ids; +extern std::array free_parameter_ids; extern std::array fixed_parameter_ids; extern std::array state_ids; extern std::array observable_ids; @@ -460,9 +460,9 @@ class Model_model_robertson_py : public amici::Model_DAE { * @brief Get ids of the model parameters * @return the ids */ - std::vector get_parameter_ids() const override { - return std::vector(parameter_ids.begin(), - parameter_ids.end()); + std::vector get_free_parameter_ids() const override { + return std::vector(free_parameter_ids.begin(), + free_parameter_ids.end()); } /** diff --git a/models/model_steadystate_py/main.cpp b/models/model_steadystate_py/main.cpp index 41cbc62010..a7a833273f 100644 --- a/models/model_steadystate_py/main.cpp +++ b/models/model_steadystate_py/main.cpp @@ -74,13 +74,13 @@ int main() { // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_parameter_ids(); + auto parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx for (int i_state = 0; i_state < rdata->nx_rdata; ++i_state) { std::cout << "\td(" << state_ids[i_state] << ")/d(" - << parameter_ids[model->plist(i_nplist)] << ") = "; + << free_parameter_ids[model->plist(i_nplist)] << ") = "; // rdata->sx is a flat 3D array in row-major ordering std::cout << rdata->sx diff --git a/models/model_steadystate_py/model_steadystate_py.h b/models/model_steadystate_py/model_steadystate_py.h index 955eebf40c..cf57982fad 100644 --- a/models/model_steadystate_py/model_steadystate_py.h +++ b/models/model_steadystate_py/model_steadystate_py.h @@ -20,7 +20,7 @@ extern std::array state_names; extern std::array observable_names; extern std::array observable_scalings; extern std::array expression_names; -extern std::array parameter_ids; +extern std::array free_parameter_ids; extern std::array fixed_parameter_ids; extern std::array state_ids; extern std::array observable_ids; @@ -460,9 +460,9 @@ class Model_model_steadystate_py : public amici::Model_ODE { * @brief Get ids of the model parameters * @return the ids */ - std::vector get_parameter_ids() const override { - return std::vector(parameter_ids.begin(), - parameter_ids.end()); + std::vector get_free_parameter_ids() const override { + return std::vector(free_parameter_ids.begin(), + free_parameter_ids.end()); } /** diff --git a/python/sdist/amici/adapters/fiddy.py b/python/sdist/amici/adapters/fiddy.py index e90778e0b4..43587f97bd 100644 --- a/python/sdist/amici/adapters/fiddy.py +++ b/python/sdist/amici/adapters/fiddy.py @@ -111,7 +111,7 @@ def run_simulation_to_cached_functions( amici_model: amici.AmiciModel, *, cache: bool = True, - parameter_ids: list[str] = None, + free_parameter_ids: list[str] = None, amici_solver: amici.AmiciSolver = None, amici_edata: amici.AmiciExpData = None, derivative_variables: list[str] = None, @@ -128,8 +128,8 @@ def run_simulation_to_cached_functions( :param derivative_variables: The variables that derivatives will be computed or approximated for. See the keys of `all_rdata_derivatives` for options. - :param parameter_ids: - The IDs that correspond to the values in the parameter vector that is + :param free_parameter_ids: + The IDs that correspond to the values in the free parameter vector that is simulated. :param cache: Whether to cache the function calls. @@ -137,8 +137,8 @@ def run_simulation_to_cached_functions( """ if amici_solver is None: amici_solver = amici_model.create_solver() - if parameter_ids is None: - parameter_ids = amici_model.get_parameter_ids() + if free_parameter_ids is None: + free_parameter_ids = amici_model.get_free_parameter_ids() if amici_edata is not None and amici_edata.free_parameters is not None: raise NotImplementedError( "Customization of parameter values inside AMICI ExpData." @@ -152,7 +152,7 @@ def run_simulation_to_cached_functions( def run_amici_simulation( point: Type.POINT, order: SensitivityOrder ) -> ReturnData: - problem_parameters = dict(zip(parameter_ids, point, strict=True)) + problem_parameters = dict(zip(free_parameter_ids, point, strict=True)) amici_model.set_parameter_by_id(problem_parameters) amici_solver.set_sensitivity_order(order) rdata = amici.run_simulation( @@ -197,7 +197,10 @@ def derivative(point: Type.POINT, return_dict: bool = False): # Get structure dummy_point = fiddy_array( - [amici_model.get_parameter_by_id(par_id) for par_id in parameter_ids] + [ + amici_model.get_parameter_by_id(par_id) + for par_id in free_parameter_ids + ] ) dummy_rdata = run_amici_simulation( point=dummy_point, order=SensitivityOrder.first @@ -279,7 +282,7 @@ def reshape( def simulate_petab_to_cached_functions( petab_problem: petab.Problem, amici_model: amici.Model, - parameter_ids: list[str] = None, + free_parameter_ids: list[str] = None, cache: bool = True, precreate_edatas: bool = True, precreate_parameter_mapping: bool = True, @@ -298,7 +301,7 @@ def simulate_petab_to_cached_functions( :param simulate_petab: A method to simulate PEtab problems with AMICI, e.g. `amici.petab_objective.simulate_petab`. - :param parameter_ids: + :param free_parameter_ids: The IDs of the parameters, in the order that parameter values will be supplied. Defaults to `petab_problem.parameter_df.index`. :param petab_problem: @@ -319,8 +322,8 @@ def simulate_petab_to_cached_functions( * 1: A method to compute the function at a point. * 2: A method to compute the gradient at a point. """ - if parameter_ids is None: - parameter_ids = list(petab_problem.parameter_df.index) + if free_parameter_ids is None: + free_parameter_ids = list(petab_problem.parameter_df.index) if simulate_petab is None: simulate_petab = amici.petab.simulations.simulate_petab @@ -368,7 +371,7 @@ def simulate_petab_to_cached_functions( ) def simulate_petab_full(point: Type.POINT, order: SensitivityOrder): - problem_parameters = dict(zip(parameter_ids, point, strict=True)) + problem_parameters = dict(zip(free_parameter_ids, point, strict=True)) amici_solver.set_sensitivity_order(order) result = simulate_petab_partial( problem_parameters=problem_parameters, @@ -388,7 +391,7 @@ def derivative(point: Type.POINT) -> Type.POINT: raise RuntimeError("Simulation failed.") sllh = np.array( - [result[SLLH][parameter_id] for parameter_id in parameter_ids] + [result[SLLH][parameter_id] for parameter_id in free_parameter_ids] ) return sllh @@ -401,14 +404,14 @@ def derivative(point: Type.POINT) -> Type.POINT: def simulate_petab_v2_to_cached_functions( petab_simulator: PetabSimulator, - parameter_ids: list[str] = None, + free_parameter_ids: list[str] = None, cache: bool = True, ) -> tuple[Type.FUNCTION, Type.FUNCTION]: r"""Create fiddy functions for PetabSimulator. :param petab_simulator: The PEtab simulator to use. - :param parameter_ids: + :param free_parameter_ids: The IDs of the parameters, in the order that parameter values will be supplied. Defaults to the estimated parameters of the PEtab problem. :param cache: @@ -419,11 +422,11 @@ def simulate_petab_v2_to_cached_functions( * 1: A method to compute the function at a point. * 2: A method to compute the gradient at a point. """ - if parameter_ids is None: - parameter_ids = list(petab_simulator._petab_problem.x_free_ids) + if free_parameter_ids is None: + free_parameter_ids = list(petab_simulator._petab_problem.x_free_ids) def simulate(point: Type.POINT, order: SensitivityOrder) -> dict: - problem_parameters = dict(zip(parameter_ids, point, strict=True)) + problem_parameters = dict(zip(free_parameter_ids, point, strict=True)) petab_simulator.solver.set_sensitivity_order(order) result = petab_simulator.simulate( @@ -443,7 +446,7 @@ def derivative(point: Type.POINT) -> Type.POINT: raise RuntimeError("Simulation failed.") sllh = np.array( - [result[SLLH][parameter_id] for parameter_id in parameter_ids] + [result[SLLH][parameter_id] for parameter_id in free_parameter_ids] ) return sllh diff --git a/python/sdist/amici/exporters/sundials/templates/main.template.cpp b/python/sdist/amici/exporters/sundials/templates/main.template.cpp index 41cbc62010..d6969550af 100644 --- a/python/sdist/amici/exporters/sundials/templates/main.template.cpp +++ b/python/sdist/amici/exporters/sundials/templates/main.template.cpp @@ -74,13 +74,13 @@ int main() { // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_parameter_ids(); + auto free_parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx for (int i_state = 0; i_state < rdata->nx_rdata; ++i_state) { std::cout << "\td(" << state_ids[i_state] << ")/d(" - << parameter_ids[model->plist(i_nplist)] << ") = "; + << free_parameter_ids[model->plist(i_nplist)] << ") = "; // rdata->sx is a flat 3D array in row-major ordering std::cout << rdata->sx diff --git a/python/sdist/amici/exporters/sundials/templates/model_header.template.h b/python/sdist/amici/exporters/sundials/templates/model_header.template.h index 69360edb38..52c972b395 100644 --- a/python/sdist/amici/exporters/sundials/templates/model_header.template.h +++ b/python/sdist/amici/exporters/sundials/templates/model_header.template.h @@ -20,7 +20,7 @@ extern std::array state_names; extern std::array observable_names; extern std::array observable_scalings; extern std::array expression_names; -extern std::array parameter_ids; +extern std::array free_parameter_ids; extern std::array fixed_parameter_ids; extern std::array state_ids; extern std::array observable_ids; @@ -348,9 +348,9 @@ class Model_TPL_MODELNAME : public amici::Model_TPL_MODEL_TYPE_UPPER { * @brief Get ids of the model parameters * @return the ids */ - std::vector get_parameter_ids() const override { - return std::vector(parameter_ids.begin(), - parameter_ids.end()); + std::vector get_free_parameter_ids() const override { + return std::vector(free_parameter_ids.begin(), + free_parameter_ids.end()); } /** diff --git a/python/sdist/amici/gradient_check.py b/python/sdist/amici/gradient_check.py index 2c7cdba47b..d14a59bbef 100644 --- a/python/sdist/amici/gradient_check.py +++ b/python/sdist/amici/gradient_check.py @@ -140,8 +140,8 @@ def check_finite_difference( rtol=rtol, field=field, ip=ip, - parameter_id=model.get_parameter_ids()[ip] - if model.has_parameter_ids() + parameter_id=model.get_free_parameter_ids()[ip] + if model.has_free_parameter_ids() else None, ) diff --git a/python/sdist/amici/numpy.py b/python/sdist/amici/numpy.py index 8243b29b21..af16d0b128 100644 --- a/python/sdist/amici/numpy.py +++ b/python/sdist/amici/numpy.py @@ -495,8 +495,8 @@ def by_id( ) or self._swigptr.observable_ids elif field in {"sllh"}: ids = ( - model and model.get_parameter_ids() - ) or self._swigptr.parameter_ids + model and model.get_free_parameter_ids() + ) or self._swigptr.free_parameter_ids else: raise NotImplementedError( f"Subsetting `{field}` by ID (`{entity_id}`) " diff --git a/python/sdist/amici/petab/conditions.py b/python/sdist/amici/petab/conditions.py index 0630c9928f..7087db40b7 100644 --- a/python/sdist/amici/petab/conditions.py +++ b/python/sdist/amici/petab/conditions.py @@ -185,19 +185,19 @@ def _get_par(model_par, value, mapping): # parameter list from mapping dict parameters = [ - map_sim_var[par_id] for par_id in amici_model.get_parameter_ids() + map_sim_var[par_id] for par_id in amici_model.get_free_parameter_ids() ] # scales list from mapping dict scales = [ petab_to_amici_scale(scale_map_sim_var[par_id]) - for par_id in amici_model.get_parameter_ids() + for par_id in amici_model.get_free_parameter_ids() ] # plist plist = [ ip - for ip, par_id in enumerate(amici_model.get_parameter_ids()) + for ip, par_id in enumerate(amici_model.get_free_parameter_ids()) if isinstance(parameter_mapping.map_sim_var[par_id], str) ] diff --git a/python/sdist/amici/petab/import_helpers.py b/python/sdist/amici/petab/import_helpers.py index 5726cbf49f..398ae49200 100644 --- a/python/sdist/amici/petab/import_helpers.py +++ b/python/sdist/amici/petab/import_helpers.py @@ -253,7 +253,7 @@ def check_model( if petab_problem.parameter_df is None: return - amici_ids_free = set(amici_model.get_parameter_ids()) + amici_ids_free = set(amici_model.get_free_parameter_ids()) amici_ids = amici_ids_free | set(amici_model.get_fixed_parameter_ids()) petab_ids_free = set( diff --git a/python/sdist/amici/petab/parameter_mapping.py b/python/sdist/amici/petab/parameter_mapping.py index 41b1d72dd9..6d3ac550ca 100644 --- a/python/sdist/amici/petab/parameter_mapping.py +++ b/python/sdist/amici/petab/parameter_mapping.py @@ -538,7 +538,7 @@ def create_parameter_mapping_for_condition( # merge_preeq_and_sim_pars_condition below may fail. # TODO: This can be done already in parameter mapping creation. if amici_model is not None: - variable_par_ids = amici_model.get_parameter_ids() + variable_par_ids = amici_model.get_free_parameter_ids() fixed_par_ids = amici_model.get_fixed_parameter_ids() condition_map_preeq_var, condition_map_preeq_fix = _subset_dict( condition_map_preeq, variable_par_ids, fixed_par_ids diff --git a/python/sdist/amici/petab/petab_importer.py b/python/sdist/amici/petab/petab_importer.py index e87bc1503b..dc56ba168b 100644 --- a/python/sdist/amici/petab/petab_importer.py +++ b/python/sdist/amici/petab/petab_importer.py @@ -660,15 +660,15 @@ def __init__( self._model: amici.Model = model self._petab_problem: v2.Problem = petab_problem self._state_ids: tuple[str, ...] = tuple(self._model.get_state_ids()) - self._parameter_ids: tuple[str, ...] = tuple( - self._model.get_parameter_ids() + self._free_parameter_ids: tuple[str, ...] = tuple( + self._model.get_free_parameter_ids() ) self._fixed_parameter_ids: tuple[str, ...] = tuple( self._model.get_fixed_parameter_ids() ) # maps parameter IDs to parameter indices in the model self._pid_to_idx: dict[str, int] = { - id_: i for i, id_ in enumerate(self._parameter_ids) + id_: i for i, id_ in enumerate(self._free_parameter_ids) } self._fixed_pid_to_idx: dict[str, int] = { id_: i for i, id_ in enumerate(self._fixed_parameter_ids) @@ -944,7 +944,7 @@ def apply_parameters( placeholder_mappings = self._get_placeholder_mapping(experiment) estimated_par_ids = self._petab_problem.x_free_ids for model_par_idx, model_par_id in enumerate( - self._model.get_parameter_ids() + self._model.get_free_parameter_ids() ): if model_par_id in estimated_par_ids or ( (maps_to := placeholder_mappings.get(model_par_id)) is not None @@ -1043,7 +1043,7 @@ def apply_override(placeholder: str, override: sp.Basic): logger.debug("ExperimentManager.apply_parameters:") logger.debug( f"Parameters: " - f"{dict(zip(self._parameter_ids, map(float, par_vals)))}" + f"{dict(zip(self._free_parameter_ids, map(float, par_vals)))}" ) @property @@ -1226,7 +1226,7 @@ def _aggregate_sllh( f"{rdata.id} were not computed." ) - parameter_ids = self._model.get_parameter_ids() + free_parameter_ids = self._model.get_free_parameter_ids() # still needs parameter mapping for placeholders for rdata in rdatas: @@ -1237,7 +1237,9 @@ def _aggregate_sllh( for model_par_idx, sllh in zip( rdata.plist, rdata.sllh, strict=True ): - model_par_id = problem_par_id = parameter_ids[model_par_idx] + model_par_id = problem_par_id = free_parameter_ids[ + model_par_idx + ] if maps_to := placeholder_mappings.get(model_par_id): problem_par_id = maps_to @@ -1294,7 +1296,7 @@ def _aggregate_s2llh( global_ix_map: dict[int, int] = { model_ix: self._petab_problem.x_free_ids.index(model_pid) for model_ix, model_pid in enumerate( - self._model.get_parameter_ids() + self._model.get_free_parameter_ids() ) if model_pid in self._petab_problem.x_free_ids } @@ -1316,9 +1318,9 @@ def _aggregate_s2llh( ) for model_pid, problem_pid in placeholder_mappings.items(): try: - ix_map[self.model.get_parameter_ids().index(model_pid)] = ( - self._petab_problem.x_free_ids.index(problem_pid) - ) + ix_map[ + self.model.get_free_parameter_ids().index(model_pid) + ] = self._petab_problem.x_free_ids.index(problem_pid) except ValueError: # mapped-to parameter is not estimated pass diff --git a/python/sdist/amici/petab/simulations.py b/python/sdist/amici/petab/simulations.py index f6e953309b..950f32b7bd 100644 --- a/python/sdist/amici/petab/simulations.py +++ b/python/sdist/amici/petab/simulations.py @@ -284,7 +284,7 @@ def aggregate_sllh( Aggregated likelihood sensitivities. """ accumulated_sllh = {} - model_parameter_ids = amici_model.get_parameter_ids() + model_free_parameter_ids = amici_model.get_free_parameter_ids() if petab_scale and petab_problem is None: raise ValueError( @@ -316,7 +316,9 @@ def aggregate_sllh( model_parameter_index = edata.plist[sllh_parameter_index] else: model_parameter_index = amici_model.plist(sllh_parameter_index) - model_parameter_id = model_parameter_ids[model_parameter_index] + model_parameter_id = model_free_parameter_ids[ + model_parameter_index + ] petab_parameter_id = condition_parameter_mapping.map_sim_var[ model_parameter_id ] diff --git a/python/tests/adapters/test_fiddy.py b/python/tests/adapters/test_fiddy.py index 2ae5c88f96..7ce7b42ac9 100644 --- a/python/tests/adapters/test_fiddy.py +++ b/python/tests/adapters/test_fiddy.py @@ -52,7 +52,7 @@ def test_run_amici_simulation_to_functions(problem_generator): ].index ) parameter_indices = [ - amici_model.get_parameter_ids().index(parameter_id) + amici_model.get_free_parameter_ids().index(parameter_id) for parameter_id in parameter_ids ] @@ -61,7 +61,7 @@ def test_run_amici_simulation_to_functions(problem_generator): amici_derivative, structures, ) = run_simulation_to_cached_functions( - parameter_ids=parameter_ids, + free_parameter_ids=parameter_ids, amici_model=amici_model, amici_solver=amici_solver, ) @@ -131,7 +131,7 @@ def test_simulate_petab_to_functions(problem_generator, scaled_parameters): ) amici_function, amici_derivative = simulate_petab_to_cached_functions( - parameter_ids=petab_problem.parameter_df.index, + free_parameter_ids=petab_problem.parameter_df.index, petab_problem=petab_problem, amici_model=amici_model, solver=amici_solver, @@ -141,7 +141,7 @@ def test_simulate_petab_to_functions(problem_generator, scaled_parameters): expected_derivative = amici_derivative(point) - parameter_ids = list( + free_parameter_ids = list( petab_problem.parameter_df[ petab_problem.parameter_df.estimate == 1 ].index @@ -156,7 +156,7 @@ def test_simulate_petab_to_functions(problem_generator, scaled_parameters): function=amici_function, point=point, sizes=[1e-10, 1e-5, 1e-3, 1e-1], - direction_ids=parameter_ids, + direction_ids=free_parameter_ids, method_ids=[MethodId.FORWARD, MethodId.BACKWARD, MethodId.CENTRAL], success_checker=Consistency(), ) diff --git a/python/tests/petab_/test_petab_problem.py b/python/tests/petab_/test_petab_problem.py index a1e4a2f806..24ef65f40d 100644 --- a/python/tests/petab_/test_petab_problem.py +++ b/python/tests/petab_/test_petab_problem.py @@ -26,7 +26,8 @@ def test_amici_petab_problem_pregenerate(): # ensure parameter are updated edatas = app.get_edatas() app.set_parameters( - {app.model.get_parameter_ids()[0]: 0.12345}, scaled_parameters=True + {app.model.get_free_parameter_ids()[0]: 0.12345}, + scaled_parameters=True, ) for edata in edatas: assert edata.free_parameters[0] == 0.12345 @@ -50,7 +51,8 @@ def test_amici_petab_problem_on_demand(): # ensure parameter are updated app.set_parameters( - {app.model.get_parameter_ids()[0]: 0.12345}, scaled_parameters=True + {app.model.get_free_parameter_ids()[0]: 0.12345}, + scaled_parameters=True, ) # previously generated ExpDatas are not updated for edata in edatas: @@ -83,7 +85,9 @@ def test_amici_petab_problem_pregenerate_equals_on_demand(tempdir): petab_problem, store_edatas=False, amici_model=amici_model ) - parameter_update = {app_store_true.model.get_parameter_ids()[0]: 0.12345} + parameter_update = { + app_store_true.model.get_free_parameter_ids()[0]: 0.12345 + } app_store_true.set_parameters(parameter_update, scaled_parameters=True) app_store_false.set_parameters(parameter_update, scaled_parameters=True) diff --git a/python/tests/splines_utils.py b/python/tests/splines_utils.py index f29c61743f..bcb4b22c61 100644 --- a/python/tests/splines_utils.py +++ b/python/tests/splines_utils.py @@ -444,7 +444,7 @@ def simulate_splines( # Return state/parameter ordering state_ids = amici_model.get_state_ids() - param_ids = amici_model.get_parameter_ids() + param_ids = amici_model.get_free_parameter_ids() return ( initial_values, diff --git a/python/tests/test_events.py b/python/tests/test_events.py index c546d06373..d0558b6fd1 100644 --- a/python/tests/test_events.py +++ b/python/tests/test_events.py @@ -938,7 +938,7 @@ def test_event_priorities(tempdir): model.set_parameter_list( [ ip - for ip, par in enumerate(model.get_parameter_ids()) + for ip, par in enumerate(model.get_free_parameter_ids()) if par != "two" ] ) @@ -1090,7 +1090,7 @@ def test_event_uses_values_from_trigger_time(tempdir): model.set_parameter_list( [ ip - for ip, par in enumerate(model.get_parameter_ids()) + for ip, par in enumerate(model.get_free_parameter_ids()) if par not in ["one"] ] ) @@ -1101,7 +1101,7 @@ def test_event_uses_values_from_trigger_time(tempdir): model.set_parameter_list( [ ip - for ip, par in enumerate(model.get_parameter_ids()) + for ip, par in enumerate(model.get_free_parameter_ids()) if par not in ["one", "three"] ] ) diff --git a/python/tests/test_jax.py b/python/tests/test_jax.py index 28b1ab539c..a4701df155 100644 --- a/python/tests/test_jax.py +++ b/python/tests/test_jax.py @@ -145,7 +145,7 @@ def _test_model(amici_module, jax_module, ts, p, k): check_fields_jax( rs_amici, jax_model, - amici_model.get_parameter_ids(), + amici_model.get_free_parameter_ids(), amici_model.get_fixed_parameter_ids(), edata, ["x", "y", "llh", "res", "x0"], @@ -154,7 +154,7 @@ def _test_model(amici_module, jax_module, ts, p, k): check_fields_jax( rs_amici, jax_model, - amici_model.get_parameter_ids(), + amici_model.get_free_parameter_ids(), amici_model.get_fixed_parameter_ids(), edata, ["sllh", "sx0", "sx", "sres", "sy"], @@ -165,7 +165,7 @@ def _test_model(amici_module, jax_module, ts, p, k): def check_fields_jax( rs_amici, jax_model, - parameter_ids, + free_parameter_ids, fixed_parameter_ids, edata, fields, @@ -185,7 +185,7 @@ def check_fields_jax( ts_posteq = np.array([]) par_dict = { - **dict(zip(parameter_ids, edata.free_parameters)), + **dict(zip(free_parameter_ids, edata.free_parameters)), **dict(zip(fixed_parameter_ids, edata.fixed_parameters)), } @@ -229,7 +229,10 @@ def check_fields_jax( )[0] amici_par_idx = np.array( - [jax_model.parameter_ids.index(par_id) for par_id in parameter_ids] + [ + jax_model.parameter_ids.index(par_id) + for par_id in free_parameter_ids + ] ) for field in fields: diff --git a/python/tests/test_preequilibration.py b/python/tests/test_preequilibration.py index db90a44ffe..546d506751 100644 --- a/python/tests/test_preequilibration.py +++ b/python/tests/test_preequilibration.py @@ -846,7 +846,7 @@ def test_preequilibration_events(tempdir): amici_model.set_parameter_list( [ i - for i, p in enumerate(amici_model.get_parameter_ids()) + for i, p in enumerate(amici_model.get_free_parameter_ids()) if p != "trigger_time2" ] ) diff --git a/python/tests/test_sbml_import.py b/python/tests/test_sbml_import.py index 288c7aedae..1e50fc5aa0 100644 --- a/python/tests/test_sbml_import.py +++ b/python/tests/test_sbml_import.py @@ -329,7 +329,7 @@ def test_presimulation_events(tempdir): # are not supported edata.plist = [ ip - for ip, p in enumerate(model.get_parameter_ids()) + for ip, p in enumerate(model.get_free_parameter_ids()) if p != "t_initial_presim" ] solver.set_sensitivity_order(amici.SensitivityOrder.first) @@ -719,7 +719,7 @@ def test_sympy_exp_monkeypatch(tempdir): amici.ParameterScaling.none if re.match(r"n[0-9]+$", par_id) else amici.ParameterScaling.log10 - for par_id in model.get_parameter_ids() + for par_id in model.get_free_parameter_ids() ] ) ) @@ -782,8 +782,8 @@ def _test_set_parameters_by_dict(model_module): """Test setting parameter via id/name => value dicts""" model = model_module.get_model() old_parameter_values = model.get_parameters() - parameter_ids = model.get_parameter_ids() - change_par_id = parameter_ids[-1] + free_parameter_ids = model.get_free_parameter_ids() + change_par_id = free_parameter_ids[-1] new_par_val = 0.1234 old_par_val = model.get_parameter_by_id(change_par_id) diff --git a/python/tests/test_swig_interface.py b/python/tests/test_swig_interface.py index c2a3970d45..504874d09a 100644 --- a/python/tests/test_swig_interface.py +++ b/python/tests/test_swig_interface.py @@ -322,10 +322,10 @@ def test_unhandled_settings(pysb_example_presimulation_module): "get_observable_ids", "get_observable_names", "get_observable_scaling", - "get_parameter_by_id", - "get_parameter_by_name", - "get_parameter_ids", - "get_parameter_names", + "get_free_parameter_by_id", + "get_free_parameter_by_name", + "get_free_parameter_ids", + "get_free_parameter_names", "get_second_order_mode", "get_solver", "get_state_ids", diff --git a/python/tests/util.py b/python/tests/util.py index a98d47fac5..c2df3b94ce 100644 --- a/python/tests/util.py +++ b/python/tests/util.py @@ -130,7 +130,7 @@ def check_trajectories_with_adjoint_sensitivities( "asa": rdata_asa["sllh"], "fd": np.nan, }, - index=list(amici_model.get_parameter_ids()), + index=list(amici_model.get_free_parameter_ids()), ) df["abs_diff"] = df["fsa"] - df["asa"] df["rel_diff"] = df["abs_diff"] / df["fsa"] diff --git a/src/model.cpp b/src/model.cpp index 78ef4cd0ee..265d0652ef 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -529,13 +529,13 @@ std::vector const& Model::get_parameters() const { return simulation_parameters_.free_parameters; } -realtype Model::get_parameter_by_id(std::string const& par_id) const { - if (!has_parameter_ids()) +realtype Model::get_free_parameter_by_id(std::string const& par_id) const { + if (!has_free_parameter_ids()) throw AmiException( "Could not access parameters by id as they are not set" ); return get_value_by_id( - get_parameter_ids(), simulation_parameters_.free_parameters, par_id, + get_free_parameter_ids(), simulation_parameters_.free_parameters, par_id, "parameters", "id" ); } @@ -578,16 +578,16 @@ void Model::set_parameter_by_id( } } -void Model::set_parameter_by_id( +void Model::set_free_parameter_by_id( std::string const& par_id, realtype const value ) { - if (!has_parameter_ids()) + if (!has_free_parameter_ids()) throw AmiException( "Could not access parameters by id as they are not set" ); set_value_by_id( - get_parameter_ids(), simulation_parameters_.free_parameters, value, par_id, + get_free_parameter_ids(), simulation_parameters_.free_parameters, value, par_id, "parameter", "id" ); unscale_parameters( @@ -596,15 +596,15 @@ void Model::set_parameter_by_id( ); } -int Model::set_parameters_by_id_regex( +int Model::set_free_parameters_by_id_regex( std::string const& par_id_regex, realtype const value ) { - if (!has_parameter_ids()) + if (!has_free_parameter_ids()) throw AmiException( "Could not access parameters by id as they are not set" ); int n_found = set_value_by_id_regex( - get_parameter_ids(), simulation_parameters_.free_parameters, value, + get_free_parameter_ids(), simulation_parameters_.free_parameters, value, par_id_regex, "parameter", "id" ); unscale_parameters( @@ -792,11 +792,11 @@ bool Model::has_expression_names() const { std::vector Model::get_expression_names() const { return {}; } -bool Model::has_parameter_ids() const { - return np() == 0 || !get_parameter_ids().empty(); +bool Model::has_free_parameter_ids() const { + return np() == 0 || !get_free_parameter_ids().empty(); } -std::vector Model::get_parameter_ids() const { return {}; } +std::vector Model::get_free_parameter_ids() const { return {}; } bool Model::has_state_ids() const { return nx_rdata == 0 || !get_state_ids().empty(); @@ -1619,8 +1619,8 @@ int Model::check_finite( } break; case ModelQuantity::p: - if (has_parameter_ids()) { - element_id = get_parameter_ids()[flat_index]; + if (has_free_parameter_ids()) { + element_id = get_free_parameter_ids()[flat_index]; } break; default: @@ -1695,8 +1695,8 @@ int Model::check_finite( case ModelQuantity::dsigmaydp: if (has_observable_ids()) row_id += " " + get_observable_ids()[row]; - if (has_parameter_ids()) - col_id += " " + get_parameter_ids()[plist(gsl::narrow(col))]; + if (has_free_parameter_ids()) + col_id += " " + get_free_parameter_ids()[plist(gsl::narrow(col))]; break; case ModelQuantity::dydx: if (has_observable_ids()) @@ -1707,8 +1707,8 @@ int Model::check_finite( case ModelQuantity::deltasx: if (has_state_ids()) row_id += " " + get_state_ids_solver()[row]; - if (has_parameter_ids()) - col_id += " " + get_parameter_ids()[plist(gsl::narrow(col))]; + if (has_free_parameter_ids()) + col_id += " " + get_free_parameter_ids()[plist(gsl::narrow(col))]; break; case ModelQuantity::dJydy: case ModelQuantity::dJydsigma: @@ -1728,8 +1728,8 @@ int Model::check_finite( case ModelQuantity::dzdp: case ModelQuantity::drzdp: case ModelQuantity::dsigmazdp: - if (has_parameter_ids()) - col_id += " " + get_parameter_ids()[plist(gsl::narrow(col))]; + if (has_free_parameter_ids()) + col_id += " " + get_free_parameter_ids()[plist(gsl::narrow(col))]; break; case ModelQuantity::dsigmaydy: if (has_observable_ids()) { @@ -1831,8 +1831,8 @@ int Model::check_finite( case ModelQuantity::dwdp: if (has_expression_ids()) row_id += " " + get_expression_ids()[row]; - if (has_parameter_ids()) - col_id += " " + get_parameter_ids()[col]; + if (has_free_parameter_ids()) + col_id += " " + get_free_parameter_ids()[col]; break; default: break; diff --git a/tests/cpp/testfunctions.h b/tests/cpp/testfunctions.h index eda3c3848a..a1557a0877 100644 --- a/tests/cpp/testfunctions.h +++ b/tests/cpp/testfunctions.h @@ -163,7 +163,7 @@ class Model_Test : public Model { return getVariableNames("y", ny); } - std::vector get_parameter_ids() const override { + std::vector get_free_parameter_ids() const override { return getVariableNames("p", np()); } diff --git a/tests/sbml/testSBMLSuite.py b/tests/sbml/testSBMLSuite.py index 6ad10fcb6e..f794dcfdd3 100755 --- a/tests/sbml/testSBMLSuite.py +++ b/tests/sbml/testSBMLSuite.py @@ -240,7 +240,7 @@ def simulate(pars): sx = jax.jacfwd(simulate)(p) par_idx = [ jax_model.parameter_ids.index(pid) - for pid in amici_model.get_parameter_ids() + for pid in amici_model.get_free_parameter_ids() ] sx = jnp.transpose(sx[:, :, par_idx], (0, 2, 1)) diff --git a/tests/sbml/utils.py b/tests/sbml/utils.py index 3998c4ea63..f92f413b29 100644 --- a/tests/sbml/utils.py +++ b/tests/sbml/utils.py @@ -35,7 +35,7 @@ def verify_results( parameter_data = {} # collect parameters - for par in model.get_parameter_ids(): + for par in model.get_free_parameter_ids(): parameter_data[par] = rdata["ts"] * 0 + model.get_parameter_by_id(par) expression_data = {} From a5e98221707c259d613eed906fcd6cf65126f0d8 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Thu, 13 Nov 2025 22:30:42 +0100 Subject: [PATCH 12/23] more renaming --- include/amici/model.h | 20 +++++++++---------- src/edata.cpp | 6 +++--- src/hdf5.cpp | 2 +- src/model.cpp | 18 ++++++++--------- src/rdata.cpp | 2 +- tests/cpp/jakstat_adjoint/tests1.cpp | 4 ++-- tests/cpp/steadystate/tests1.cpp | 6 +++--- tests/cpp/unittests/testMisc.cpp | 30 ++++++++++++++-------------- 8 files changed, 44 insertions(+), 44 deletions(-) diff --git a/include/amici/model.h b/include/amici/model.h index 0c7e8cd84e..12e0b6ad0d 100644 --- a/include/amici/model.h +++ b/include/amici/model.h @@ -411,27 +411,27 @@ class Model : public AbstractModel, public ModelDimensions { * @brief Get parameter vector. * @return The user-set parameters (see also `Model::getUnscaledParameters`) */ - std::vector const& get_parameters() const; + std::vector const& get_free_parameters() const; /** * @brief Get value of first model parameter with the specified ID. * @param par_id Parameter ID * @return Parameter value */ - realtype get_parameter_by_id(std::string const& par_id) const; + realtype get_free_parameter_by_id(std::string const& par_id) const; /** * @brief Get value of first model parameter with the specified name. * @param par_name Parameter name * @return Parameter value */ - realtype get_parameter_by_name(std::string const& par_name) const; + realtype get_free_parameter_by_name(std::string const& par_name) const; /** * @brief Set the parameter vector. * @param p Vector of parameters */ - void set_parameters(std::vector const& p); + void set_free_parameters(std::vector const& p); /** * @brief Set model parameters according to the parameter IDs and mapped @@ -440,7 +440,7 @@ class Model : public AbstractModel, public ModelDimensions { * @param ignoreErrors Ignore errors such as parameter IDs in p which are * not model parameters */ - void set_parameter_by_id( + void set_free_parameter_by_id( std::map const& p, bool ignoreErrors = false ); @@ -449,7 +449,7 @@ class Model : public AbstractModel, public ModelDimensions { * @param par_id Parameter ID * @param value Parameter value */ - void set_parameter_by_id(std::string const& par_id, realtype value); + void set_free_parameter_by_id(std::string const& par_id, realtype value); /** * @brief Set all values of model parameters with IDs matching the specified @@ -459,14 +459,14 @@ class Model : public AbstractModel, public ModelDimensions { * @return Number of parameter IDs that matched the regex */ int - set_parameters_by_id_regex(std::string const& par_id_regex, realtype value); + set_free_parameters_by_id_regex(std::string const& par_id_regex, realtype value); /** * @brief Set value of first model parameter with the specified name. * @param par_name Parameter name * @param value Parameter value */ - void set_parameter_by_name(std::string const& par_name, realtype value); + void set_free_parameter_by_name(std::string const& par_name, realtype value); /** * @brief Set model parameters according to the parameter name and mapped @@ -475,7 +475,7 @@ class Model : public AbstractModel, public ModelDimensions { * @param ignoreErrors Ignore errors such as parameter names in p which are * not model parameters */ - void set_parameter_by_name( + void set_free_parameter_by_name( std::map const& p, bool ignoreErrors = false ); @@ -486,7 +486,7 @@ class Model : public AbstractModel, public ModelDimensions { * @param value Parameter value * @return Number of fixed parameter names that matched the regex */ - int set_parameters_by_name_regex( + int set_free_parameters_by_name_regex( std::string const& par_name_regex, realtype value ); diff --git a/src/edata.cpp b/src/edata.cpp index 0b4f3f2e94..a5364a3251 100644 --- a/src/edata.cpp +++ b/src/edata.cpp @@ -410,7 +410,7 @@ ConditionContext::ConditionContext( Model* model, ExpData const* edata, FixedParameterContext fpc ) : model_(model) - , original_parameters_(model->get_parameters()) + , original_parameters_(model->get_free_parameters()) , original_fixed_parameters_(model->get_fixed_parameters()) , original_tstart_(model->t0()) , original_tstart_preeq_(model->t0_preeq()) @@ -466,7 +466,7 @@ void ConditionContext::apply_condition( " match ExpData (%zd).", model_->np(), edata->free_parameters.size() ); - model_->set_parameters(edata->free_parameters); + model_->set_free_parameters(edata->free_parameters); } if (!edata->x0.empty()) { @@ -567,7 +567,7 @@ void ConditionContext::restore() { if (!original_sx0_.empty()) model_->set_unscaled_initial_state_sensitivities(original_sx0_); - model_->set_parameters(original_parameters_); + model_->set_free_parameters(original_parameters_); model_->set_fixed_parameters(original_fixed_parameters_); model_->set_t0(original_tstart_); model_->set_t0_preeq(original_tstart_preeq_); diff --git a/src/hdf5.cpp b/src/hdf5.cpp index f613bfdef9..6c00002edc 100644 --- a/src/hdf5.cpp +++ b/src/hdf5.cpp @@ -1518,7 +1518,7 @@ void read_model_data_from_hdf5( } if (location_exists(file, datasetPath + "/theta")) { - model.set_parameters(get_double_1d_dataset(file, datasetPath + "/theta") + model.set_free_parameters(get_double_1d_dataset(file, datasetPath + "/theta") ); } diff --git a/src/model.cpp b/src/model.cpp index 265d0652ef..af7a5d60e2 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -525,7 +525,7 @@ std::vector const& Model::get_unscaled_parameters() const { return state_.unscaled_parameters; } -std::vector const& Model::get_parameters() const { +std::vector const& Model::get_free_parameters() const { return simulation_parameters_.free_parameters; } @@ -540,7 +540,7 @@ realtype Model::get_free_parameter_by_id(std::string const& par_id) const { ); } -realtype Model::get_parameter_by_name(std::string const& par_name) const { +realtype Model::get_free_parameter_by_name(std::string const& par_name) const { if (!has_free_parameter_names()) throw AmiException( "Could not access parameters by name as they are not set" @@ -551,7 +551,7 @@ realtype Model::get_parameter_by_name(std::string const& par_name) const { ); } -void Model::set_parameters(std::vector const& p) { +void Model::set_free_parameters(std::vector const& p) { if (p.size() != (unsigned)np()) throw AmiException( "Dimension mismatch. Size of parameters does not " @@ -565,12 +565,12 @@ void Model::set_parameters(std::vector const& p) { ); } -void Model::set_parameter_by_id( +void Model::set_free_parameter_by_id( std::map const& p, bool const ignoreErrors ) { for (auto const& [parameter_id, value] : p) { try { - set_parameter_by_id(parameter_id, value); + set_free_parameter_by_id(parameter_id, value); } catch (AmiException const&) { if (!ignoreErrors) throw; @@ -614,7 +614,7 @@ int Model::set_free_parameters_by_id_regex( return n_found; } -void Model::set_parameter_by_name( +void Model::set_free_parameter_by_name( std::string const& par_name, realtype const value ) { if (!has_free_parameter_names()) @@ -632,12 +632,12 @@ void Model::set_parameter_by_name( ); } -void Model::set_parameter_by_name( +void Model::set_free_parameter_by_name( std::map const& p, bool ignoreErrors ) { for (auto const& [name, value] : p) { try { - set_parameter_by_name(name, value); + set_free_parameter_by_name(name, value); } catch (AmiException const&) { if (!ignoreErrors) throw; @@ -645,7 +645,7 @@ void Model::set_parameter_by_name( } } -int Model::set_parameters_by_name_regex( +int Model::set_free_parameters_by_name_regex( std::string const& par_name_regex, realtype value ) { if (!has_free_parameter_names()) diff --git a/src/rdata.cpp b/src/rdata.cpp index 3ad5b7f2b5..27450c1448 100644 --- a/src/rdata.cpp +++ b/src/rdata.cpp @@ -696,7 +696,7 @@ void ReturnData::apply_chain_rule_factor_to_simulation_results( // to such parameters if they are log-scaled. std::vector pcoefficient(nplist, 1.0); - std::vector unscaledParameters = model.get_parameters(); + std::vector unscaledParameters = model.get_free_parameters(); unscale_parameters( unscaledParameters, model.get_parameter_scale(), unscaledParameters ); diff --git a/tests/cpp/jakstat_adjoint/tests1.cpp b/tests/cpp/jakstat_adjoint/tests1.cpp index 5e94ccfdd1..4dded0f4f7 100644 --- a/tests/cpp/jakstat_adjoint/tests1.cpp +++ b/tests/cpp/jakstat_adjoint/tests1.cpp @@ -52,9 +52,9 @@ TEST(ExampleJakstatAdjoint, SensitivityAdjointUnusedNanOutputs) // Set output parameter p[10] to NaN and remove respective measurements // -> gradient should still be finite - auto p = model->get_parameters(); + auto p = model->get_free_parameters(); p[10] = NAN; - model->set_parameter_by_id("offset_tSTAT", NAN); + model->set_free_parameter_by_id("offset_tSTAT", NAN); auto iy = 1; Expects(model->get_observable_ids()[iy] == "obs_tSTAT"); diff --git a/tests/cpp/steadystate/tests1.cpp b/tests/cpp/steadystate/tests1.cpp index 92d56b1d28..a4bad16922 100644 --- a/tests/cpp/steadystate/tests1.cpp +++ b/tests/cpp/steadystate/tests1.cpp @@ -29,7 +29,7 @@ TEST(ExampleSteadystate, ModelFromHDF5) for (int i = 0; i < model->np(); ++i) { ASSERT_EQ(pExp[i], model->get_unscaled_parameters()[i]); - ASSERT_EQ(log10(pExp[i]), model->get_parameters()[i]); + ASSERT_EQ(log10(pExp[i]), model->get_free_parameters()[i]); } } @@ -98,9 +98,9 @@ TEST(ExampleSteadystate, Rethrow) NEW_OPTION_FILE, *solver, "/model_steadystate/nosensi/options"); // p = NaN will raise amici::IntegrationFailure - auto p = model->get_parameters(); + auto p = model->get_free_parameters(); std::fill(p.begin(), p.end(), std::nan("")); - model->set_parameters(p); + model->set_free_parameters(p); // must not throw run_simulation(*solver, nullptr, *model); diff --git a/tests/cpp/unittests/testMisc.cpp b/tests/cpp/unittests/testMisc.cpp index b8891257b7..244c87f52a 100644 --- a/tests/cpp/unittests/testMisc.cpp +++ b/tests/cpp/unittests/testMisc.cpp @@ -80,19 +80,19 @@ class ModelTest : public ::testing::Test { TEST_F(ModelTest, LinScaledParameterIsNotTransformed) { model.set_parameter_scale(ParameterScaling::none); - ASSERT_EQ(p[0], model.get_parameters()[0]); + ASSERT_EQ(p[0], model.get_free_parameters()[0]); } TEST_F(ModelTest, LogScaledParameterIsTransformed) { model.set_parameter_scale(ParameterScaling::ln); - ASSERT_NEAR(std::log(p[0]), model.get_parameters()[0], 1e-16); + ASSERT_NEAR(std::log(p[0]), model.get_free_parameters()[0], 1e-16); } TEST_F(ModelTest, Log10ScaledParameterIsTransformed) { model.set_parameter_scale(ParameterScaling::log10); - ASSERT_NEAR(std::log10(p[0]), model.get_parameters()[0], 1e-16); + ASSERT_NEAR(std::log10(p[0]), model.get_free_parameters()[0], 1e-16); } TEST_F(ModelTest, ParameterScaleTooShort) { @@ -112,28 +112,28 @@ TEST_F(ModelTest, UnsortedTimepointsThrow) { } TEST_F(ModelTest, ParameterNameIdGetterSetter) { - model.set_parameter_by_id("p0", 3.0); - ASSERT_NEAR(model.get_parameter_by_id("p0"), 3.0, 1e-16); - ASSERT_THROW(model.get_parameter_by_id("p1"), AmiException); + model.set_free_parameter_by_id("p0", 3.0); + ASSERT_NEAR(model.get_free_parameter_by_id("p0"), 3.0, 1e-16); + ASSERT_THROW(model.get_free_parameter_by_id("p1"), AmiException); ASSERT_NEAR( - model.set_parameters_by_id_regex("p[\\d]+", 5.0), p.size(), 1e-16 + model.set_free_parameters_by_id_regex("p[\\d]+", 5.0), p.size(), 1e-16 ); - for (auto const& ip : model.get_parameters()) + for (auto const& ip : model.get_free_parameters()) ASSERT_NEAR(ip, 5.0, 1e-16); ASSERT_THROW( - model.set_parameters_by_id_regex("k[\\d]+", 5.0), AmiException + model.set_free_parameters_by_id_regex("k[\\d]+", 5.0), AmiException ); - model.set_parameter_by_name("p0", 3.0); - ASSERT_NEAR(model.get_parameter_by_name("p0"), 3.0, 1e-16); - ASSERT_THROW(model.get_parameter_by_name("p1"), AmiException); + model.set_free_parameter_by_name("p0", 3.0); + ASSERT_NEAR(model.get_free_parameter_by_name("p0"), 3.0, 1e-16); + ASSERT_THROW(model.get_free_parameter_by_name("p1"), AmiException); ASSERT_NEAR( - model.set_parameters_by_name_regex("p[\\d]+", 5.0), p.size(), 1e-16 + model.set_free_parameters_by_name_regex("p[\\d]+", 5.0), p.size(), 1e-16 ); - for (auto const& ip : model.get_parameters()) + for (auto const& ip : model.get_free_parameters()) ASSERT_NEAR(ip, 5.0, 1e-16); ASSERT_THROW( - model.set_parameters_by_name_regex("k[\\d]+", 5.0), AmiException + model.set_free_parameters_by_name_regex("k[\\d]+", 5.0), AmiException ); model.set_fixed_parameter_by_id("k0", 3.0); From 65e327d49b2135b77dcd21d6535e92c4993f0c0f Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Thu, 13 Nov 2025 22:50:03 +0100 Subject: [PATCH 13/23] update templates, regenerate test models --- models/model_calvetti_py/main.cpp | 4 +-- .../model_calvetti_py/model_calvetti_py.cpp | 4 +-- models/model_calvetti_py/model_calvetti_py.h | 8 ++--- models/model_calvetti_py/setup.py | 2 +- .../swig/model_calvetti_py.i | 31 +++++++++++++++++-- models/model_dirac_py/main.cpp | 4 +-- models/model_dirac_py/model_dirac_py.cpp | 4 +-- models/model_dirac_py/model_dirac_py.h | 16 +++++----- .../model_dirac_py/model_dirac_py.py | 24 ++++++++++++-- models/model_dirac_py/setup.py | 2 +- models/model_dirac_py/swig/model_dirac_py.i | 31 +++++++++++++++++-- models/model_events_py/main.cpp | 4 +-- models/model_events_py/model_events_py.cpp | 4 +-- models/model_events_py/model_events_py.h | 16 +++++----- models/model_events_py/setup.py | 2 +- models/model_events_py/swig/model_events_py.i | 31 +++++++++++++++++-- models/model_jakstat_adjoint_py/main.cpp | 4 +-- .../model_jakstat_adjoint_py.cpp | 4 +-- .../model_jakstat_adjoint_py.h | 8 ++--- models/model_jakstat_adjoint_py/setup.py | 2 +- .../swig/model_jakstat_adjoint_py.i | 31 +++++++++++++++++-- models/model_nested_events_py/main.cpp | 4 +-- .../model_nested_events_py.cpp | 4 +-- .../model_nested_events_py.h | 10 +++--- models/model_nested_events_py/setup.py | 2 +- .../swig/model_nested_events_py.i | 31 +++++++++++++++++-- models/model_neuron_py/main.cpp | 4 +-- models/model_neuron_py/model_neuron_py.cpp | 4 +-- models/model_neuron_py/model_neuron_py.h | 8 ++--- models/model_neuron_py/setup.py | 2 +- models/model_neuron_py/swig/model_neuron_py.i | 31 +++++++++++++++++-- models/model_robertson_py/main.cpp | 4 +-- .../model_robertson_py/model_robertson_py.cpp | 4 +-- .../model_robertson_py/model_robertson_py.h | 8 ++--- models/model_robertson_py/setup.py | 2 +- .../swig/model_robertson_py.i | 31 +++++++++++++++++-- models/model_steadystate_py/main.cpp | 6 ++-- .../model_steadystate_py.cpp | 4 +-- .../model_steadystate_py.h | 8 ++--- .../model_steadystate_py/__init__.py | 3 +- models/model_steadystate_py/setup.py | 2 +- .../swig/model_steadystate_py.i | 31 +++++++++++++++++-- .../amici/exporters/sundials/de_export.py | 6 ++-- .../sundials/templates/main.template.cpp | 4 +-- .../sundials/templates/model.template.cpp | 8 ++--- .../templates/model_header.template.h | 6 ++-- 46 files changed, 342 insertions(+), 121 deletions(-) diff --git a/models/model_calvetti_py/main.cpp b/models/model_calvetti_py/main.cpp index d6969550af..6cf4f96026 100644 --- a/models/model_calvetti_py/main.cpp +++ b/models/model_calvetti_py/main.cpp @@ -38,7 +38,7 @@ int main() { solver->set_relative_tolerance(1e-8); // Run the simulation using default parameters set during model import - // (can be changed using model->setParameters() or model->setParameterBy*()) + // (can be changed using model->set_free_parameters() or model->set_free_parameter_by*()) auto rdata = run_simulation(*solver, nullptr, *model); // Print observable time course @@ -69,7 +69,7 @@ int main() { // Print state sensitivities sx... // ... for the first timepoint... int i_time = 0; - // ... with respect to the first parameter + // ... with respect to the first free parameter int i_nplist = 0; // get identifiers from model diff --git a/models/model_calvetti_py/model_calvetti_py.cpp b/models/model_calvetti_py/model_calvetti_py.cpp index 55bcbfaaf7..79758b2a17 100644 --- a/models/model_calvetti_py/model_calvetti_py.cpp +++ b/models/model_calvetti_py/model_calvetti_py.cpp @@ -5,7 +5,7 @@ namespace amici::model_model_calvetti_py { // clang-format off -std::array parameter_names = { +std::array free_parameter_names = { }; @@ -65,7 +65,7 @@ std::array expression_names = { "flux_r0", // w[16] }; -std::array parameter_ids = { +std::array free_parameter_ids = { }; diff --git a/models/model_calvetti_py/model_calvetti_py.h b/models/model_calvetti_py/model_calvetti_py.h index a6e78635a5..4001463533 100644 --- a/models/model_calvetti_py/model_calvetti_py.h +++ b/models/model_calvetti_py/model_calvetti_py.h @@ -144,7 +144,7 @@ class Model_model_calvetti_py : public amici::Model_DAE { }, amici::SimulationParameters( std::vector{0.28999999999999998, 0.73999999999999999, 0.44, 0.080000000000000002, 0.27000000000000002, 0.17999999999999999}, // fixedParameters - std::vector{} // dynamic parameters + std::vector{} // free parameters ), amici::SecondOrderMode::none, // o2mode std::vector{1.0, 1.0, 1.0, 0.0, 0.0, 0.0}, // idlist @@ -421,7 +421,7 @@ class Model_model_calvetti_py : public amici::Model_DAE { } /** - * @brief Get names of the model parameters + * @brief Get names of the free model parameters * @return the names */ std::vector get_free_parameter_names() const override { @@ -478,7 +478,7 @@ class Model_model_calvetti_py : public amici::Model_DAE { } /** - * @brief Get ids of the model parameters + * @brief Get ids of the free model parameters * @return the ids */ std::vector get_free_parameter_ids() const override { @@ -557,7 +557,7 @@ class Model_model_calvetti_py : public amici::Model_DAE { * @return AMICI git commit hash */ std::string get_amici_commit() const override { - return "f005fac9e2de7c3c90be2ac55d4ad165471ed1e7"; + return "40190b46b1b398e321314ded4169fe910b37c484"; } bool has_quadratic_llh() const override { diff --git a/models/model_calvetti_py/setup.py b/models/model_calvetti_py/setup.py index 8396442dc5..6fceb4e8c9 100644 --- a/models/model_calvetti_py/setup.py +++ b/models/model_calvetti_py/setup.py @@ -1,5 +1,6 @@ """AMICI model package setup""" +import importlib.metadata import os import sys from pathlib import Path @@ -8,7 +9,6 @@ from amici.custom_commands import AmiciBuildCMakeExtension from cmake_build_extension import CMakeExtension from setuptools import find_namespace_packages, setup -import importlib.metadata def get_extension() -> CMakeExtension: diff --git a/models/model_calvetti_py/swig/model_calvetti_py.i b/models/model_calvetti_py/swig/model_calvetti_py.i index 9e75161f53..3a33581e7f 100644 --- a/models/model_calvetti_py/swig/model_calvetti_py.i +++ b/models/model_calvetti_py/swig/model_calvetti_py.i @@ -8,10 +8,11 @@ import sysconfig from pathlib import Path ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +extension_path = Path(__file__).parent / f'_model_calvetti_py{ext_suffix}' _model_calvetti_py = amici._module_from_path( 'model_calvetti_py._model_calvetti_py' if __package__ or '.' in __name__ else '_model_calvetti_py', - Path(__file__).parent / f'_model_calvetti_py{ext_suffix}', + extension_path, ) def _get_import_time(): @@ -36,6 +37,28 @@ if t_imported < t_modified: %module(package="model_calvetti_py",moduleimport=MODULEIMPORT) model_calvetti_py +// store swig version +%constant int SWIG_VERSION_MAJOR = (SWIG_VERSION >> 16); +%constant int SWIG_VERSION_MINOR = ((SWIG_VERSION >> 8) & 0xff); +%constant int SWIG_VERSION_PATCH = (SWIG_VERSION & 0xff); + +%pythoncode %{ +# SWIG version used to build the model extension as `(major, minor, patch)` +_SWIG_VERSION = (SWIG_VERSION_MAJOR, SWIG_VERSION_MINOR, SWIG_VERSION_PATCH) + +if (amici_swig := amici.amici._SWIG_VERSION) != (model_swig := _SWIG_VERSION): + import warnings + warnings.warn( + f"SWIG version mismatch between amici ({amici_swig}) and model " + f"({model_swig}). This may lead to unexpected behavior. " + "In that case, please recompile the model with swig==" + f"{amici_swig[0]}.{amici_swig[1]}.{amici_swig[2]} or rebuild amici " + f"with swig=={model_swig[0]}.{model_swig[1]}.{model_swig[2]}.", + RuntimeWarning, + stacklevel=2, + ) +%} + %pythoncode %{ # the model-package __init__.py module (will be set during import) _model_module = None @@ -56,7 +79,7 @@ using namespace amici; // store the time a module was imported %{ #include -static std::chrono::time_point _module_import_time; +static std::chrono::time_point _module_import_time = std::chrono::system_clock::now(); static double _get_import_time() { auto epoch = _module_import_time.time_since_epoch(); @@ -67,7 +90,9 @@ static double _get_import_time() { static double _get_import_time(); %init %{ - _module_import_time = std::chrono::system_clock::now(); + // NOTE: from SWIG 4.4.0 onwards, %init code is executed every time the + // module is executed - not only on first import + // This code ends up in `SWIG_mod_exec`. %} diff --git a/models/model_dirac_py/main.cpp b/models/model_dirac_py/main.cpp index d6969550af..6cf4f96026 100644 --- a/models/model_dirac_py/main.cpp +++ b/models/model_dirac_py/main.cpp @@ -38,7 +38,7 @@ int main() { solver->set_relative_tolerance(1e-8); // Run the simulation using default parameters set during model import - // (can be changed using model->setParameters() or model->setParameterBy*()) + // (can be changed using model->set_free_parameters() or model->set_free_parameter_by*()) auto rdata = run_simulation(*solver, nullptr, *model); // Print observable time course @@ -69,7 +69,7 @@ int main() { // Print state sensitivities sx... // ... for the first timepoint... int i_time = 0; - // ... with respect to the first parameter + // ... with respect to the first free parameter int i_nplist = 0; // get identifiers from model diff --git a/models/model_dirac_py/model_dirac_py.cpp b/models/model_dirac_py/model_dirac_py.cpp index e0b939a903..c173bf7726 100644 --- a/models/model_dirac_py/model_dirac_py.cpp +++ b/models/model_dirac_py/model_dirac_py.cpp @@ -5,7 +5,7 @@ namespace amici::model_model_dirac_py { // clang-format off -std::array parameter_names = { +std::array free_parameter_names = { "p1", // p[0] "p2", // p[1] "p3", // p[2] @@ -33,7 +33,7 @@ std::array expression_names = { "flux_r0", // w[0] }; -std::array parameter_ids = { +std::array free_parameter_ids = { "p1", // p[0] "p2", // p[1] "p3", // p[2] diff --git a/models/model_dirac_py/model_dirac_py.h b/models/model_dirac_py/model_dirac_py.h index c9a25268e8..137b6203bd 100644 --- a/models/model_dirac_py/model_dirac_py.h +++ b/models/model_dirac_py/model_dirac_py.h @@ -14,7 +14,7 @@ class Solver; namespace model_model_dirac_py { -extern std::array parameter_names; +extern std::array free_parameter_names; extern std::array fixed_parameter_names; extern std::array state_names; extern std::array observable_names; @@ -144,7 +144,7 @@ class Model_model_dirac_py : public amici::Model_ODE { }, amici::SimulationParameters( std::vector{}, // fixedParameters - std::vector{1.0, 0.5, 2.0, 3.0} // dynamic parameters + std::vector{1.0, 0.5, 2.0, 3.0} // free parameters ), amici::SecondOrderMode::none, // o2mode std::vector{1.0, 1.0}, // idlist @@ -408,12 +408,12 @@ class Model_model_dirac_py : public amici::Model_ODE { } /** - * @brief Get names of the model parameters + * @brief Get names of the free model parameters * @return the names */ - std::vector get_parameter_names() const override { - return std::vector(parameter_names.begin(), - parameter_names.end()); + std::vector get_free_parameter_names() const override { + return std::vector(free_parameter_names.begin(), + free_parameter_names.end()); } /** @@ -465,7 +465,7 @@ class Model_model_dirac_py : public amici::Model_ODE { } /** - * @brief Get ids of the model parameters + * @brief Get ids of the free model parameters * @return the ids */ std::vector get_free_parameter_ids() const override { @@ -544,7 +544,7 @@ class Model_model_dirac_py : public amici::Model_ODE { * @return AMICI git commit hash */ std::string get_amici_commit() const override { - return "f005fac9e2de7c3c90be2ac55d4ad165471ed1e7"; + return "40190b46b1b398e321314ded4169fe910b37c484"; } bool has_quadratic_llh() const override { diff --git a/models/model_dirac_py/model_dirac_py/model_dirac_py.py b/models/model_dirac_py/model_dirac_py/model_dirac_py.py index e9ed86904f..fa04165fdc 100644 --- a/models/model_dirac_py/model_dirac_py/model_dirac_py.py +++ b/models/model_dirac_py/model_dirac_py/model_dirac_py.py @@ -1,5 +1,5 @@ # This file was automatically generated by SWIG (https://www.swig.org). -# Version 4.3.1 +# Version 4.4.0 # # Do not make changes to this file unless you know what you are doing - modify # the SWIG interface file instead. @@ -14,10 +14,11 @@ from pathlib import Path ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +extension_path = Path(__file__).parent / f'_model_dirac_py{ext_suffix}' _model_dirac_py = amici._module_from_path( 'model_dirac_py._model_dirac_py' if __package__ or '.' in __name__ else '_model_dirac_py', - Path(__file__).parent / f'_model_dirac_py{ext_suffix}', + extension_path, ) def _get_import_time(): @@ -86,6 +87,25 @@ class _SwigNonDynamicMeta(type): __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__) +SWIG_VERSION_MAJOR = _model_dirac_py.SWIG_VERSION_MAJOR +SWIG_VERSION_MINOR = _model_dirac_py.SWIG_VERSION_MINOR +SWIG_VERSION_PATCH = _model_dirac_py.SWIG_VERSION_PATCH + +# SWIG version used to build the model extension as `(major, minor, patch)` +_SWIG_VERSION = (SWIG_VERSION_MAJOR, SWIG_VERSION_MINOR, SWIG_VERSION_PATCH) + +if (amici_swig := amici.amici._SWIG_VERSION) != (model_swig := _SWIG_VERSION): + import warnings + warnings.warn( + f"SWIG version mismatch between amici ({amici_swig}) and model " + f"({model_swig}). This may lead to unexpected behavior. " + "In that case, please recompile the model with swig==" + f"{amici_swig[0]}.{amici_swig[1]}.{amici_swig[2]} or rebuild amici " + f"with swig=={model_swig[0]}.{model_swig[1]}.{model_swig[2]}.", + RuntimeWarning, + stacklevel=2, + ) + # the model-package __init__.py module (will be set during import) _model_module = None diff --git a/models/model_dirac_py/setup.py b/models/model_dirac_py/setup.py index 96a986db12..44eff82bd1 100644 --- a/models/model_dirac_py/setup.py +++ b/models/model_dirac_py/setup.py @@ -1,5 +1,6 @@ """AMICI model package setup""" +import importlib.metadata import os import sys from pathlib import Path @@ -8,7 +9,6 @@ from amici.custom_commands import AmiciBuildCMakeExtension from cmake_build_extension import CMakeExtension from setuptools import find_namespace_packages, setup -import importlib.metadata def get_extension() -> CMakeExtension: diff --git a/models/model_dirac_py/swig/model_dirac_py.i b/models/model_dirac_py/swig/model_dirac_py.i index 27869edf00..248e97e644 100644 --- a/models/model_dirac_py/swig/model_dirac_py.i +++ b/models/model_dirac_py/swig/model_dirac_py.i @@ -8,10 +8,11 @@ import sysconfig from pathlib import Path ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +extension_path = Path(__file__).parent / f'_model_dirac_py{ext_suffix}' _model_dirac_py = amici._module_from_path( 'model_dirac_py._model_dirac_py' if __package__ or '.' in __name__ else '_model_dirac_py', - Path(__file__).parent / f'_model_dirac_py{ext_suffix}', + extension_path, ) def _get_import_time(): @@ -36,6 +37,28 @@ if t_imported < t_modified: %module(package="model_dirac_py",moduleimport=MODULEIMPORT) model_dirac_py +// store swig version +%constant int SWIG_VERSION_MAJOR = (SWIG_VERSION >> 16); +%constant int SWIG_VERSION_MINOR = ((SWIG_VERSION >> 8) & 0xff); +%constant int SWIG_VERSION_PATCH = (SWIG_VERSION & 0xff); + +%pythoncode %{ +# SWIG version used to build the model extension as `(major, minor, patch)` +_SWIG_VERSION = (SWIG_VERSION_MAJOR, SWIG_VERSION_MINOR, SWIG_VERSION_PATCH) + +if (amici_swig := amici.amici._SWIG_VERSION) != (model_swig := _SWIG_VERSION): + import warnings + warnings.warn( + f"SWIG version mismatch between amici ({amici_swig}) and model " + f"({model_swig}). This may lead to unexpected behavior. " + "In that case, please recompile the model with swig==" + f"{amici_swig[0]}.{amici_swig[1]}.{amici_swig[2]} or rebuild amici " + f"with swig=={model_swig[0]}.{model_swig[1]}.{model_swig[2]}.", + RuntimeWarning, + stacklevel=2, + ) +%} + %pythoncode %{ # the model-package __init__.py module (will be set during import) _model_module = None @@ -56,7 +79,7 @@ using namespace amici; // store the time a module was imported %{ #include -static std::chrono::time_point _module_import_time; +static std::chrono::time_point _module_import_time = std::chrono::system_clock::now(); static double _get_import_time() { auto epoch = _module_import_time.time_since_epoch(); @@ -67,7 +90,9 @@ static double _get_import_time() { static double _get_import_time(); %init %{ - _module_import_time = std::chrono::system_clock::now(); + // NOTE: from SWIG 4.4.0 onwards, %init code is executed every time the + // module is executed - not only on first import + // This code ends up in `SWIG_mod_exec`. %} diff --git a/models/model_events_py/main.cpp b/models/model_events_py/main.cpp index d6969550af..6cf4f96026 100644 --- a/models/model_events_py/main.cpp +++ b/models/model_events_py/main.cpp @@ -38,7 +38,7 @@ int main() { solver->set_relative_tolerance(1e-8); // Run the simulation using default parameters set during model import - // (can be changed using model->setParameters() or model->setParameterBy*()) + // (can be changed using model->set_free_parameters() or model->set_free_parameter_by*()) auto rdata = run_simulation(*solver, nullptr, *model); // Print observable time course @@ -69,7 +69,7 @@ int main() { // Print state sensitivities sx... // ... for the first timepoint... int i_time = 0; - // ... with respect to the first parameter + // ... with respect to the first free parameter int i_nplist = 0; // get identifiers from model diff --git a/models/model_events_py/model_events_py.cpp b/models/model_events_py/model_events_py.cpp index 87bb71c88e..056e4bf79c 100644 --- a/models/model_events_py/model_events_py.cpp +++ b/models/model_events_py/model_events_py.cpp @@ -5,7 +5,7 @@ namespace amici::model_model_events_py { // clang-format off -std::array parameter_names = { +std::array free_parameter_names = { "p1", // p[0] "p2", // p[1] "p3", // p[2] @@ -37,7 +37,7 @@ std::array expression_names = { "flux_r0", // w[0] }; -std::array parameter_ids = { +std::array free_parameter_ids = { "p1", // p[0] "p2", // p[1] "p3", // p[2] diff --git a/models/model_events_py/model_events_py.h b/models/model_events_py/model_events_py.h index b8c5170485..88ffdaf37d 100644 --- a/models/model_events_py/model_events_py.h +++ b/models/model_events_py/model_events_py.h @@ -20,7 +20,7 @@ extern std::array state_names; extern std::array observable_names; extern std::array observable_scalings; extern std::array expression_names; -extern std::array parameter_ids; +extern std::array free_parameter_ids; extern std::array fixed_parameter_ids; extern std::array state_ids; extern std::array observable_ids; @@ -144,7 +144,7 @@ class Model_model_events_py : public amici::Model_ODE { }, amici::SimulationParameters( std::vector{4.0, 8.0, 10.0, 4.0}, // fixedParameters - std::vector{0.5, 2.0, 0.5, 0.5} // dynamic parameters + std::vector{0.5, 2.0, 0.5, 0.5} // free parameters ), amici::SecondOrderMode::none, // o2mode std::vector{1.0, 1.0, 1.0}, // idlist @@ -443,7 +443,7 @@ class Model_model_events_py : public amici::Model_ODE { } /** - * @brief Get names of the model parameters + * @brief Get names of the free model parameters * @return the names */ std::vector get_free_parameter_names() const override { @@ -500,12 +500,12 @@ class Model_model_events_py : public amici::Model_ODE { } /** - * @brief Get ids of the model parameters + * @brief Get ids of the free model parameters * @return the ids */ - std::vector get_parameter_ids() const override { - return std::vector(parameter_ids.begin(), - parameter_ids.end()); + std::vector get_free_parameter_ids() const override { + return std::vector(free_parameter_ids.begin(), + free_parameter_ids.end()); } /** @@ -579,7 +579,7 @@ class Model_model_events_py : public amici::Model_ODE { * @return AMICI git commit hash */ std::string get_amici_commit() const override { - return "f005fac9e2de7c3c90be2ac55d4ad165471ed1e7"; + return "40190b46b1b398e321314ded4169fe910b37c484"; } bool has_quadratic_llh() const override { diff --git a/models/model_events_py/setup.py b/models/model_events_py/setup.py index 0b7665b708..95fc57311a 100644 --- a/models/model_events_py/setup.py +++ b/models/model_events_py/setup.py @@ -1,5 +1,6 @@ """AMICI model package setup""" +import importlib.metadata import os import sys from pathlib import Path @@ -8,7 +9,6 @@ from amici.custom_commands import AmiciBuildCMakeExtension from cmake_build_extension import CMakeExtension from setuptools import find_namespace_packages, setup -import importlib.metadata def get_extension() -> CMakeExtension: diff --git a/models/model_events_py/swig/model_events_py.i b/models/model_events_py/swig/model_events_py.i index f86cbab411..c14cdef4e2 100644 --- a/models/model_events_py/swig/model_events_py.i +++ b/models/model_events_py/swig/model_events_py.i @@ -8,10 +8,11 @@ import sysconfig from pathlib import Path ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +extension_path = Path(__file__).parent / f'_model_events_py{ext_suffix}' _model_events_py = amici._module_from_path( 'model_events_py._model_events_py' if __package__ or '.' in __name__ else '_model_events_py', - Path(__file__).parent / f'_model_events_py{ext_suffix}', + extension_path, ) def _get_import_time(): @@ -36,6 +37,28 @@ if t_imported < t_modified: %module(package="model_events_py",moduleimport=MODULEIMPORT) model_events_py +// store swig version +%constant int SWIG_VERSION_MAJOR = (SWIG_VERSION >> 16); +%constant int SWIG_VERSION_MINOR = ((SWIG_VERSION >> 8) & 0xff); +%constant int SWIG_VERSION_PATCH = (SWIG_VERSION & 0xff); + +%pythoncode %{ +# SWIG version used to build the model extension as `(major, minor, patch)` +_SWIG_VERSION = (SWIG_VERSION_MAJOR, SWIG_VERSION_MINOR, SWIG_VERSION_PATCH) + +if (amici_swig := amici.amici._SWIG_VERSION) != (model_swig := _SWIG_VERSION): + import warnings + warnings.warn( + f"SWIG version mismatch between amici ({amici_swig}) and model " + f"({model_swig}). This may lead to unexpected behavior. " + "In that case, please recompile the model with swig==" + f"{amici_swig[0]}.{amici_swig[1]}.{amici_swig[2]} or rebuild amici " + f"with swig=={model_swig[0]}.{model_swig[1]}.{model_swig[2]}.", + RuntimeWarning, + stacklevel=2, + ) +%} + %pythoncode %{ # the model-package __init__.py module (will be set during import) _model_module = None @@ -56,7 +79,7 @@ using namespace amici; // store the time a module was imported %{ #include -static std::chrono::time_point _module_import_time; +static std::chrono::time_point _module_import_time = std::chrono::system_clock::now(); static double _get_import_time() { auto epoch = _module_import_time.time_since_epoch(); @@ -67,7 +90,9 @@ static double _get_import_time() { static double _get_import_time(); %init %{ - _module_import_time = std::chrono::system_clock::now(); + // NOTE: from SWIG 4.4.0 onwards, %init code is executed every time the + // module is executed - not only on first import + // This code ends up in `SWIG_mod_exec`. %} diff --git a/models/model_jakstat_adjoint_py/main.cpp b/models/model_jakstat_adjoint_py/main.cpp index d6969550af..6cf4f96026 100644 --- a/models/model_jakstat_adjoint_py/main.cpp +++ b/models/model_jakstat_adjoint_py/main.cpp @@ -38,7 +38,7 @@ int main() { solver->set_relative_tolerance(1e-8); // Run the simulation using default parameters set during model import - // (can be changed using model->setParameters() or model->setParameterBy*()) + // (can be changed using model->set_free_parameters() or model->set_free_parameter_by*()) auto rdata = run_simulation(*solver, nullptr, *model); // Print observable time course @@ -69,7 +69,7 @@ int main() { // Print state sensitivities sx... // ... for the first timepoint... int i_time = 0; - // ... with respect to the first parameter + // ... with respect to the first free parameter int i_nplist = 0; // get identifiers from model diff --git a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.cpp b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.cpp index c584ee0582..1d933731aa 100644 --- a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.cpp +++ b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.cpp @@ -5,7 +5,7 @@ namespace amici::model_model_jakstat_adjoint_py { // clang-format off -std::array parameter_names = { +std::array free_parameter_names = { "p1", // p[0] "p2", // p[1] "p3", // p[2] @@ -59,7 +59,7 @@ std::array expression_names = { "flux_r0", // w[1] }; -std::array parameter_ids = { +std::array free_parameter_ids = { "p1", // p[0] "p2", // p[1] "p3", // p[2] diff --git a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h index 06ccd44eff..e8b1aff3bf 100644 --- a/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h +++ b/models/model_jakstat_adjoint_py/model_jakstat_adjoint_py.h @@ -144,7 +144,7 @@ class Model_model_jakstat_adjoint_py : public amici::Model_ODE { }, amici::SimulationParameters( std::vector{1.3999999999999999, 0.45000000000000001}, // fixedParameters - std::vector{3.9810717055349727, 1000.0, 0.11220184543019635, 0.98287887300003218, 1.0, 0.0015848931924611134, 0.54954087385762451, 0.84139514164519513, 0.38904514499428061, 9.9999999999999991e-6, 0.18197008586099833, 0.22908676527677729, 0.77624711662869172, 1.0641430182243161, 0.31622776601683794, 1.0, 0.31622776601683794} // dynamic parameters + std::vector{3.9810717055349727, 1000.0, 0.11220184543019635, 0.98287887300003218, 1.0, 0.0015848931924611134, 0.54954087385762451, 0.84139514164519513, 0.38904514499428061, 9.9999999999999991e-6, 0.18197008586099833, 0.22908676527677729, 0.77624711662869172, 1.0641430182243161, 0.31622776601683794, 1.0, 0.31622776601683794} // free parameters ), amici::SecondOrderMode::none, // o2mode std::vector{1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0}, // idlist @@ -416,7 +416,7 @@ class Model_model_jakstat_adjoint_py : public amici::Model_ODE { } /** - * @brief Get names of the model parameters + * @brief Get names of the free model parameters * @return the names */ std::vector get_free_parameter_names() const override { @@ -473,7 +473,7 @@ class Model_model_jakstat_adjoint_py : public amici::Model_ODE { } /** - * @brief Get ids of the model parameters + * @brief Get ids of the free model parameters * @return the ids */ std::vector get_free_parameter_ids() const override { @@ -552,7 +552,7 @@ class Model_model_jakstat_adjoint_py : public amici::Model_ODE { * @return AMICI git commit hash */ std::string get_amici_commit() const override { - return "f005fac9e2de7c3c90be2ac55d4ad165471ed1e7"; + return "40190b46b1b398e321314ded4169fe910b37c484"; } bool has_quadratic_llh() const override { diff --git a/models/model_jakstat_adjoint_py/setup.py b/models/model_jakstat_adjoint_py/setup.py index 34f6a26701..adaf524116 100644 --- a/models/model_jakstat_adjoint_py/setup.py +++ b/models/model_jakstat_adjoint_py/setup.py @@ -1,5 +1,6 @@ """AMICI model package setup""" +import importlib.metadata import os import sys from pathlib import Path @@ -8,7 +9,6 @@ from amici.custom_commands import AmiciBuildCMakeExtension from cmake_build_extension import CMakeExtension from setuptools import find_namespace_packages, setup -import importlib.metadata def get_extension() -> CMakeExtension: diff --git a/models/model_jakstat_adjoint_py/swig/model_jakstat_adjoint_py.i b/models/model_jakstat_adjoint_py/swig/model_jakstat_adjoint_py.i index 3f05b98996..ab94d3c927 100644 --- a/models/model_jakstat_adjoint_py/swig/model_jakstat_adjoint_py.i +++ b/models/model_jakstat_adjoint_py/swig/model_jakstat_adjoint_py.i @@ -8,10 +8,11 @@ import sysconfig from pathlib import Path ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +extension_path = Path(__file__).parent / f'_model_jakstat_adjoint_py{ext_suffix}' _model_jakstat_adjoint_py = amici._module_from_path( 'model_jakstat_adjoint_py._model_jakstat_adjoint_py' if __package__ or '.' in __name__ else '_model_jakstat_adjoint_py', - Path(__file__).parent / f'_model_jakstat_adjoint_py{ext_suffix}', + extension_path, ) def _get_import_time(): @@ -36,6 +37,28 @@ if t_imported < t_modified: %module(package="model_jakstat_adjoint_py",moduleimport=MODULEIMPORT) model_jakstat_adjoint_py +// store swig version +%constant int SWIG_VERSION_MAJOR = (SWIG_VERSION >> 16); +%constant int SWIG_VERSION_MINOR = ((SWIG_VERSION >> 8) & 0xff); +%constant int SWIG_VERSION_PATCH = (SWIG_VERSION & 0xff); + +%pythoncode %{ +# SWIG version used to build the model extension as `(major, minor, patch)` +_SWIG_VERSION = (SWIG_VERSION_MAJOR, SWIG_VERSION_MINOR, SWIG_VERSION_PATCH) + +if (amici_swig := amici.amici._SWIG_VERSION) != (model_swig := _SWIG_VERSION): + import warnings + warnings.warn( + f"SWIG version mismatch between amici ({amici_swig}) and model " + f"({model_swig}). This may lead to unexpected behavior. " + "In that case, please recompile the model with swig==" + f"{amici_swig[0]}.{amici_swig[1]}.{amici_swig[2]} or rebuild amici " + f"with swig=={model_swig[0]}.{model_swig[1]}.{model_swig[2]}.", + RuntimeWarning, + stacklevel=2, + ) +%} + %pythoncode %{ # the model-package __init__.py module (will be set during import) _model_module = None @@ -56,7 +79,7 @@ using namespace amici; // store the time a module was imported %{ #include -static std::chrono::time_point _module_import_time; +static std::chrono::time_point _module_import_time = std::chrono::system_clock::now(); static double _get_import_time() { auto epoch = _module_import_time.time_since_epoch(); @@ -67,7 +90,9 @@ static double _get_import_time() { static double _get_import_time(); %init %{ - _module_import_time = std::chrono::system_clock::now(); + // NOTE: from SWIG 4.4.0 onwards, %init code is executed every time the + // module is executed - not only on first import + // This code ends up in `SWIG_mod_exec`. %} diff --git a/models/model_nested_events_py/main.cpp b/models/model_nested_events_py/main.cpp index d6969550af..6cf4f96026 100644 --- a/models/model_nested_events_py/main.cpp +++ b/models/model_nested_events_py/main.cpp @@ -38,7 +38,7 @@ int main() { solver->set_relative_tolerance(1e-8); // Run the simulation using default parameters set during model import - // (can be changed using model->setParameters() or model->setParameterBy*()) + // (can be changed using model->set_free_parameters() or model->set_free_parameter_by*()) auto rdata = run_simulation(*solver, nullptr, *model); // Print observable time course @@ -69,7 +69,7 @@ int main() { // Print state sensitivities sx... // ... for the first timepoint... int i_time = 0; - // ... with respect to the first parameter + // ... with respect to the first free parameter int i_nplist = 0; // get identifiers from model diff --git a/models/model_nested_events_py/model_nested_events_py.cpp b/models/model_nested_events_py/model_nested_events_py.cpp index 40603e18e2..1237c430bf 100644 --- a/models/model_nested_events_py/model_nested_events_py.cpp +++ b/models/model_nested_events_py/model_nested_events_py.cpp @@ -5,7 +5,7 @@ namespace amici::model_model_nested_events_py { // clang-format off -std::array parameter_names = { +std::array free_parameter_names = { "V_0", // p[0] "V_0_inject", // p[1] "t_0", // p[2] @@ -33,7 +33,7 @@ std::array expression_names = { "flux_r0", // w[0] }; -std::array parameter_ids = { +std::array free_parameter_ids = { "V_0", // p[0] "V_0_inject", // p[1] "t_0", // p[2] diff --git a/models/model_nested_events_py/model_nested_events_py.h b/models/model_nested_events_py/model_nested_events_py.h index e9d70ea315..ca2de85ebe 100644 --- a/models/model_nested_events_py/model_nested_events_py.h +++ b/models/model_nested_events_py/model_nested_events_py.h @@ -20,7 +20,7 @@ extern std::array state_names; extern std::array observable_names; extern std::array observable_scalings; extern std::array expression_names; -extern std::array parameter_ids; +extern std::array free_parameter_ids; extern std::array fixed_parameter_ids; extern std::array state_ids; extern std::array observable_ids; @@ -144,7 +144,7 @@ class Model_model_nested_events_py : public amici::Model_ODE { }, amici::SimulationParameters( std::vector{}, // fixedParameters - std::vector{0.10000000000000001, 1000.0, 2.0, 0.80000000000000004, 1.6000000000000001} // dynamic parameters + std::vector{0.10000000000000001, 1000.0, 2.0, 0.80000000000000004, 1.6000000000000001} // free parameters ), amici::SecondOrderMode::none, // o2mode std::vector{1.0}, // idlist @@ -416,7 +416,7 @@ class Model_model_nested_events_py : public amici::Model_ODE { } /** - * @brief Get names of the model parameters + * @brief Get names of the free model parameters * @return the names */ std::vector get_free_parameter_names() const override { @@ -473,7 +473,7 @@ class Model_model_nested_events_py : public amici::Model_ODE { } /** - * @brief Get ids of the model parameters + * @brief Get ids of the free model parameters * @return the ids */ std::vector get_free_parameter_ids() const override { @@ -552,7 +552,7 @@ class Model_model_nested_events_py : public amici::Model_ODE { * @return AMICI git commit hash */ std::string get_amici_commit() const override { - return "f005fac9e2de7c3c90be2ac55d4ad165471ed1e7"; + return "40190b46b1b398e321314ded4169fe910b37c484"; } bool has_quadratic_llh() const override { diff --git a/models/model_nested_events_py/setup.py b/models/model_nested_events_py/setup.py index a3f550259e..23443c712d 100644 --- a/models/model_nested_events_py/setup.py +++ b/models/model_nested_events_py/setup.py @@ -1,5 +1,6 @@ """AMICI model package setup""" +import importlib.metadata import os import sys from pathlib import Path @@ -8,7 +9,6 @@ from amici.custom_commands import AmiciBuildCMakeExtension from cmake_build_extension import CMakeExtension from setuptools import find_namespace_packages, setup -import importlib.metadata def get_extension() -> CMakeExtension: diff --git a/models/model_nested_events_py/swig/model_nested_events_py.i b/models/model_nested_events_py/swig/model_nested_events_py.i index 9f03945317..2a6453a644 100644 --- a/models/model_nested_events_py/swig/model_nested_events_py.i +++ b/models/model_nested_events_py/swig/model_nested_events_py.i @@ -8,10 +8,11 @@ import sysconfig from pathlib import Path ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +extension_path = Path(__file__).parent / f'_model_nested_events_py{ext_suffix}' _model_nested_events_py = amici._module_from_path( 'model_nested_events_py._model_nested_events_py' if __package__ or '.' in __name__ else '_model_nested_events_py', - Path(__file__).parent / f'_model_nested_events_py{ext_suffix}', + extension_path, ) def _get_import_time(): @@ -36,6 +37,28 @@ if t_imported < t_modified: %module(package="model_nested_events_py",moduleimport=MODULEIMPORT) model_nested_events_py +// store swig version +%constant int SWIG_VERSION_MAJOR = (SWIG_VERSION >> 16); +%constant int SWIG_VERSION_MINOR = ((SWIG_VERSION >> 8) & 0xff); +%constant int SWIG_VERSION_PATCH = (SWIG_VERSION & 0xff); + +%pythoncode %{ +# SWIG version used to build the model extension as `(major, minor, patch)` +_SWIG_VERSION = (SWIG_VERSION_MAJOR, SWIG_VERSION_MINOR, SWIG_VERSION_PATCH) + +if (amici_swig := amici.amici._SWIG_VERSION) != (model_swig := _SWIG_VERSION): + import warnings + warnings.warn( + f"SWIG version mismatch between amici ({amici_swig}) and model " + f"({model_swig}). This may lead to unexpected behavior. " + "In that case, please recompile the model with swig==" + f"{amici_swig[0]}.{amici_swig[1]}.{amici_swig[2]} or rebuild amici " + f"with swig=={model_swig[0]}.{model_swig[1]}.{model_swig[2]}.", + RuntimeWarning, + stacklevel=2, + ) +%} + %pythoncode %{ # the model-package __init__.py module (will be set during import) _model_module = None @@ -56,7 +79,7 @@ using namespace amici; // store the time a module was imported %{ #include -static std::chrono::time_point _module_import_time; +static std::chrono::time_point _module_import_time = std::chrono::system_clock::now(); static double _get_import_time() { auto epoch = _module_import_time.time_since_epoch(); @@ -67,7 +90,9 @@ static double _get_import_time() { static double _get_import_time(); %init %{ - _module_import_time = std::chrono::system_clock::now(); + // NOTE: from SWIG 4.4.0 onwards, %init code is executed every time the + // module is executed - not only on first import + // This code ends up in `SWIG_mod_exec`. %} diff --git a/models/model_neuron_py/main.cpp b/models/model_neuron_py/main.cpp index d6969550af..6cf4f96026 100644 --- a/models/model_neuron_py/main.cpp +++ b/models/model_neuron_py/main.cpp @@ -38,7 +38,7 @@ int main() { solver->set_relative_tolerance(1e-8); // Run the simulation using default parameters set during model import - // (can be changed using model->setParameters() or model->setParameterBy*()) + // (can be changed using model->set_free_parameters() or model->set_free_parameter_by*()) auto rdata = run_simulation(*solver, nullptr, *model); // Print observable time course @@ -69,7 +69,7 @@ int main() { // Print state sensitivities sx... // ... for the first timepoint... int i_time = 0; - // ... with respect to the first parameter + // ... with respect to the first free parameter int i_nplist = 0; // get identifiers from model diff --git a/models/model_neuron_py/model_neuron_py.cpp b/models/model_neuron_py/model_neuron_py.cpp index 5ca0b9d008..70995ad2e2 100644 --- a/models/model_neuron_py/model_neuron_py.cpp +++ b/models/model_neuron_py/model_neuron_py.cpp @@ -5,7 +5,7 @@ namespace amici::model_model_neuron_py { // clang-format off -std::array parameter_names = { +std::array free_parameter_names = { "a", // p[0] "b", // p[1] "c", // p[2] @@ -34,7 +34,7 @@ std::array expression_names = { "flux_r0", // w[0] }; -std::array parameter_ids = { +std::array free_parameter_ids = { "a", // p[0] "b", // p[1] "c", // p[2] diff --git a/models/model_neuron_py/model_neuron_py.h b/models/model_neuron_py/model_neuron_py.h index 501011aa7f..96b7ba48fd 100644 --- a/models/model_neuron_py/model_neuron_py.h +++ b/models/model_neuron_py/model_neuron_py.h @@ -144,7 +144,7 @@ class Model_model_neuron_py : public amici::Model_ODE { }, amici::SimulationParameters( std::vector{-60.0, 10.0}, // fixedParameters - std::vector{0.02, 0.29999999999999999, 65.0, 0.90000000000000002} // dynamic parameters + std::vector{0.02, 0.29999999999999999, 65.0, 0.90000000000000002} // free parameters ), amici::SecondOrderMode::none, // o2mode std::vector{1.0, 1.0}, // idlist @@ -438,7 +438,7 @@ class Model_model_neuron_py : public amici::Model_ODE { } /** - * @brief Get names of the model parameters + * @brief Get names of the free model parameters * @return the names */ std::vector get_free_parameter_names() const override { @@ -495,7 +495,7 @@ class Model_model_neuron_py : public amici::Model_ODE { } /** - * @brief Get ids of the model parameters + * @brief Get ids of the free model parameters * @return the ids */ std::vector get_free_parameter_ids() const override { @@ -574,7 +574,7 @@ class Model_model_neuron_py : public amici::Model_ODE { * @return AMICI git commit hash */ std::string get_amici_commit() const override { - return "f005fac9e2de7c3c90be2ac55d4ad165471ed1e7"; + return "40190b46b1b398e321314ded4169fe910b37c484"; } bool has_quadratic_llh() const override { diff --git a/models/model_neuron_py/setup.py b/models/model_neuron_py/setup.py index ea902ab899..b1338bd9ca 100644 --- a/models/model_neuron_py/setup.py +++ b/models/model_neuron_py/setup.py @@ -1,5 +1,6 @@ """AMICI model package setup""" +import importlib.metadata import os import sys from pathlib import Path @@ -8,7 +9,6 @@ from amici.custom_commands import AmiciBuildCMakeExtension from cmake_build_extension import CMakeExtension from setuptools import find_namespace_packages, setup -import importlib.metadata def get_extension() -> CMakeExtension: diff --git a/models/model_neuron_py/swig/model_neuron_py.i b/models/model_neuron_py/swig/model_neuron_py.i index 949da25226..539af3b45b 100644 --- a/models/model_neuron_py/swig/model_neuron_py.i +++ b/models/model_neuron_py/swig/model_neuron_py.i @@ -8,10 +8,11 @@ import sysconfig from pathlib import Path ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +extension_path = Path(__file__).parent / f'_model_neuron_py{ext_suffix}' _model_neuron_py = amici._module_from_path( 'model_neuron_py._model_neuron_py' if __package__ or '.' in __name__ else '_model_neuron_py', - Path(__file__).parent / f'_model_neuron_py{ext_suffix}', + extension_path, ) def _get_import_time(): @@ -36,6 +37,28 @@ if t_imported < t_modified: %module(package="model_neuron_py",moduleimport=MODULEIMPORT) model_neuron_py +// store swig version +%constant int SWIG_VERSION_MAJOR = (SWIG_VERSION >> 16); +%constant int SWIG_VERSION_MINOR = ((SWIG_VERSION >> 8) & 0xff); +%constant int SWIG_VERSION_PATCH = (SWIG_VERSION & 0xff); + +%pythoncode %{ +# SWIG version used to build the model extension as `(major, minor, patch)` +_SWIG_VERSION = (SWIG_VERSION_MAJOR, SWIG_VERSION_MINOR, SWIG_VERSION_PATCH) + +if (amici_swig := amici.amici._SWIG_VERSION) != (model_swig := _SWIG_VERSION): + import warnings + warnings.warn( + f"SWIG version mismatch between amici ({amici_swig}) and model " + f"({model_swig}). This may lead to unexpected behavior. " + "In that case, please recompile the model with swig==" + f"{amici_swig[0]}.{amici_swig[1]}.{amici_swig[2]} or rebuild amici " + f"with swig=={model_swig[0]}.{model_swig[1]}.{model_swig[2]}.", + RuntimeWarning, + stacklevel=2, + ) +%} + %pythoncode %{ # the model-package __init__.py module (will be set during import) _model_module = None @@ -56,7 +79,7 @@ using namespace amici; // store the time a module was imported %{ #include -static std::chrono::time_point _module_import_time; +static std::chrono::time_point _module_import_time = std::chrono::system_clock::now(); static double _get_import_time() { auto epoch = _module_import_time.time_since_epoch(); @@ -67,7 +90,9 @@ static double _get_import_time() { static double _get_import_time(); %init %{ - _module_import_time = std::chrono::system_clock::now(); + // NOTE: from SWIG 4.4.0 onwards, %init code is executed every time the + // module is executed - not only on first import + // This code ends up in `SWIG_mod_exec`. %} diff --git a/models/model_robertson_py/main.cpp b/models/model_robertson_py/main.cpp index d6969550af..6cf4f96026 100644 --- a/models/model_robertson_py/main.cpp +++ b/models/model_robertson_py/main.cpp @@ -38,7 +38,7 @@ int main() { solver->set_relative_tolerance(1e-8); // Run the simulation using default parameters set during model import - // (can be changed using model->setParameters() or model->setParameterBy*()) + // (can be changed using model->set_free_parameters() or model->set_free_parameter_by*()) auto rdata = run_simulation(*solver, nullptr, *model); // Print observable time course @@ -69,7 +69,7 @@ int main() { // Print state sensitivities sx... // ... for the first timepoint... int i_time = 0; - // ... with respect to the first parameter + // ... with respect to the first free parameter int i_nplist = 0; // get identifiers from model diff --git a/models/model_robertson_py/model_robertson_py.cpp b/models/model_robertson_py/model_robertson_py.cpp index c274f12cda..145282b8b9 100644 --- a/models/model_robertson_py/model_robertson_py.cpp +++ b/models/model_robertson_py/model_robertson_py.cpp @@ -5,7 +5,7 @@ namespace amici::model_model_robertson_py { // clang-format off -std::array parameter_names = { +std::array free_parameter_names = { "p1", // p[0] "p2", // p[1] "p3", // p[2] @@ -37,7 +37,7 @@ std::array expression_names = { "flux_r0", // w[0] }; -std::array parameter_ids = { +std::array free_parameter_ids = { "p1", // p[0] "p2", // p[1] "p3", // p[2] diff --git a/models/model_robertson_py/model_robertson_py.h b/models/model_robertson_py/model_robertson_py.h index 4e35a64e2d..959f379c5a 100644 --- a/models/model_robertson_py/model_robertson_py.h +++ b/models/model_robertson_py/model_robertson_py.h @@ -144,7 +144,7 @@ class Model_model_robertson_py : public amici::Model_DAE { }, amici::SimulationParameters( std::vector{0.90000000000000002}, // fixedParameters - std::vector{0.040000000000000001, 10000.0, 30000000.0} // dynamic parameters + std::vector{0.040000000000000001, 10000.0, 30000000.0} // free parameters ), amici::SecondOrderMode::none, // o2mode std::vector{1.0, 1.0, 0.0}, // idlist @@ -400,7 +400,7 @@ class Model_model_robertson_py : public amici::Model_DAE { } /** - * @brief Get names of the model parameters + * @brief Get names of the free model parameters * @return the names */ std::vector get_free_parameter_names() const override { @@ -457,7 +457,7 @@ class Model_model_robertson_py : public amici::Model_DAE { } /** - * @brief Get ids of the model parameters + * @brief Get ids of the free model parameters * @return the ids */ std::vector get_free_parameter_ids() const override { @@ -536,7 +536,7 @@ class Model_model_robertson_py : public amici::Model_DAE { * @return AMICI git commit hash */ std::string get_amici_commit() const override { - return "f005fac9e2de7c3c90be2ac55d4ad165471ed1e7"; + return "40190b46b1b398e321314ded4169fe910b37c484"; } bool has_quadratic_llh() const override { diff --git a/models/model_robertson_py/setup.py b/models/model_robertson_py/setup.py index db4c2f0b85..ca942279e5 100644 --- a/models/model_robertson_py/setup.py +++ b/models/model_robertson_py/setup.py @@ -1,5 +1,6 @@ """AMICI model package setup""" +import importlib.metadata import os import sys from pathlib import Path @@ -8,7 +9,6 @@ from amici.custom_commands import AmiciBuildCMakeExtension from cmake_build_extension import CMakeExtension from setuptools import find_namespace_packages, setup -import importlib.metadata def get_extension() -> CMakeExtension: diff --git a/models/model_robertson_py/swig/model_robertson_py.i b/models/model_robertson_py/swig/model_robertson_py.i index 99e14a1916..d62408f6c0 100644 --- a/models/model_robertson_py/swig/model_robertson_py.i +++ b/models/model_robertson_py/swig/model_robertson_py.i @@ -8,10 +8,11 @@ import sysconfig from pathlib import Path ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +extension_path = Path(__file__).parent / f'_model_robertson_py{ext_suffix}' _model_robertson_py = amici._module_from_path( 'model_robertson_py._model_robertson_py' if __package__ or '.' in __name__ else '_model_robertson_py', - Path(__file__).parent / f'_model_robertson_py{ext_suffix}', + extension_path, ) def _get_import_time(): @@ -36,6 +37,28 @@ if t_imported < t_modified: %module(package="model_robertson_py",moduleimport=MODULEIMPORT) model_robertson_py +// store swig version +%constant int SWIG_VERSION_MAJOR = (SWIG_VERSION >> 16); +%constant int SWIG_VERSION_MINOR = ((SWIG_VERSION >> 8) & 0xff); +%constant int SWIG_VERSION_PATCH = (SWIG_VERSION & 0xff); + +%pythoncode %{ +# SWIG version used to build the model extension as `(major, minor, patch)` +_SWIG_VERSION = (SWIG_VERSION_MAJOR, SWIG_VERSION_MINOR, SWIG_VERSION_PATCH) + +if (amici_swig := amici.amici._SWIG_VERSION) != (model_swig := _SWIG_VERSION): + import warnings + warnings.warn( + f"SWIG version mismatch between amici ({amici_swig}) and model " + f"({model_swig}). This may lead to unexpected behavior. " + "In that case, please recompile the model with swig==" + f"{amici_swig[0]}.{amici_swig[1]}.{amici_swig[2]} or rebuild amici " + f"with swig=={model_swig[0]}.{model_swig[1]}.{model_swig[2]}.", + RuntimeWarning, + stacklevel=2, + ) +%} + %pythoncode %{ # the model-package __init__.py module (will be set during import) _model_module = None @@ -56,7 +79,7 @@ using namespace amici; // store the time a module was imported %{ #include -static std::chrono::time_point _module_import_time; +static std::chrono::time_point _module_import_time = std::chrono::system_clock::now(); static double _get_import_time() { auto epoch = _module_import_time.time_since_epoch(); @@ -67,7 +90,9 @@ static double _get_import_time() { static double _get_import_time(); %init %{ - _module_import_time = std::chrono::system_clock::now(); + // NOTE: from SWIG 4.4.0 onwards, %init code is executed every time the + // module is executed - not only on first import + // This code ends up in `SWIG_mod_exec`. %} diff --git a/models/model_steadystate_py/main.cpp b/models/model_steadystate_py/main.cpp index a7a833273f..6cf4f96026 100644 --- a/models/model_steadystate_py/main.cpp +++ b/models/model_steadystate_py/main.cpp @@ -38,7 +38,7 @@ int main() { solver->set_relative_tolerance(1e-8); // Run the simulation using default parameters set during model import - // (can be changed using model->setParameters() or model->setParameterBy*()) + // (can be changed using model->set_free_parameters() or model->set_free_parameter_by*()) auto rdata = run_simulation(*solver, nullptr, *model); // Print observable time course @@ -69,12 +69,12 @@ int main() { // Print state sensitivities sx... // ... for the first timepoint... int i_time = 0; - // ... with respect to the first parameter + // ... with respect to the first free parameter int i_nplist = 0; // get identifiers from model auto state_ids = model->get_state_ids(); - auto parameter_ids = model->get_free_parameter_ids(); + auto free_parameter_ids = model->get_free_parameter_ids(); std::cout << "State sensitivities for timepoint " << rdata->ts[i_time] << std::endl; // nt x nplist x nx diff --git a/models/model_steadystate_py/model_steadystate_py.cpp b/models/model_steadystate_py/model_steadystate_py.cpp index 88ab4724d2..58da853481 100644 --- a/models/model_steadystate_py/model_steadystate_py.cpp +++ b/models/model_steadystate_py/model_steadystate_py.cpp @@ -5,7 +5,7 @@ namespace amici::model_model_steadystate_py { // clang-format off -std::array parameter_names = { +std::array free_parameter_names = { "p1", // p[0] "p2", // p[1] "p3", // p[2] @@ -42,7 +42,7 @@ std::array expression_names = { "flux_r0", // w[0] }; -std::array parameter_ids = { +std::array free_parameter_ids = { "p1", // p[0] "p2", // p[1] "p3", // p[2] diff --git a/models/model_steadystate_py/model_steadystate_py.h b/models/model_steadystate_py/model_steadystate_py.h index cf57982fad..335ddff398 100644 --- a/models/model_steadystate_py/model_steadystate_py.h +++ b/models/model_steadystate_py/model_steadystate_py.h @@ -144,7 +144,7 @@ class Model_model_steadystate_py : public amici::Model_ODE { }, amici::SimulationParameters( std::vector{0.10000000000000001, 0.40000000000000002, 0.69999999999999996, 1.0}, // fixedParameters - std::vector{1.0, 0.5, 0.40000000000000002, 2.0, 0.10000000000000001} // dynamic parameters + std::vector{1.0, 0.5, 0.40000000000000002, 2.0, 0.10000000000000001} // free parameters ), amici::SecondOrderMode::none, // o2mode std::vector{1.0, 1.0, 1.0}, // idlist @@ -400,7 +400,7 @@ class Model_model_steadystate_py : public amici::Model_ODE { } /** - * @brief Get names of the model parameters + * @brief Get names of the free model parameters * @return the names */ std::vector get_free_parameter_names() const override { @@ -457,7 +457,7 @@ class Model_model_steadystate_py : public amici::Model_ODE { } /** - * @brief Get ids of the model parameters + * @brief Get ids of the free model parameters * @return the ids */ std::vector get_free_parameter_ids() const override { @@ -536,7 +536,7 @@ class Model_model_steadystate_py : public amici::Model_ODE { * @return AMICI git commit hash */ std::string get_amici_commit() const override { - return "f005fac9e2de7c3c90be2ac55d4ad165471ed1e7"; + return "40190b46b1b398e321314ded4169fe910b37c484"; } bool has_quadratic_llh() const override { diff --git a/models/model_steadystate_py/model_steadystate_py/__init__.py b/models/model_steadystate_py/model_steadystate_py/__init__.py index 6407687e8f..0dfa676313 100644 --- a/models/model_steadystate_py/model_steadystate_py/__init__.py +++ b/models/model_steadystate_py/model_steadystate_py/__init__.py @@ -1,9 +1,10 @@ """AMICI-generated module for model model_steadystate_py""" import sys +import warnings from pathlib import Path + import amici -import warnings # Ensure we are binary-compatible, see #556 if "0.34.1" != amici.__version__: diff --git a/models/model_steadystate_py/setup.py b/models/model_steadystate_py/setup.py index 2741e047ae..dc11b7a2c8 100644 --- a/models/model_steadystate_py/setup.py +++ b/models/model_steadystate_py/setup.py @@ -1,5 +1,6 @@ """AMICI model package setup""" +import importlib.metadata import os import sys from pathlib import Path @@ -8,7 +9,6 @@ from amici.custom_commands import AmiciBuildCMakeExtension from cmake_build_extension import CMakeExtension from setuptools import find_namespace_packages, setup -import importlib.metadata def get_extension() -> CMakeExtension: diff --git a/models/model_steadystate_py/swig/model_steadystate_py.i b/models/model_steadystate_py/swig/model_steadystate_py.i index f9e5333fa9..cdd2483406 100644 --- a/models/model_steadystate_py/swig/model_steadystate_py.i +++ b/models/model_steadystate_py/swig/model_steadystate_py.i @@ -8,10 +8,11 @@ import sysconfig from pathlib import Path ext_suffix = sysconfig.get_config_var('EXT_SUFFIX') +extension_path = Path(__file__).parent / f'_model_steadystate_py{ext_suffix}' _model_steadystate_py = amici._module_from_path( 'model_steadystate_py._model_steadystate_py' if __package__ or '.' in __name__ else '_model_steadystate_py', - Path(__file__).parent / f'_model_steadystate_py{ext_suffix}', + extension_path, ) def _get_import_time(): @@ -36,6 +37,28 @@ if t_imported < t_modified: %module(package="model_steadystate_py",moduleimport=MODULEIMPORT) model_steadystate_py +// store swig version +%constant int SWIG_VERSION_MAJOR = (SWIG_VERSION >> 16); +%constant int SWIG_VERSION_MINOR = ((SWIG_VERSION >> 8) & 0xff); +%constant int SWIG_VERSION_PATCH = (SWIG_VERSION & 0xff); + +%pythoncode %{ +# SWIG version used to build the model extension as `(major, minor, patch)` +_SWIG_VERSION = (SWIG_VERSION_MAJOR, SWIG_VERSION_MINOR, SWIG_VERSION_PATCH) + +if (amici_swig := amici.amici._SWIG_VERSION) != (model_swig := _SWIG_VERSION): + import warnings + warnings.warn( + f"SWIG version mismatch between amici ({amici_swig}) and model " + f"({model_swig}). This may lead to unexpected behavior. " + "In that case, please recompile the model with swig==" + f"{amici_swig[0]}.{amici_swig[1]}.{amici_swig[2]} or rebuild amici " + f"with swig=={model_swig[0]}.{model_swig[1]}.{model_swig[2]}.", + RuntimeWarning, + stacklevel=2, + ) +%} + %pythoncode %{ # the model-package __init__.py module (will be set during import) _model_module = None @@ -56,7 +79,7 @@ using namespace amici; // store the time a module was imported %{ #include -static std::chrono::time_point _module_import_time; +static std::chrono::time_point _module_import_time = std::chrono::system_clock::now(); static double _get_import_time() { auto epoch = _module_import_time.time_since_epoch(); @@ -67,7 +90,9 @@ static double _get_import_time() { static double _get_import_time(); %init %{ - _module_import_time = std::chrono::system_clock::now(); + // NOTE: from SWIG 4.4.0 onwards, %init code is executed every time the + // module is executed - not only on first import + // This code ends up in `SWIG_mod_exec`. %} diff --git a/python/sdist/amici/exporters/sundials/de_export.py b/python/sdist/amici/exporters/sundials/de_export.py index e0215579fc..c6865a57cf 100644 --- a/python/sdist/amici/exporters/sundials/de_export.py +++ b/python/sdist/amici/exporters/sundials/de_export.py @@ -1028,13 +1028,13 @@ def event_initializer_list() -> str: "NK": self.model.num_const(), "O2MODE": "amici::SecondOrderMode::none", # using code printer ensures proper handling of nan/inf - "PARAMETERS": self._code_printer.doprint(self.model.val("p"))[ + "FREE_PARAMETERS": self._code_printer.doprint(self.model.val("p"))[ 1:-1 ], "FIXED_PARAMETERS": self._code_printer.doprint( self.model.val("k") )[1:-1], - "PARAMETER_NAMES_INITIALIZER_LIST": self._get_symbol_name_initializer_list( + "FREE_PARAMETER_NAMES_INITIALIZER_LIST": self._get_symbol_name_initializer_list( "p" ), "STATE_NAMES_INITIALIZER_LIST": self._get_symbol_name_initializer_list( @@ -1055,7 +1055,7 @@ def event_initializer_list() -> str: "EXPRESSION_NAMES_INITIALIZER_LIST": self._get_symbol_name_initializer_list( "w" ), - "PARAMETER_IDS_INITIALIZER_LIST": self._get_symbol_id_initializer_list( + "FREE_PARAMETER_IDS_INITIALIZER_LIST": self._get_symbol_id_initializer_list( "p" ), "STATE_IDS_INITIALIZER_LIST": self._get_symbol_id_initializer_list( diff --git a/python/sdist/amici/exporters/sundials/templates/main.template.cpp b/python/sdist/amici/exporters/sundials/templates/main.template.cpp index d6969550af..6cf4f96026 100644 --- a/python/sdist/amici/exporters/sundials/templates/main.template.cpp +++ b/python/sdist/amici/exporters/sundials/templates/main.template.cpp @@ -38,7 +38,7 @@ int main() { solver->set_relative_tolerance(1e-8); // Run the simulation using default parameters set during model import - // (can be changed using model->setParameters() or model->setParameterBy*()) + // (can be changed using model->set_free_parameters() or model->set_free_parameter_by*()) auto rdata = run_simulation(*solver, nullptr, *model); // Print observable time course @@ -69,7 +69,7 @@ int main() { // Print state sensitivities sx... // ... for the first timepoint... int i_time = 0; - // ... with respect to the first parameter + // ... with respect to the first free parameter int i_nplist = 0; // get identifiers from model diff --git a/python/sdist/amici/exporters/sundials/templates/model.template.cpp b/python/sdist/amici/exporters/sundials/templates/model.template.cpp index 8d23113c10..5bee191c3d 100644 --- a/python/sdist/amici/exporters/sundials/templates/model.template.cpp +++ b/python/sdist/amici/exporters/sundials/templates/model.template.cpp @@ -5,8 +5,8 @@ namespace amici::model_TPL_MODELNAME { // clang-format off -std::array parameter_names = { - TPL_PARAMETER_NAMES_INITIALIZER_LIST +std::array free_parameter_names = { + TPL_FREE_PARAMETER_NAMES_INITIALIZER_LIST }; std::array fixed_parameter_names = { @@ -29,8 +29,8 @@ std::array expression_names = { TPL_EXPRESSION_NAMES_INITIALIZER_LIST }; -std::array parameter_ids = { - TPL_PARAMETER_IDS_INITIALIZER_LIST +std::array free_parameter_ids = { + TPL_FREE_PARAMETER_IDS_INITIALIZER_LIST }; std::array fixed_parameter_ids = { diff --git a/python/sdist/amici/exporters/sundials/templates/model_header.template.h b/python/sdist/amici/exporters/sundials/templates/model_header.template.h index 52c972b395..e71b556f36 100644 --- a/python/sdist/amici/exporters/sundials/templates/model_header.template.h +++ b/python/sdist/amici/exporters/sundials/templates/model_header.template.h @@ -144,7 +144,7 @@ class Model_TPL_MODELNAME : public amici::Model_TPL_MODEL_TYPE_UPPER { }, amici::SimulationParameters( std::vector{TPL_FIXED_PARAMETERS}, // fixedParameters - std::vector{TPL_PARAMETERS} // dynamic parameters + std::vector{TPL_FREE_PARAMETERS} // free parameters ), TPL_O2MODE, // o2mode std::vector{TPL_ID}, // idlist @@ -288,7 +288,7 @@ class Model_TPL_MODELNAME : public amici::Model_TPL_MODEL_TYPE_UPPER { } /** - * @brief Get names of the model parameters + * @brief Get names of the free model parameters * @return the names */ std::vector get_free_parameter_names() const override { @@ -345,7 +345,7 @@ class Model_TPL_MODELNAME : public amici::Model_TPL_MODEL_TYPE_UPPER { } /** - * @brief Get ids of the model parameters + * @brief Get ids of the free model parameters * @return the ids */ std::vector get_free_parameter_ids() const override { From f0bc5d1d82ef1c0e49a4f87433b332b69463e62f Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Thu, 13 Nov 2025 23:11:57 +0100 Subject: [PATCH 14/23] Rename py --- .../GettingStartedExtended.ipynb | 30 ++++++++-------- python/sdist/amici/debugging/__init__.py | 2 +- python/sdist/amici/gradient_check.py | 12 +++---- python/sdist/amici/pandas.py | 2 +- python/sdist/amici/petab/petab_importer.py | 2 +- python/sdist/amici/swig_wrappers.py | 2 +- python/tests/test_edata.py | 2 +- python/tests/test_jax.py | 4 +-- python/tests/test_preequilibration.py | 6 ++-- python/tests/test_pysb.py | 2 +- python/tests/test_sbml_import.py | 36 +++++++++---------- python/tests/test_swig_interface.py | 10 +++--- python/tests/util.py | 4 +-- tests/performance/test.py | 16 ++++----- 14 files changed, 66 insertions(+), 64 deletions(-) diff --git a/doc/examples/getting_started_extended/GettingStartedExtended.ipynb b/doc/examples/getting_started_extended/GettingStartedExtended.ipynb index 94c6463039..0538c8cba2 100644 --- a/doc/examples/getting_started_extended/GettingStartedExtended.ipynb +++ b/doc/examples/getting_started_extended/GettingStartedExtended.ipynb @@ -415,7 +415,7 @@ "print(\n", " \"Simulation was run using model default parameters as specified in the SBML model:\"\n", ")\n", - "print(dict(zip(model.get_free_parameter_ids(), model.get_parameters())))" + "print(dict(zip(model.get_free_parameter_ids(), model.get_free_parameters())))" ] }, { @@ -1111,11 +1111,11 @@ "source": [ "# Set model options\n", "model = model_module.get_model()\n", - "p_orig = np.array(model.get_parameters())\n", + "p_orig = np.array(model.get_free_parameters())\n", "p_orig[\n", " list(model.get_free_parameter_ids()).index(\"observable_x1withsigma_sigma\")\n", "] = 0.1 # Change default parameter\n", - "model.set_parameters(p_orig)\n", + "model.set_free_parameters(p_orig)\n", "model.set_parameter_scale(amici.ParameterScaling.none)\n", "model.set_timepoints(np.linspace(0, 10, 21))\n", "\n", @@ -1172,12 +1172,12 @@ " p[plist] = x0\n", " verbose and print(f\"f: p={p}\")\n", "\n", - " old_parameters = model.get_parameters()\n", + " old_parameters = model.get_free_parameters()\n", " solver.set_sensitivity_order(amici.SensitivityOrder.none)\n", - " model.set_parameters(p)\n", + " model.set_free_parameters(p)\n", " rdata = amici.run_simulation(model, solver, edata)\n", "\n", - " model.set_parameters(old_parameters)\n", + " model.set_free_parameters(old_parameters)\n", "\n", " res = np.sum(rdata[symbol])\n", " verbose and print(res)\n", @@ -1194,13 +1194,13 @@ " model.require_sensitivities_for_all_parameters()\n", " verbose and print(f\"g: p={p}\")\n", "\n", - " old_parameters = model.get_parameters()\n", + " old_parameters = model.get_free_parameters()\n", " solver.set_sensitivity_method(amici.SensitivityMethod.forward)\n", " solver.set_sensitivity_order(amici.SensitivityOrder.first)\n", - " model.set_parameters(p)\n", + " model.set_free_parameters(p)\n", " rdata = amici.run_simulation(model, solver, edata)\n", "\n", - " model.set_parameters(old_parameters)\n", + " model.set_free_parameters(old_parameters)\n", "\n", " res = rdata[f\"s{symbol}\"]\n", " if not isinstance(res, float):\n", @@ -1255,7 +1255,7 @@ "outputs": [], "source": [ "eps = 1e-4\n", - "op = model.get_parameters()\n", + "op = model.get_free_parameters()\n", "\n", "\n", "solver.set_sensitivity_method(\n", @@ -1271,23 +1271,23 @@ "\n", "def fd(x0, ip, eps, symbol=\"llh\"):\n", " p = list(x0[:])\n", - " old_parameters = model.get_parameters()\n", + " old_parameters = model.get_free_parameters()\n", " solver.set_sensitivity_order(amici.SensitivityOrder.none)\n", " p[ip] += eps\n", - " model.set_parameters(p)\n", + " model.set_free_parameters(p)\n", " rdata_f = amici.run_simulation(model, solver, edata)\n", " p[ip] -= 2 * eps\n", - " model.set_parameters(p)\n", + " model.set_free_parameters(p)\n", " rdata_b = amici.run_simulation(model, solver, edata)\n", "\n", - " model.set_parameters(old_parameters)\n", + " model.set_free_parameters(old_parameters)\n", " return (rdata_f[symbol] - rdata_b[symbol]) / (2 * eps)\n", "\n", "\n", "def plot_sensitivities(symbol, eps):\n", " fig, axes = plt.subplots(4, 2, figsize=(15, 10))\n", " for ip in range(4):\n", - " fd_approx = fd(model.get_parameters(), ip, eps, symbol=symbol)\n", + " fd_approx = fd(model.get_free_parameters(), ip, eps, symbol=symbol)\n", "\n", " axes[ip, 0].plot(\n", " edata.get_timepoints(), rdata[f\"s{symbol}\"][:, ip, :], \"r-\"\n", diff --git a/python/sdist/amici/debugging/__init__.py b/python/sdist/amici/debugging/__init__.py index 656ae9c6ca..856c542092 100644 --- a/python/sdist/amici/debugging/__init__.py +++ b/python/sdist/amici/debugging/__init__.py @@ -36,7 +36,7 @@ def get_model_for_preeq(model: amici.Model, edata: amici.ExpData): if edata.pscale: model.set_parameter_scale(edata.pscale) if edata.free_parameters: - model.set_parameters(edata.free_parameters) + model.set_free_parameters(edata.free_parameters) if edata.plist: model.set_parameter_list(edata.plist) model.set_initial_state(edata.x0) diff --git a/python/sdist/amici/gradient_check.py b/python/sdist/amici/gradient_check.py index d14a59bbef..0286488e33 100644 --- a/python/sdist/amici/gradient_check.py +++ b/python/sdist/amici/gradient_check.py @@ -71,7 +71,7 @@ def check_finite_difference( # store original settings and apply new ones og_sensitivity_order = solver.get_sensitivity_order() - og_parameters = model.get_parameters() + og_parameters = model.get_free_parameters() og_plist = model.get_parameter_list() if edata: og_eplist = edata.plist @@ -88,7 +88,7 @@ def check_finite_difference( model.set_parameter_list(plist) model.set_parameter_scale(pscale) - model.set_parameters(p) + model.set_free_parameters(p) # simulation with gradient if int(og_sensitivity_order) < int(SensitivityOrder.first): @@ -110,13 +110,13 @@ def check_finite_difference( pb[ip] /= 1 + epsilon / 2 # forward: - model.set_parameters(pf) + model.set_free_parameters(pf) rdataf = run_simulation(model, solver, edata) if rdataf["status"] != AMICI_SUCCESS: raise AssertionError(f"Simulation failed (status {rdataf['status']}") # backward: - model.set_parameters(pb) + model.set_free_parameters(pb) rdatab = run_simulation(model, solver, edata) if rdatab["status"] != AMICI_SUCCESS: raise AssertionError(f"Simulation failed (status {rdatab['status']}") @@ -146,7 +146,7 @@ def check_finite_difference( ) solver.set_sensitivity_order(og_sensitivity_order) - model.set_parameters(og_parameters) + model.set_free_parameters(og_parameters) model.set_parameter_list(og_plist) if edata: edata.plist = og_eplist @@ -182,7 +182,7 @@ def check_derivatives( if edata and edata.free_parameters: p = np.array(edata.free_parameters) else: - p = np.array(model.get_parameters()) + p = np.array(model.get_free_parameters()) og_sens_order = solver.get_sensitivity_order() diff --git a/python/sdist/amici/pandas.py b/python/sdist/amici/pandas.py index 7166494b30..2f1cbaffbf 100644 --- a/python/sdist/amici/pandas.py +++ b/python/sdist/amici/pandas.py @@ -421,7 +421,7 @@ def _fill_conditions_dict( if len(edata.free_parameters): datadict[par] = edata.free_parameters[i_par] else: - datadict[par] = model.get_parameters()[i_par] + datadict[par] = model.get_free_parameters()[i_par] if len(edata.pscale): datadict[par + "_scale"] = edata.pscale[i_par] diff --git a/python/sdist/amici/petab/petab_importer.py b/python/sdist/amici/petab/petab_importer.py index dc56ba168b..663172b460 100644 --- a/python/sdist/amici/petab/petab_importer.py +++ b/python/sdist/amici/petab/petab_importer.py @@ -681,7 +681,7 @@ def __init__( # create a new model instance from the model module from which # we can get the default parameters model0 = model.module.get_model() - self._original_p = np.array(model0.get_parameters()) + self._original_p = np.array(model0.get_free_parameters()) self._original_k = np.array(model0.get_fixed_parameters()) def create_edatas(self) -> list[amici.ExpData]: diff --git a/python/sdist/amici/swig_wrappers.py b/python/sdist/amici/swig_wrappers.py index 5fa0fc5962..abbab7cc29 100644 --- a/python/sdist/amici/swig_wrappers.py +++ b/python/sdist/amici/swig_wrappers.py @@ -266,7 +266,7 @@ def _ids_and_names_to_rdata( "state", "observable", "expression", - "parameter", + "free_parameter", "fixed_parameter", ): for name_or_id in ("ids", "names"): diff --git a/python/tests/test_edata.py b/python/tests/test_edata.py index a6e9a81583..e81fd0ebff 100644 --- a/python/tests/test_edata.py +++ b/python/tests/test_edata.py @@ -28,7 +28,7 @@ def test_edata_sensi_unscaling(model_units_module): # noqa: F811 model = model_units_module.get_model() model.set_timepoints(np.linspace(0, 1, 3)) model.set_parameter_scale(parameter_scales_log10) - model.set_parameters(parameters0) + model.set_free_parameters(parameters0) solver = model.create_solver() solver.set_sensitivity_order(amici.SensitivityOrder.first) diff --git a/python/tests/test_jax.py b/python/tests/test_jax.py index a4701df155..922f81afca 100644 --- a/python/tests/test_jax.py +++ b/python/tests/test_jax.py @@ -129,10 +129,10 @@ def _test_model(amici_module, jax_module, ts, p, k): jax_model = jax_module.Model() - amici_model.set_parameters(np.asarray(p, dtype=np.float64)) + amici_model.set_free_parameters(np.asarray(p, dtype=np.float64)) amici_model.set_fixed_parameters(np.asarray(k, dtype=np.float64)) edata = amici.ExpData(sol_amici_ref, 1.0, 1.0) - edata.free_parameters = amici_model.get_parameters() + edata.free_parameters = amici_model.get_free_parameters() edata.fixed_parameters = amici_model.get_fixed_parameters() edata.pscale = amici_model.get_parameter_scale() amici_solver = amici_model.create_solver() diff --git a/python/tests/test_preequilibration.py b/python/tests/test_preequilibration.py index 546d506751..a8ae783365 100644 --- a/python/tests/test_preequilibration.py +++ b/python/tests/test_preequilibration.py @@ -279,9 +279,11 @@ def test_parameter_in_expdata(preeq_fixture): model.set_parameter_list([i for i in reversed(model.get_parameter_list())]) # set ExpData parameters - edata.free_parameters = model.get_parameters() + edata.free_parameters = model.get_free_parameters() # perturb model parameters - model.set_parameters(tuple(p * 2 for p in model.get_parameters())) + model.set_free_parameters( + tuple(p * 2 for p in model.get_free_parameters()) + ) # set ExpData pscale edata.pscale = model.get_parameter_scale() diff --git a/python/tests/test_pysb.py b/python/tests/test_pysb.py index 7f2823d26f..aef0142fa5 100644 --- a/python/tests/test_pysb.py +++ b/python/tests/test_pysb.py @@ -239,7 +239,7 @@ def test_compare_to_pysb_simulation(example): ParameterScaling.log10 if p > 0 else ParameterScaling.none - for p in model_pysb.get_parameters() + for p in model_pysb.get_free_parameters() ] ) ) diff --git a/python/tests/test_sbml_import.py b/python/tests/test_sbml_import.py index 1e50fc5aa0..574bfcf7b2 100644 --- a/python/tests/test_sbml_import.py +++ b/python/tests/test_sbml_import.py @@ -781,26 +781,26 @@ def custom_nllh(m, y, sigma): def _test_set_parameters_by_dict(model_module): """Test setting parameter via id/name => value dicts""" model = model_module.get_model() - old_parameter_values = model.get_parameters() + old_parameter_values = model.get_free_parameters() free_parameter_ids = model.get_free_parameter_ids() change_par_id = free_parameter_ids[-1] new_par_val = 0.1234 - old_par_val = model.get_parameter_by_id(change_par_id) + old_par_val = model.get_free_parameter_by_id(change_par_id) - assert model.get_parameter_by_id(change_par_id) != new_par_val - model.set_parameter_by_id({change_par_id: new_par_val}) - assert model.get_parameter_by_id(change_par_id) == new_par_val + assert model.get_free_parameter_by_id(change_par_id) != new_par_val + model.set_free_parameter_by_id({change_par_id: new_par_val}) + assert model.get_free_parameter_by_id(change_par_id) == new_par_val # reset and check we are back to original - model.set_parameter_by_id(change_par_id, old_par_val) - assert model.get_parameters() == old_parameter_values + model.set_free_parameter_by_id(change_par_id, old_par_val) + assert model.get_free_parameters() == old_parameter_values # Same for by-name parameter_names = model.get_free_parameter_names() change_par_name = parameter_names[-1] - model.set_parameter_by_name({change_par_name: new_par_val}) - assert model.get_parameter_by_name(change_par_name) == new_par_val - model.set_parameter_by_name(change_par_name, old_par_val) - assert model.get_parameters() == old_parameter_values + model.set_free_parameter_by_name({change_par_name: new_par_val}) + assert model.get_free_parameter_by_name(change_par_name) == new_par_val + model.set_free_parameter_by_name(change_par_name, old_par_val) + assert model.get_free_parameters() == old_parameter_values @skip_on_valgrind @@ -962,7 +962,7 @@ def test_import_same_model_name(tempdir): model_module_1 = import_model_module( module_name=module_name, module_path=outdir_1 ) - assert model_module_1.get_model().get_parameters()[0] == 1.0 + assert model_module_1.get_model().get_free_parameters()[0] == 1.0 # no error if the same model is loaded again without changes on disk model_module_1b = import_model_module( @@ -971,13 +971,13 @@ def test_import_same_model_name(tempdir): # downside: the modules will compare as different assert (model_module_1 == model_module_1b) is False assert model_module_1.__file__ == model_module_1b.__file__ - assert model_module_1b.get_model().get_parameters()[0] == 1.0 + assert model_module_1b.get_model().get_free_parameters()[0] == 1.0 model_module_2 = import_model_module( module_name=module_name, module_path=outdir_2 ) - assert model_module_1.get_model().get_parameters()[0] == 1.0 - assert model_module_2.get_model().get_parameters()[0] == 2.0 + assert model_module_1.get_model().get_free_parameters()[0] == 1.0 + assert model_module_2.get_model().get_free_parameters()[0] == 2.0 # import the third model, with the same name and location as the second # model -- this is not supported, because there is some caching at @@ -1000,14 +1000,14 @@ def test_import_same_model_name(tempdir): import_model_module(module_name=module_name, module_path=outdir_2) # this should not affect the previously loaded models - assert model_module_1.get_model().get_parameters()[0] == 1.0 - assert model_module_2.get_model().get_parameters()[0] == 2.0 + assert model_module_1.get_model().get_free_parameters()[0] == 1.0 + assert model_module_2.get_model().get_free_parameters()[0] == 2.0 # test that we can still import the model classically if we wanted to: with amici.set_path(outdir_1): import test_same_extension as model_module_1c # noqa: F401 - assert model_module_1c.get_model().get_parameters()[0] == 1.0 + assert model_module_1c.get_model().get_free_parameters()[0] == 1.0 assert model_module_1c.get_model().module is model_module_1c diff --git a/python/tests/test_swig_interface.py b/python/tests/test_swig_interface.py index 504874d09a..ab53d37e5b 100644 --- a/python/tests/test_swig_interface.py +++ b/python/tests/test_swig_interface.py @@ -339,10 +339,10 @@ def test_unhandled_settings(pysb_example_presimulation_module): "set_fixed_parameter_by_name", "set_fixed_parameters_by_id_regex", "set_fixed_parameters_by_name_regex", - "set_parameter_by_id", - "set_parameter_by_name", - "set_parameters_by_id_regex", - "set_parameters_by_name_regex", + "set_free_parameter_by_id", + "set_free_parameter_by_name", + "set_free_parameters_by_id_regex", + "set_free_parameters_by_name_regex", "set_initial_state_sensitivities", "get_trigger_timepoints", "get_any_state_nonnegative", @@ -605,7 +605,7 @@ def test_python_exceptions(sbml_example_presimulation_module): ) # model throws, base catches, swig-exception handling is not involved - model.set_parameters([nan] * model.np()) + model.set_free_parameters([nan] * model.np()) model.set_timepoints([1]) rdata = amici.run_simulation(model, solver) assert rdata.status == amici.AMICI_FIRST_RHSFUNC_ERR diff --git a/python/tests/util.py b/python/tests/util.py index c2df3b94ce..4a126a7211 100644 --- a/python/tests/util.py +++ b/python/tests/util.py @@ -143,11 +143,11 @@ def check_trajectories_with_adjoint_sensitivities( for i_par, par in enumerate(parameters): tmp_par = np.array(parameters[:]) tmp_par[i_par] += eps - amici_model.set_parameters(tmp_par) + amici_model.set_free_parameters(tmp_par) rdata_p = run_simulation(amici_model, solver=solver, edata=edata) tmp_par = np.array(parameters[:]) tmp_par[i_par] -= eps - amici_model.set_parameters(tmp_par) + amici_model.set_free_parameters(tmp_par) rdata_m = run_simulation(amici_model, solver=solver, edata=edata) sllh_fd.append((rdata_p["llh"] - rdata_m["llh"]) / (2 * eps)) df["fd"] = sllh_fd diff --git a/tests/performance/test.py b/tests/performance/test.py index 5dd007a573..8d58a01771 100755 --- a/tests/performance/test.py +++ b/tests/performance/test.py @@ -105,18 +105,18 @@ def prepare_simulation(arg, model, solver, edata): solver.set_sensitivity_method(amici.SensitivityMethod.adjoint) solver.set_sensitivity_order(amici.SensitivityOrder.first) elif arg == "forward_simulation_non_optimal_parameters": - tmp_par = model.get_parameters() - model.set_parameters([0.1 for _ in tmp_par]) + tmp_par = model.get_free_parameters() + model.set_free_parameters([0.1 for _ in tmp_par]) solver.set_sensitivity_method(amici.SensitivityMethod.none) solver.set_sensitivity_order(amici.SensitivityOrder.none) elif arg == "adjoint_sensitivities_non_optimal_parameters": - tmp_par = model.get_parameters() - model.set_parameters([0.1 for _ in tmp_par]) + tmp_par = model.get_free_parameters() + model.set_free_parameters([0.1 for _ in tmp_par]) solver.set_sensitivity_method(amici.SensitivityMethod.adjoint) solver.set_sensitivity_order(amici.SensitivityOrder.first) elif arg == "forward_steadystate_sensitivities_non_optimal_parameters": - tmp_par = model.get_parameters() - model.set_parameters([0.1 for _ in tmp_par]) + tmp_par = model.get_free_parameters() + model.set_free_parameters([0.1 for _ in tmp_par]) solver.set_sensitivity_method(amici.SensitivityMethod.forward) solver.set_sensitivity_order(amici.SensitivityOrder.first) model.set_steady_state_sensitivity_mode( @@ -124,8 +124,8 @@ def prepare_simulation(arg, model, solver, edata): ) edata.set_timepoints([float("inf")]) elif arg == "adjoint_steadystate_sensitivities_non_optimal_parameters": - tmp_par = model.get_parameters() - model.set_parameters([0.1 for _ in tmp_par]) + tmp_par = model.get_free_parameters() + model.set_free_parameters([0.1 for _ in tmp_par]) solver.set_sensitivity_method(amici.SensitivityMethod.adjoint) solver.set_sensitivity_order(amici.SensitivityOrder.first) edata.set_timepoints([float("inf")]) From b272be0c3a9da228a672bae564c392c2ecb8e0ef Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Thu, 13 Nov 2025 23:24:55 +0100 Subject: [PATCH 15/23] some more --- doc/examples/example_splines/ExampleSplines.ipynb | 2 +- doc/examples/getting_started/GettingStarted.ipynb | 4 ++-- python/sdist/amici/adapters/fiddy.py | 4 ++-- python/sdist/amici/swig_wrappers.py | 2 +- python/tests/test_pysb.py | 2 +- tests/sbml/utils.py | 4 +++- 6 files changed, 10 insertions(+), 8 deletions(-) diff --git a/doc/examples/example_splines/ExampleSplines.ipynb b/doc/examples/example_splines/ExampleSplines.ipynb index 5b2080eac1..de5125aedb 100644 --- a/doc/examples/example_splines/ExampleSplines.ipynb +++ b/doc/examples/example_splines/ExampleSplines.ipynb @@ -90,7 +90,7 @@ " # Setup simulation timepoints and parameters\n", " model = model_module.get_model()\n", " for name, value in parameters.items():\n", - " model.set_parameter_by_name(name, value)\n", + " model.set_free_parameter_by_name(name, value)\n", " if isinstance(T, int | float):\n", " T = np.linspace(0, T, 100)\n", " model.set_timepoints([float(t) for t in T])\n", diff --git a/doc/examples/getting_started/GettingStarted.ipynb b/doc/examples/getting_started/GettingStarted.ipynb index 1e01d26e81..4b3d9447cc 100644 --- a/doc/examples/getting_started/GettingStarted.ipynb +++ b/doc/examples/getting_started/GettingStarted.ipynb @@ -73,12 +73,12 @@ { "cell_type": "markdown", "metadata": {}, - "source": "The model allows the user to manipulate model related properties of simulations. This includes the values of model parameters that can be set by using [amici.Model.set_parameter_by_name](https://amici.readthedocs.io/en/latest/generated/amici.amici.Model.html#amici.amici.Model.set_parameter_by_name). Here, we set the model parameter `p1` to a value of `1e-3`." + "source": "The model allows the user to manipulate model related properties of simulations. This includes the values of model parameters that can be set by using [amici.Model.set_free_parameter_by_name](https://amici.readthedocs.io/en/latest/generated/amici.amici.Model.html#amici.amici.Model.set_free_parameter_by_name). Here, we set the model parameter `p1` to a value of `1e-3`." }, { "cell_type": "code", "metadata": {}, - "source": "model.set_parameter_by_name(\"p1\", 1e-3)", + "source": "model.set_free_parameter_by_name(\"p1\", 1e-3)", "outputs": [], "execution_count": null }, diff --git a/python/sdist/amici/adapters/fiddy.py b/python/sdist/amici/adapters/fiddy.py index 43587f97bd..79154badcd 100644 --- a/python/sdist/amici/adapters/fiddy.py +++ b/python/sdist/amici/adapters/fiddy.py @@ -153,7 +153,7 @@ def run_amici_simulation( point: Type.POINT, order: SensitivityOrder ) -> ReturnData: problem_parameters = dict(zip(free_parameter_ids, point, strict=True)) - amici_model.set_parameter_by_id(problem_parameters) + amici_model.set_free_parameter_by_id(problem_parameters) amici_solver.set_sensitivity_order(order) rdata = amici.run_simulation( model=amici_model, solver=amici_solver, edata=amici_edata @@ -198,7 +198,7 @@ def derivative(point: Type.POINT, return_dict: bool = False): # Get structure dummy_point = fiddy_array( [ - amici_model.get_parameter_by_id(par_id) + amici_model.get_free_parameter_by_id(par_id) for par_id in free_parameter_ids ] ) diff --git a/python/sdist/amici/swig_wrappers.py b/python/sdist/amici/swig_wrappers.py index abbab7cc29..2040c558a5 100644 --- a/python/sdist/amici/swig_wrappers.py +++ b/python/sdist/amici/swig_wrappers.py @@ -181,7 +181,7 @@ def write_solver_settings_to_hdf5( ), "minimum_sigma_residuals", ("n_max_event", "set_n_max_event"), - "parameters", + "free_parameters", "reinitialization_state_idxs", "reinitialize_fixed_parameter_initial_states", "state_is_non_negative", diff --git a/python/tests/test_pysb.py b/python/tests/test_pysb.py index aef0142fa5..35784fe4e3 100644 --- a/python/tests/test_pysb.py +++ b/python/tests/test_pysb.py @@ -59,7 +59,7 @@ def test_compare_to_sbml_import( # check equilibrium initial parameters assert np.isclose( sum(rdata["x_ss"][[0, 3, 4, 5]]), - model.get_parameter_by_name("PROT_0"), + model.get_free_parameter_by_name("PROT_0"), atol=1e-6, rtol=1e-6, ), f"{importer} preequilibration" diff --git a/tests/sbml/utils.py b/tests/sbml/utils.py index f92f413b29..973fa9469f 100644 --- a/tests/sbml/utils.py +++ b/tests/sbml/utils.py @@ -36,7 +36,9 @@ def verify_results( # collect parameters for par in model.get_free_parameter_ids(): - parameter_data[par] = rdata["ts"] * 0 + model.get_parameter_by_id(par) + parameter_data[par] = rdata["ts"] * 0 + model.get_free_parameter_by_id( + par + ) expression_data = {} From a5c05e625f48afd200791424b0f3e0db747a4bc1 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Fri, 14 Nov 2025 07:41:42 +0100 Subject: [PATCH 16/23] .. --- python/sdist/amici/pandas.py | 2 +- python/tests/test_swig_interface.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/sdist/amici/pandas.py b/python/sdist/amici/pandas.py index 2f1cbaffbf..ae37acf12a 100644 --- a/python/sdist/amici/pandas.py +++ b/python/sdist/amici/pandas.py @@ -608,7 +608,7 @@ def _get_names_or_ids( """ # check whether variable type permitted variable_options = [ - "parameter", + "free_parameter", "fixed_parameter", "observable", "state", diff --git a/python/tests/test_swig_interface.py b/python/tests/test_swig_interface.py index ab53d37e5b..272ef31bac 100644 --- a/python/tests/test_swig_interface.py +++ b/python/tests/test_swig_interface.py @@ -98,7 +98,7 @@ def test_copy_constructors(pysb_example_presimulation_module): 10, 20, ], - "parameters": [(10.0, 0.1, 0.1, 0.1, 0.1, 0.1), tuple([1.0] * 6)], + "free_parameters": [(10.0, 0.1, 0.1, 0.1, 0.1, 0.1), tuple([1.0] * 6)], # Skipped due to interdependency with `'InitialStateSensitivities'`. "parameter_list": None, # Skipped due to interdependency with `'InitialStateSensitivities'`. From ed5fdb0276215a6d10c1060fa573fdd602bc6578 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Fri, 14 Nov 2025 08:11:59 +0100 Subject: [PATCH 17/23] .. --- python/sdist/amici/pandas.py | 26 ++++++++++--------- .../benchmark_models/test_petab_benchmark.py | 4 +-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/python/sdist/amici/pandas.py b/python/sdist/amici/pandas.py index ae37acf12a..97497d619c 100644 --- a/python/sdist/amici/pandas.py +++ b/python/sdist/amici/pandas.py @@ -416,7 +416,7 @@ def _fill_conditions_dict( datadict[par + "_presim"] = np.nan for i_par, par in enumerate( - _get_names_or_ids(model, "parameter", by_id=by_id) + _get_names_or_ids(model, "free_parameter", by_id=by_id) ): if len(edata.free_parameters): datadict[par] = edata.free_parameters[i_par] @@ -460,10 +460,10 @@ def _get_extended_observable_cols(model: AmiciModel, by_id: bool) -> list[str]: model, "fixed_parameter", by_id=by_id ) ] - + _get_names_or_ids(model, "parameter", by_id=by_id) + + _get_names_or_ids(model, "free_parameter", by_id=by_id) + [ name + "_scale" - for name in _get_names_or_ids(model, "parameter", by_id=by_id) + for name in _get_names_or_ids(model, "free_parameter", by_id=by_id) ] + _get_names_or_ids(model, "observable", by_id=by_id) + [ @@ -502,10 +502,10 @@ def _get_observable_cols(model: AmiciModel, by_id: bool) -> list[str]: model, "fixed_parameter", by_id=by_id ) ] - + _get_names_or_ids(model, "parameter", by_id=by_id) + + _get_names_or_ids(model, "free_parameter", by_id=by_id) + [ name + "_scale" - for name in _get_names_or_ids(model, "parameter", by_id=by_id) + for name in _get_names_or_ids(model, "free_parameter", by_id=by_id) ] + _get_names_or_ids(model, "observable", by_id=by_id) ) @@ -540,10 +540,10 @@ def _get_state_cols(model: AmiciModel, by_id: bool) -> list[str]: model, "fixed_parameter", by_id=by_id ) ] - + _get_names_or_ids(model, "parameter", by_id=by_id) + + _get_names_or_ids(model, "free_parameter", by_id=by_id) + [ name + "_scale" - for name in _get_names_or_ids(model, "parameter", by_id=by_id) + for name in _get_names_or_ids(model, "free_parameter", by_id=by_id) ] + _get_names_or_ids(model, "state", by_id=by_id) ) @@ -577,10 +577,10 @@ def _get_expression_cols(model: AmiciModel, by_id: bool) -> list[str]: model, "fixed_parameter", by_id=by_id ) ] - + _get_names_or_ids(model, "parameter", by_id=by_id) + + _get_names_or_ids(model, "free_parameter", by_id=by_id) + [ name + "_scale" - for name in _get_names_or_ids(model, "parameter", by_id=by_id) + for name in _get_names_or_ids(model, "free_parameter", by_id=by_id) ] + _get_names_or_ids(model, "expression", by_id=by_id) ) @@ -737,7 +737,7 @@ def construct_edata_from_data_frame( # fill in parameters edata.free_parameters = ( - condition[_get_names_or_ids(model, "parameter", by_id=by_id)] + condition[_get_names_or_ids(model, "free_parameter", by_id=by_id)] .astype(float) .values ) @@ -745,7 +745,9 @@ def construct_edata_from_data_frame( edata.pscale = amici.parameter_scaling_from_int_vector( [ amici.ParameterScaling(condition[par + "_scale"].astype(int)) - for par in list(_get_names_or_ids(model, "parameter", by_id=by_id)) + for par in list( + _get_names_or_ids(model, "free_parameter", by_id=by_id) + ) ] ) @@ -838,7 +840,7 @@ def get_edata_from_data_frame( if par + "_presim" in df.columns: condition_parameters.append(par + "_presim") # parameters & scales - for par in _get_names_or_ids(model, "parameter", by_id=by_id): + for par in _get_names_or_ids(model, "free_parameter", by_id=by_id): condition_parameters.append(par) condition_parameters.append(par + "_scale") # presimulation time diff --git a/tests/benchmark_models/test_petab_benchmark.py b/tests/benchmark_models/test_petab_benchmark.py index 8fe457d509..b7804a8c6d 100644 --- a/tests/benchmark_models/test_petab_benchmark.py +++ b/tests/benchmark_models/test_petab_benchmark.py @@ -443,7 +443,7 @@ def test_benchmark_gradient( amici_function, amici_derivative = simulate_petab_to_cached_functions( petab_problem=petab_problem, - parameter_ids=parameter_ids, + free_parameter_ids=parameter_ids, amici_model=amici_model, solver=amici_solver, scaled_parameters=scale, @@ -782,7 +782,7 @@ def test_nominal_parameters_llh_v2(problem_id): parameter_ids = ps._petab_problem.x_free_ids amici_function, amici_derivative = simulate_petab_v2_to_cached_functions( ps, - parameter_ids=parameter_ids, + free_parameter_ids=parameter_ids, cache=False, ) np.random.seed(cur_settings.rng_seed) From bb9614d12d2b2d3c6c55af40d9d4a46804b168a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Fri, 14 Nov 2025 09:22:32 +0000 Subject: [PATCH 18/23] Update test_pregenerated_models.py --- python/tests/test_pregenerated_models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/tests/test_pregenerated_models.py b/python/tests/test_pregenerated_models.py index 54dbcbadbd..95ac8a1724 100755 --- a/python/tests/test_pregenerated_models.py +++ b/python/tests/test_pregenerated_models.py @@ -223,7 +223,7 @@ def test_pregenerated_model_py(sub_test, case): assert np.isnan(rdata.chi2) with pytest.raises(RuntimeError): - model.get_parameter_by_name("thisParameterDoesNotExist") + model.get_free_parameter_by_name("thisParameterDoesNotExist") def verify_simulation_results( From 04c987810958c6831ed6b71fbc99d5f2f72441aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fabian=20Fr=C3=B6hlich?= Date: Fri, 14 Nov 2025 09:26:19 +0000 Subject: [PATCH 19/23] fix pysb tests --- python/tests/test_pysb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/python/tests/test_pysb.py b/python/tests/test_pysb.py index 35784fe4e3..ef43983a6a 100644 --- a/python/tests/test_pysb.py +++ b/python/tests/test_pysb.py @@ -300,7 +300,7 @@ def test_names_and_ids(pysb_example_presimulation_module): "fixed_parameter_names": ("DRUG_0", "KIN_0"), "observable_ids": ("pPROT_obs",), "observable_names": ("pPROT_obs",), - "parameter_ids": ( + "free_parameter_ids": ( "PROT_0", "kon_prot_drug", "koff_prot_drug", @@ -320,7 +320,7 @@ def test_names_and_ids(pysb_example_presimulation_module): } # Names and IDs are the same here expected["expression_names"] = expected["expression_ids"] - expected["parameter_names"] = expected["parameter_ids"] + expected["free_parameter_names"] = expected["free_parameter_ids"] for field_name, cur_expected in expected.items(): actual = getattr(model_pysb, f"get_{field_name}")() From d6924dc3ba9fc72e95fa3016ec18981edfdd3ab2 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Fri, 14 Nov 2025 11:11:57 +0100 Subject: [PATCH 20/23] clang-format --- include/amici/edata.h | 3 ++- include/amici/model.h | 12 ++++++---- include/amici/simulation_parameters.h | 32 +++++++++++++++++--------- include/amici/solver_cvodes.h | 2 +- include/amici/solver_idas.h | 2 +- src/backwardproblem.cpp | 8 +++---- src/forwardproblem.cpp | 12 +++++----- src/hdf5.cpp | 3 ++- src/model.cpp | 33 +++++++++++++++------------ src/simulation_parameters.cpp | 4 ++-- src/sundials_linsol_wrapper.cpp | 8 +++---- src/sundials_matrix_wrapper.cpp | 7 +++--- 12 files changed, 73 insertions(+), 53 deletions(-) diff --git a/include/amici/edata.h b/include/amici/edata.h index 05db142507..9382d12899 100644 --- a/include/amici/edata.h +++ b/include/amici/edata.h @@ -58,7 +58,8 @@ class ExpData : public SimulationParameters { * @param nztrue Number of event outputs * @param nmaxevent Maximal number of events to track * @param ts Timepoints (dimension: nt) - * @param fixed_parameters Model variables excluded from sensitivity analysis (dimension: nk) + * @param fixed_parameters Model variables excluded from sensitivity + * analysis (dimension: nk) */ ExpData( int nytrue, int nztrue, int nmaxevent, std::vector ts, diff --git a/include/amici/model.h b/include/amici/model.h index 12e0b6ad0d..23860ab9a4 100644 --- a/include/amici/model.h +++ b/include/amici/model.h @@ -458,15 +458,17 @@ class Model : public AbstractModel, public ModelDimensions { * @param value Parameter value * @return Number of parameter IDs that matched the regex */ - int - set_free_parameters_by_id_regex(std::string const& par_id_regex, realtype value); + int set_free_parameters_by_id_regex( + std::string const& par_id_regex, realtype value + ); /** * @brief Set value of first model parameter with the specified name. * @param par_name Parameter name * @param value Parameter value */ - void set_free_parameter_by_name(std::string const& par_name, realtype value); + void + set_free_parameter_by_name(std::string const& par_name, realtype value); /** * @brief Set model parameters according to the parameter name and mapped @@ -567,8 +569,8 @@ class Model : public AbstractModel, public ModelDimensions { /** * @brief Report whether the model has free parameter names set. * - * @return Boolean indicating whether freeparameter names were set. Also returns - * `true` if the number of corresponding variables is just zero. + * @return Boolean indicating whether freeparameter names were set. Also + * returns `true` if the number of corresponding variables is just zero. */ virtual bool has_free_parameter_names() const; diff --git a/include/amici/simulation_parameters.h b/include/amici/simulation_parameters.h index 9d10ae005e..01fc4fced4 100644 --- a/include/amici/simulation_parameters.h +++ b/include/amici/simulation_parameters.h @@ -23,16 +23,19 @@ class SimulationParameters { /** * @brief Constructor - * @param fixed_parameters Model parameters excluded from sensitivity analysis + * @param fixed_parameters Model parameters excluded from sensitivity + * analysis * @param free_parameters Model parameters included in sensitivity analysis */ SimulationParameters( - std::vector fixed_parameters, std::vector free_parameters + std::vector fixed_parameters, + std::vector free_parameters ) : fixed_parameters(std::move(fixed_parameters)) , free_parameters(std::move(free_parameters)) - , pscale(std::vector(this->free_parameters.size(), ParameterScaling::none)) { - } + , pscale( + std::vector(this->free_parameters.size(), ParameterScaling::none) + ) {} #ifndef SWIGPYTHON /* @@ -49,33 +52,40 @@ class SimulationParameters { */ /** * @brief Constructor - * @param fixed_parameters Model parameters excluded from sensitivity analysis + * @param fixed_parameters Model parameters excluded from sensitivity + * analysis * @param free_parameters Model parameters included in sensitivity analysis * @param plist Model parameter indices w.r.t. which sensitivities are to be * computed */ SimulationParameters( - std::vector fixed_parameters, std::vector free_parameters, - std::vector plist + std::vector fixed_parameters, + std::vector free_parameters, std::vector plist ) : fixed_parameters(std::move(fixed_parameters)) , free_parameters(std::move(free_parameters)) - , pscale(std::vector(this->free_parameters.size(), ParameterScaling::none)) + , pscale( + std::vector(this->free_parameters.size(), ParameterScaling::none) + ) , plist(std::move(plist)) {} /** * @brief Constructor * @param timepoints Timepoints for which simulation results are requested - * @param fixed_parameters Model parameters excluded from sensitivity analysis + * @param fixed_parameters Model parameters excluded from sensitivity + * analysis * @param free_parameters Model parameters included in sensitivity analysis */ SimulationParameters( - std::vector timepoints, std::vector fixed_parameters, + std::vector timepoints, + std::vector fixed_parameters, std::vector free_parameters ) : fixed_parameters(std::move(fixed_parameters)) , free_parameters(std::move(free_parameters)) - , pscale(std::vector(this->free_parameters.size(), ParameterScaling::none)) + , pscale( + std::vector(this->free_parameters.size(), ParameterScaling::none) + ) , timepoints(std::move(timepoints)) {} #endif diff --git a/include/amici/solver_cvodes.h b/include/amici/solver_cvodes.h index 5216fd3ec3..c6ff6b967c 100644 --- a/include/amici/solver_cvodes.h +++ b/include/amici/solver_cvodes.h @@ -38,7 +38,7 @@ class CVodeSolver : public Solver { */ Solver* clone() const override; - std::string get_class_name() const override {return "CVodeSolver"; }; + std::string get_class_name() const override { return "CVodeSolver"; }; void reinit( realtype t0, AmiVector const& yy0, AmiVector const& yp0 diff --git a/include/amici/solver_idas.h b/include/amici/solver_idas.h index 7b57edac86..d9febe9620 100644 --- a/include/amici/solver_idas.h +++ b/include/amici/solver_idas.h @@ -35,7 +35,7 @@ class IDASolver : public Solver { */ Solver* clone() const override; - std::string get_class_name() const override {return "IDASolver"; }; + std::string get_class_name() const override { return "IDASolver"; }; void reinit_post_process_f(realtype tnext) const override; diff --git a/src/backwardproblem.cpp b/src/backwardproblem.cpp index 9a6f5ada1e..75c32cf915 100644 --- a/src/backwardproblem.cpp +++ b/src/backwardproblem.cpp @@ -201,10 +201,10 @@ void EventHandlingBwdSimulator::handle_event_b( Expects(ws_->nroots_[ie] >= 0); for (int ix = 0; ix < model_->nxtrue_solver; ++ix) { for (int iJ = 0; iJ < model_->nJ; ++iJ) { - ws_->xB_[ix + iJ * model_->nxtrue_solver] += (*dJzdx - )[iJ - + (ix + ws_->nroots_[ie] * model_->nx_solver) - * model_->nJ]; + ws_->xB_[ix + iJ * model_->nxtrue_solver] += (*dJzdx) + [iJ + + (ix + ws_->nroots_[ie] * model_->nx_solver) + * model_->nJ]; } } } diff --git a/src/forwardproblem.cpp b/src/forwardproblem.cpp index 6c384c1942..fd4239adb2 100644 --- a/src/forwardproblem.cpp +++ b/src/forwardproblem.cpp @@ -71,8 +71,7 @@ void EventHandlingSimulator::run( // and filter for timepoints that are within the simulation time range auto trigger_timepoints_tmp = model_->get_trigger_timepoints(); auto trigger_timepoints = std::ranges::views::filter( - trigger_timepoints_tmp, - [this, timepoints](auto t) { + trigger_timepoints_tmp, [this, timepoints](auto t) { return t > ws_->sol.t && !timepoints.empty() && t <= timepoints.at(timepoints.size() - 1); } @@ -883,8 +882,8 @@ SteadyStateStatus SteadyStateProblem::find_steady_state_by_simulation( && (model_->get_steady_state_sensitivity_mode() == SteadyStateSensitivityMode::integrationOnly || model_->get_steady_state_sensitivity_mode() - == SteadyStateSensitivityMode::integrateIfNewtonFails - )) { + == SteadyStateSensitivityMode:: + integrateIfNewtonFails)) { // need FSA to compute sx0 for the pre/main simulation, // or enable ASA for backward integration of pre-equibration new_solver->set_sensitivity_method( @@ -995,8 +994,9 @@ realtype SteadyStateProblem::get_wrms_fsa(WRMSComputer& wrms_computer_sx) { bool SteadyStateProblem::check_steady_state_success() const { // Did one of the attempts yield a steady state? return std::ranges::any_of( - steady_state_status_, [](SteadyStateStatus status - ) { return status == SteadyStateStatus::success; } + steady_state_status_, [](SteadyStateStatus status) { + return status == SteadyStateStatus::success; + } ); } diff --git a/src/hdf5.cpp b/src/hdf5.cpp index 6c00002edc..0c7d2eece1 100644 --- a/src/hdf5.cpp +++ b/src/hdf5.cpp @@ -1518,7 +1518,8 @@ void read_model_data_from_hdf5( } if (location_exists(file, datasetPath + "/theta")) { - model.set_free_parameters(get_double_1d_dataset(file, datasetPath + "/theta") + model.set_free_parameters( + get_double_1d_dataset(file, datasetPath + "/theta") ); } diff --git a/src/model.cpp b/src/model.cpp index af7a5d60e2..f40d7d2987 100644 --- a/src/model.cpp +++ b/src/model.cpp @@ -535,8 +535,8 @@ realtype Model::get_free_parameter_by_id(std::string const& par_id) const { "Could not access parameters by id as they are not set" ); return get_value_by_id( - get_free_parameter_ids(), simulation_parameters_.free_parameters, par_id, - "parameters", "id" + get_free_parameter_ids(), simulation_parameters_.free_parameters, + par_id, "parameters", "id" ); } @@ -546,8 +546,8 @@ realtype Model::get_free_parameter_by_name(std::string const& par_name) const { "Could not access parameters by name as they are not set" ); return get_value_by_id( - get_free_parameter_names(), simulation_parameters_.free_parameters, par_name, - "parameters", "name" + get_free_parameter_names(), simulation_parameters_.free_parameters, + par_name, "parameters", "name" ); } @@ -558,7 +558,9 @@ void Model::set_free_parameters(std::vector const& p) { "match number of model parameters." ); simulation_parameters_.free_parameters = p; - state_.unscaled_parameters.resize(simulation_parameters_.free_parameters.size()); + state_.unscaled_parameters.resize( + simulation_parameters_.free_parameters.size() + ); unscale_parameters( simulation_parameters_.free_parameters, simulation_parameters_.pscale, state_.unscaled_parameters @@ -587,8 +589,8 @@ void Model::set_free_parameter_by_id( ); set_value_by_id( - get_free_parameter_ids(), simulation_parameters_.free_parameters, value, par_id, - "parameter", "id" + get_free_parameter_ids(), simulation_parameters_.free_parameters, value, + par_id, "parameter", "id" ); unscale_parameters( simulation_parameters_.free_parameters, simulation_parameters_.pscale, @@ -623,8 +625,8 @@ void Model::set_free_parameter_by_name( ); set_value_by_id( - get_free_parameter_names(), simulation_parameters_.free_parameters, value, - par_name, "parameter", "name" + get_free_parameter_names(), simulation_parameters_.free_parameters, + value, par_name, "parameter", "name" ); unscale_parameters( simulation_parameters_.free_parameters, simulation_parameters_.pscale, @@ -654,8 +656,8 @@ int Model::set_free_parameters_by_name_regex( ); int n_found = set_value_by_id_regex( - get_free_parameter_names(), simulation_parameters_.free_parameters, value, - par_name_regex, "parameter", "name" + get_free_parameter_names(), simulation_parameters_.free_parameters, + value, par_name_regex, "parameter", "name" ); unscale_parameters( @@ -1696,7 +1698,8 @@ int Model::check_finite( if (has_observable_ids()) row_id += " " + get_observable_ids()[row]; if (has_free_parameter_ids()) - col_id += " " + get_free_parameter_ids()[plist(gsl::narrow(col))]; + col_id + += " " + get_free_parameter_ids()[plist(gsl::narrow(col))]; break; case ModelQuantity::dydx: if (has_observable_ids()) @@ -1708,7 +1711,8 @@ int Model::check_finite( if (has_state_ids()) row_id += " " + get_state_ids_solver()[row]; if (has_free_parameter_ids()) - col_id += " " + get_free_parameter_ids()[plist(gsl::narrow(col))]; + col_id + += " " + get_free_parameter_ids()[plist(gsl::narrow(col))]; break; case ModelQuantity::dJydy: case ModelQuantity::dJydsigma: @@ -1729,7 +1733,8 @@ int Model::check_finite( case ModelQuantity::drzdp: case ModelQuantity::dsigmazdp: if (has_free_parameter_ids()) - col_id += " " + get_free_parameter_ids()[plist(gsl::narrow(col))]; + col_id + += " " + get_free_parameter_ids()[plist(gsl::narrow(col))]; break; case ModelQuantity::dsigmaydy: if (has_observable_ids()) { diff --git a/src/simulation_parameters.cpp b/src/simulation_parameters.cpp index b6b586bead..891b5cb41c 100644 --- a/src/simulation_parameters.cpp +++ b/src/simulation_parameters.cpp @@ -15,8 +15,8 @@ bool operator==(SimulationParameters const& a, SimulationParameters const& b) { a.fixed_parameters_presimulation, b.fixed_parameters_presimulation ) - && is_equal(a.free_parameters, b.free_parameters) && (a.plist == b.plist) - && (a.pscale == b.pscale) + && is_equal(a.free_parameters, b.free_parameters) + && (a.plist == b.plist) && (a.pscale == b.pscale) && (a.reinitialize_fixed_parameter_initial_states == b.reinitialize_fixed_parameter_initial_states) && is_equal(a.sx0, b.sx0) && (a.t_presim == b.t_presim) diff --git a/src/sundials_linsol_wrapper.cpp b/src/sundials_linsol_wrapper.cpp index 089cecc746..3bcee37578 100644 --- a/src/sundials_linsol_wrapper.cpp +++ b/src/sundials_linsol_wrapper.cpp @@ -34,8 +34,8 @@ SUNLinSolWrapper::SUNLinSolWrapper(SUNLinSolWrapper&& other) noexcept { std::swap(A_, other.A_); } -SUNLinSolWrapper& SUNLinSolWrapper::operator=(SUNLinSolWrapper&& other -) noexcept { +SUNLinSolWrapper& +SUNLinSolWrapper::operator=(SUNLinSolWrapper&& other) noexcept { std::swap(solver_, other.solver_); std::swap(A_, other.A_); return *this; @@ -88,8 +88,8 @@ SUNNonLinSolWrapper::SUNNonLinSolWrapper(SUNNonLinSolWrapper&& other) noexcept { std::swap(solver, other.solver); } -SUNNonLinSolWrapper& SUNNonLinSolWrapper::operator=(SUNNonLinSolWrapper&& other -) noexcept { +SUNNonLinSolWrapper& +SUNNonLinSolWrapper::operator=(SUNNonLinSolWrapper&& other) noexcept { std::swap(solver, other.solver); return *this; } diff --git a/src/sundials_matrix_wrapper.cpp b/src/sundials_matrix_wrapper.cpp index a532f57e8f..0913b7407a 100644 --- a/src/sundials_matrix_wrapper.cpp +++ b/src/sundials_matrix_wrapper.cpp @@ -465,8 +465,8 @@ void SUNMatrixWrapper::sparse_add( } set_indexptr(num_indexptrs(), nnz); if (capacity() == A.num_nonzeros() + B.num_nonzeros()) - realloc( - ); // resize if necessary, will have correct size in future calls + // resize if necessary, will have correct size in future calls + realloc(); } void SUNMatrixWrapper::sparse_sum(std::vector const& mats) { @@ -522,7 +522,8 @@ void SUNMatrixWrapper::sparse_sum(std::vector const& mats) { } set_indexptr(num_indexptrs(), nnz); if (capacity() == max_total_nonzero) - realloc(); // resize if necessary + // resize if necessary + realloc(); } sunindextype SUNMatrixWrapper::scatter( From b789ef5f8ab849382fd0f429eaf7420c9d041001 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Fri, 14 Nov 2025 11:19:26 +0100 Subject: [PATCH 21/23] changelog --- CHANGELOG.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32f9a9f9a0..b9e7c1c3b7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,20 @@ See also our [versioning policy](https://amici.readthedocs.io/en/latest/versioni **BREAKING CHANGES** +* The package has been reorganized. All importers have been moved to + `amici.importers` subpackages. For example, all functionality from + `amici.sbml_import` is now available in `amici.importers.sbml`. +* The naming of free and fixed parameters has been harmonized across the API: + AMICI differentiates between parameters with respect to which a model + can compute sensitivities ("free parameters") and parameters with respect to + which no sensitivities can be computed ("fixed parameters"). + "Free" and "fixed" are to be understood in the context of parameter + estimation, where free parameters are optimized, + while fixed parameters remain constant. + Free parameters were previously referred to as just "parameters", and + fixed parameters as "fixed parameters", "constant parameters", + or "constants". This has now been harmonized to "free" and "fixed" across the + API. E.g., `Model.setParameters()` is now `Model.set_free_parameters()`. * `ReturnDataView.posteq_numsteps` and `ReturnDataView.posteq_numsteps` now return a one-dimensional array of shape `(num_timepoints,)` instead of a two-dimensional array of shape `(1, num_timepoints)`. From e831f3728f2a823baccc0422ee130e282780d22d Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Fri, 14 Nov 2025 11:29:13 +0100 Subject: [PATCH 22/23] numpy --- python/sdist/amici/numpy.py | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/python/sdist/amici/numpy.py b/python/sdist/amici/numpy.py index af16d0b128..d6799c7294 100644 --- a/python/sdist/amici/numpy.py +++ b/python/sdist/amici/numpy.py @@ -90,7 +90,7 @@ def __getattr__(self, name: str) -> xr.DataArray: case "sy" | "ssigmay": coords = { "time": self._svp.ts, - "parameter": [ + "free_parameter": [ self._svp.parameter_ids[i] for i in self._svp.plist ], "observable": list(self._svp.observable_ids), @@ -102,39 +102,43 @@ def __getattr__(self, name: str) -> xr.DataArray: } case "sx0": coords = { - "parameter": [ - self._svp.parameter_ids[i] for i in self._svp.plist + "free_parameter": [ + self._svp.free_parameter_ids[i] + for i in self._svp.plist ], "state": list(self._svp.state_ids), } case "sx": coords = { "time": self._svp.ts, - "parameter": [ + "free_parameter": [ self._svp.parameter_ids[i] for i in self._svp.plist ], "state": list(self._svp.state_ids), } - dims = ("time", "parameter", "state") + dims = ("time", "free_parameter", "state_variable") case "sllh": coords = { - "parameter": [ - self._svp.parameter_ids[i] for i in self._svp.plist + "free_parameter": [ + self._svp.free_parameter_ids[i] + for i in self._svp.plist ] } case "FIM": coords = { - "parameter1": [ - self._svp.parameter_ids[i] for i in self._svp.plist + "free_parameter_1": [ + self._svp.free_parameter_ids[i] + for i in self._svp.plist ], - "parameter2": [ - self._svp.parameter_ids[i] for i in self._svp.plist + "free_parameter_2": [ + self._svp.free_parameter_ids[i] + for i in self._svp.plist ], } case "J": coords = { - "state1": list(self._svp.state_ids_solver), - "state2": list(self._svp.state_ids_solver), + "state_variable_1": list(self._svp.state_ids_solver), + "state_variable_2": list(self._svp.state_ids_solver), } case _: dims = tuple(f"dim_{i}" for i in range(data.ndim)) @@ -596,7 +600,7 @@ def _entity_type_from_id( ("state", "x"), ("observable", "y"), ("expression", "w"), - ("parameter", "p"), + ("free_parameter", "p"), ("fixed_parameter", "k"), ): if model: From df0b1b877552ccd2cc8f62da5575c269f979d794 Mon Sep 17 00:00:00 2001 From: Daniel Weindl Date: Fri, 14 Nov 2025 11:34:46 +0100 Subject: [PATCH 23/23] Apply suggestions from code review --- include/amici/model.h | 2 +- python/sdist/amici/constants.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/amici/model.h b/include/amici/model.h index 23860ab9a4..fe15c1066e 100644 --- a/include/amici/model.h +++ b/include/amici/model.h @@ -569,7 +569,7 @@ class Model : public AbstractModel, public ModelDimensions { /** * @brief Report whether the model has free parameter names set. * - * @return Boolean indicating whether freeparameter names were set. Also + * @return Boolean indicating whether free parameter names were set. Also * returns `true` if the number of corresponding variables is just zero. */ virtual bool has_free_parameter_names() const; diff --git a/python/sdist/amici/constants.py b/python/sdist/amici/constants.py index fdd7e59aee..1ee46111c4 100644 --- a/python/sdist/amici/constants.py +++ b/python/sdist/amici/constants.py @@ -23,7 +23,7 @@ class SymbolId(str, enum.Enum): SPECIES = "species" ALGEBRAIC_STATE = "algebraic_state" ALGEBRAIC_EQUATION = "algebraic_equation" - FREE_PARAMETER = "parameter" + FREE_PARAMETER = "free_parameter" FIXED_PARAMETER = "fixed_parameter" OBSERVABLE = "observable" EXPRESSION = "expression"