Skip to content

Commit 20b07e9

Browse files
authored
Move symbolic model and utils to amici._symbolic (#3058)
Closes #3040.
1 parent 5b6d241 commit 20b07e9

File tree

17 files changed

+97
-85
lines changed

17 files changed

+97
-85
lines changed

.github/workflows/test_sbml_semantic_test_suite.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ on:
88
paths:
99
- .github/workflows/test_sbml_semantic_test_suite.yml
1010
- python/sdist/amici/exporters/sundials/de_export.py
11-
- python/sdist/amici/de_model_components.py
12-
- python/sdist/amici/de_model.py
11+
- python/sdist/amici/_symbolic/**
1312
- python/sdist/amici/importers/sbml/**
1413
- python/sdist/amici/importers/utils.py
1514
- scripts/run-SBMLTestsuite.sh

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ swig/python/build/*
77
tests/cpp/build/*
88
tests/cpp/build_xcode/*
99
tests/cpp/Testing/*
10+
.cache/
1011

1112
doc-venv/*
1213
fonts/*

doc/python_modules.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ AMICI Python API
2929
amici.importers.petab.v1.simulator
3030
amici.jax
3131
amici.exporters.sundials.de_export
32-
amici.de_model
33-
amici.de_model_components
3432
amici.plotting
3533
amici.pandas
3634
amici.logging
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""
2+
Private functionality for symbolic model generation and manipulation.
3+
4+
This module provides tools to create, modify, and analyze symbolic
5+
representations of differential equation models used in AMICI.
6+
Most symbolic functionality is provided by `SymPy <https://www.sympy.org/>`_.
7+
"""
8+
9+
from .de_model import * # noqa: F403
10+
from .de_model_components import * # noqa: F403
11+
from .sympy_utils import * # noqa: F403
12+
13+
__all__ = de_model.__all__ + de_model_components.__all__ + sympy_utils.__all__
Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,22 @@
1616
import sympy as sp
1717
from sympy import ImmutableDenseMatrix, MutableDenseMatrix
1818

19+
from amici.exporters.sundials.cxx_functions import (
20+
nobody_functions,
21+
sensi_functions,
22+
sparse_functions,
23+
var_in_function_signature,
24+
)
25+
from amici.exporters.sundials.cxxcodeprinter import csc_matrix
26+
from amici.importers.utils import (
27+
ObservableTransformation,
28+
_default_simplify,
29+
amici_time_symbol,
30+
toposort_symbols,
31+
unique_preserve_order,
32+
)
33+
from amici.logging import get_logger, log_execution_time, set_log_level
34+
1935
from .de_model_components import (
2036
AlgebraicEquation,
2137
AlgebraicState,
@@ -39,21 +55,6 @@
3955
SigmaZ,
4056
State,
4157
)
42-
from .exporters.sundials.cxx_functions import (
43-
nobody_functions,
44-
sensi_functions,
45-
sparse_functions,
46-
var_in_function_signature,
47-
)
48-
from .exporters.sundials.cxxcodeprinter import csc_matrix
49-
from .importers.utils import (
50-
ObservableTransformation,
51-
_default_simplify,
52-
amici_time_symbol,
53-
toposort_symbols,
54-
unique_preserve_order,
55-
)
56-
from .logging import get_logger, log_execution_time, set_log_level
5758
from .sympy_utils import (
5859
_parallel_applyfunc,
5960
smart_is_zero_matrix,

python/sdist/amici/de_model_components.py renamed to python/sdist/amici/_symbolic/de_model_components.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66

77
import sympy as sp
88

9-
from .constants import SymbolId
10-
from .importers.utils import (
9+
from amici.constants import SymbolId
10+
from amici.importers.utils import (
1111
RESERVED_SYMBOLS,
1212
ObservableTransformation,
1313
amici_time_symbol,

python/sdist/amici/sympy_utils.py renamed to python/sdist/amici/_symbolic/sympy_utils.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,19 @@
1010

1111
import sympy as sp
1212

13-
from .logging import get_logger, log_execution_time
13+
from amici.logging import get_logger, log_execution_time
1414

1515
logger = get_logger(__name__, logging.ERROR)
1616

17+
__all__ = [
18+
"smart_jacobian",
19+
"smart_multiply",
20+
"smart_is_zero_matrix",
21+
"_monkeypatch_sympy",
22+
"_parallel_applyfunc",
23+
"_piecewise_to_minmax",
24+
]
25+
1726

1827
def _custom_pow_eval_derivative(self, s):
1928
"""

python/sdist/amici/exporters/sundials/de_export.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,15 @@
2424

2525
import sympy as sp
2626

27+
from amici._symbolic import *
28+
2729
from ... import (
2830
__commit__,
2931
__version__,
3032
get_model_dir,
3133
)
32-
from ...de_model import DEModel
33-
from ...de_model_components import *
3434
from ...importers.sbml import splines
3535
from ...logging import get_logger, log_execution_time, set_log_level
36-
from ...sympy_utils import (
37-
_custom_pow_eval_derivative,
38-
_monkeypatched,
39-
smart_is_zero_matrix,
40-
)
4136
from ..template import apply_template
4237
from .compile import build_model_extension
4338
from .cxx_functions import (
@@ -236,16 +231,14 @@ def __init__(
236231
self.generate_sensitivity_code: bool = generate_sensitivity_code
237232
self.hybridisation = hybridization
238233

234+
@_monkeypatch_sympy
239235
@log_execution_time("generating cpp code", logger)
240236
def generate_model_code(self) -> None:
241237
"""
242238
Generates the model code (Python package + C++ extension).
243239
"""
244-
with _monkeypatched(
245-
sp.Pow, "_eval_derivative", _custom_pow_eval_derivative
246-
):
247-
self._prepare_model_folder()
248-
self._generate_c_code()
240+
self._prepare_model_folder()
241+
self._generate_c_code()
249242

250243
@log_execution_time("compiling cpp code", logger)
251244
def compile_model(self) -> None:

python/sdist/amici/importers/petab/_petab_importer.py

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
import amici
2424
from amici import SensitivityOrder, get_model_dir
25-
from amici.de_model import DEModel
25+
from amici._symbolic import DEModel, Event
2626
from amici.importers.utils import MeasurementChannel, amici_time_symbol
2727
from amici.logging import get_logger
2828

@@ -32,8 +32,6 @@
3232
if TYPE_CHECKING:
3333
import pysb
3434

35-
import amici.de_model_components
36-
3735
__all__ = [
3836
"PetabImporter",
3937
"ExperimentManager",
@@ -1926,7 +1924,7 @@ def __init__(self, petab_problem: v2.Problem):
19261924
)
19271925
#: The PEtab problem to convert. Not modified by this class.
19281926
self._petab_problem = petab_problem
1929-
self._events: list[amici.de_model_components.Event] = []
1927+
self._events: list[Event] = []
19301928
self._new_problem: v2.Problem | None = None
19311929

19321930
@staticmethod
@@ -1936,7 +1934,7 @@ def _get_experiment_indicator_condition_id(experiment_id: str) -> str:
19361934

19371935
def convert(
19381936
self,
1939-
) -> tuple[v2.Problem, list[amici.de_model_components.Event]]:
1937+
) -> tuple[v2.Problem, list[Event]]:
19401938
"""Convert PEtab experiments to amici events and pysb initials.
19411939
19421940
Generate events, add Initials, or convert Parameters to Expressions
@@ -1952,7 +1950,7 @@ def convert(
19521950
to be passed to `pysb2amici`.
19531951
"""
19541952
self._new_problem = copy.deepcopy(self._petab_problem)
1955-
self._events: list[amici.de_model_components.Event] = []
1953+
self._events: list[Event] = []
19561954

19571955
self._add_preequilibration_indicator()
19581956

@@ -2177,7 +2175,7 @@ def _create_period_start_event(
21772175
else:
21782176
raise AssertionError(change)
21792177

2180-
event = amici.de_model_components.Event(
2178+
event = Event(
21812179
identifier=sp.Symbol(event_id),
21822180
name=event_id,
21832181
value=root_fun,

python/sdist/amici/importers/pysb/__init__.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@
2323
import sympy as sp
2424

2525
import amici
26-
from amici.de_model import DEModel
27-
from amici.de_model_components import (
26+
from amici._symbolic.de_model import DEModel
27+
from amici._symbolic.de_model_components import (
2828
DifferentialState,
2929
Event,
3030
Expression,
@@ -486,7 +486,7 @@ def get_cached_index(symbol, sarray, index_cache):
486486
dflux_dw = sp.ImmutableSparseMatrix(n_r, n_w, dflux_dw_dict)
487487
dflux_dp = sp.ImmutableSparseMatrix(n_r, n_p, dflux_dp_dict)
488488

489-
# use dok format to convert numeric csc to sparse symbolic
489+
# use dok format to convert numeric csc to sparse _symbolic
490490
S = sp.ImmutableSparseMatrix(
491491
n_x,
492492
n_r, # don't use shape here as we are eliminating rows
@@ -649,7 +649,7 @@ def _add_expression(
649649
name of the expression
650650
651651
:param expr:
652-
symbolic expression that the symbol refers to
652+
_symbolic expression that the symbol refers to
653653
654654
:param pysb_model:
655655
see :py:func:`_process_pysb_expressions`
@@ -681,10 +681,10 @@ def _add_expression(
681681

682682
y = sp.Symbol(name)
683683
trafo = noise_distribution_to_observable_transformation(noise_dist)
684-
# note that this is a bit iffy since we are potentially using the same symbolic identifier in expressions (w)
684+
# note that this is a bit iffy since we are potentially using the same _symbolic identifier in expressions (w)
685685
# and observables (y). This is not a problem as there currently are no model functions that use both. If this
686686
# changes, I would expect symbol redefinition warnings in CPP models and overwriting in JAX models, but as both
687-
# symbols refer to the same symbolic entity, this should not be a problem (untested)
687+
# symbols refer to the same _symbolic entity, this should not be a problem (untested)
688688
obs = Observable(
689689
y, name, _parse_special_functions(expr), transformation=trafo
690690
)
@@ -723,7 +723,7 @@ def _get_sigma(
723723
pysb_model: pysb.Model, obs_name: str, sigma_name: str | None
724724
) -> sp.Symbol:
725725
"""
726-
Tries to extract standard deviation symbolic identifier and formula
726+
Tries to extract standard deviation _symbolic identifier and formula
727727
for a given observable name from the pysb model and if no specification is
728728
available sets default values
729729
@@ -738,7 +738,7 @@ def _get_sigma(
738738
sigma or ``None``.
739739
740740
:return:
741-
symbolic variable representing the standard deviation of the observable
741+
_symbolic variable representing the standard deviation of the observable
742742
"""
743743
if sigma_name is None:
744744
return sp.Symbol(f"sigma_{obs_name}")
@@ -933,7 +933,7 @@ def _compute_possible_indices(
933933
)
934934
# TODO: implement this, multiply species by the volume of
935935
# their respective compartment and allow total_cl to depend
936-
# on parameters + constants and update the respective symbolic
936+
# on parameters + constants and update the respective _symbolic
937937
# derivative accordingly
938938

939939
prototype = dict()
@@ -1161,7 +1161,7 @@ def _is_in_cycle(
11611161
def _greedy_target_index_update(cl_prototypes: CL_Prototype) -> None:
11621162
"""
11631163
Computes unique target indices for conservation laws from possible
1164-
indices such that expected fill in in symbolic derivatives is minimized
1164+
indices such that expected fill in in _symbolic derivatives is minimized
11651165
11661166
:param cl_prototypes:
11671167
dict that contains possible indices and non-unique target indices

0 commit comments

Comments
 (0)