Skip to content

Commit

Permalink
Add debugging helper get_model_for_preeq (#2250)
Browse files Browse the repository at this point in the history
* Add debugging helper get_model_for_preeq

Makes life easier when debugging preequilibration issues.

* tol
  • Loading branch information
dweindl authored Jan 2, 2024
1 parent e836bda commit 7a9abbd
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
45 changes: 45 additions & 0 deletions python/sdist/amici/debugging/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""Functions for debugging AMICI simulation failures."""
import amici
import numpy as np


def get_model_for_preeq(model: amici.Model, edata: amici.ExpData):
"""Get a model set-up to simulate the preequilibration condition as
specified in `edata`.
Useful for analyzing simulation errors during preequilibration.
Simulating the returned model will reproduce the behavior of
simulation-based preequilibration.
Note that for models with events, the simulation results may differ.
During preequilibration, event-handling is disabled. However, when
simulating the returned model, event-handling will be enabled.
For events triggered at fixed timepoints, this can be avoided by setting
:meth:`t0 <amici.Model.setT0>` to a timepoints after the last trigger
timepoint.
:param model:
The model for which *edata* was generated.
:param edata:
The experimental data object with a preequilibration condition
specified.
:return:
A copy of *model* with the same parameters, initial states, ...
as *amici_model* for the preequilibration condition.
Output timepoints are set to ``[inf]`` and will have to be adjusted.
"""
model = model.clone()
model.setTimepoints([np.inf])
model.setFixedParameters(edata.fixedParametersPreequilibration)
if edata.pscale:
model.setParameterScale(edata.pscale)
if edata.parameters:
model.setParameters(edata.parameters)
if edata.plist:
model.setParameterList(edata.plist)
model.setInitialStates(edata.x0)
# has to be set *after* parameter list/scale!
model.setInitialStateSensitivities(edata.sx0)
model.setT0(edata.tstart_)

return model
31 changes: 30 additions & 1 deletion python/tests/test_preequilibration.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
import amici
import numpy as np
import pytest
from numpy.testing import assert_allclose
from amici.debugging import get_model_for_preeq
from numpy.testing import assert_allclose, assert_equal
from test_pysb import get_data


Expand Down Expand Up @@ -633,3 +634,31 @@ def test_simulation_errors(preeq_fixture):
assert rdata._swigptr.messages[2].identifier == "OTHER"
assert rdata._swigptr.messages[3].severity == amici.LogSeverity_debug
assert rdata._swigptr.messages[3].identifier == "BACKTRACE"


def test_get_model_for_preeq(preeq_fixture):
(
model,
solver,
edata,
edata_preeq,
edata_presim,
edata_sim,
pscales,
plists,
) = preeq_fixture
model.setSteadyStateSensitivityMode(
amici.SteadyStateSensitivityMode.integrationOnly
)
model_preeq = get_model_for_preeq(model, edata)
# the exactly same settings are used, so results should match exactly
rdata1 = amici.runAmiciSimulation(model_preeq, solver)
rdata2 = amici.runAmiciSimulation(model, solver, edata_preeq)
assert_equal(
rdata1.x,
rdata2.x,
)
assert_equal(
rdata1.sx,
rdata2.sx,
)

0 comments on commit 7a9abbd

Please sign in to comment.