Skip to content

Commit b67f5f7

Browse files
dweindlFFroehlich
andauthored
Update docstrings and annotations for sympy observables/sigmas (#2683)
Update docstrings and annotations for sympy observables/sigmas. Related to #2568. Co-authored-by: Fabian Fröhlich <fabian.frohlich@crick.ac.uk>
1 parent e588a9f commit b67f5f7

File tree

1 file changed

+76
-24
lines changed

1 file changed

+76
-24
lines changed

python/sdist/amici/sbml_import.py

Lines changed: 76 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -267,11 +267,11 @@ def sbml2amici(
267267
self,
268268
model_name: str,
269269
output_dir: str | Path = None,
270-
observables: dict[str, dict[str, str]] = None,
271-
event_observables: dict[str, dict[str, str]] = None,
270+
observables: dict[str, dict[str, str | sp.Expr]] = None,
271+
event_observables: dict[str, dict[str, str | sp.Expr]] = None,
272272
constant_parameters: Iterable[str] = None,
273-
sigmas: dict[str, str | float] = None,
274-
event_sigmas: dict[str, str | float] = None,
273+
sigmas: dict[str, str | float | sp.Expr] = None,
274+
event_sigmas: dict[str, str | float | sp.Expr] = None,
275275
noise_distributions: dict[str, str | Callable] = None,
276276
event_noise_distributions: dict[str, str | Callable] = None,
277277
verbose: int | bool = logging.ERROR,
@@ -296,11 +296,33 @@ def sbml2amici(
296296
297297
Note that this generates model ODEs for changes in concentrations, not
298298
amounts unless the `hasOnlySubstanceUnits` attribute has been
299-
defined for a particular species.
299+
defined in the SBML model for a particular species.
300300
301301
Sensitivity analysis for local parameters is enabled by creating
302302
global parameters ``_{reactionId}_{localParameterName}``.
303303
304+
.. note::
305+
306+
When providing expressions for (event) observables and their sigmas
307+
as strings (see below), those will be passed to
308+
:func:`sympy.sympify`. The supported grammar is not well defined.
309+
Note there can be issues with, for example, ``==`` or n-ary (n>2)
310+
comparison operators.
311+
Also note that operator precedence and function names may differ
312+
from SBML L3 formulas or PEtab math expressions.
313+
Passing a sympy expression directly will
314+
be the safer option for more complex expressions.
315+
316+
.. note::
317+
318+
When passing sympy expressions, all Symbols therein must have the
319+
``real=True`` assumption.
320+
321+
.. note::
322+
323+
In any math expressions passed to this function, ``time`` will
324+
be interpreted as the time symbol.
325+
304326
:param model_name:
305327
Name of the generated model package.
306328
Note that in a given Python session, only one model with a given
@@ -313,23 +335,53 @@ def sbml2amici(
313335
314336
:param observables:
315337
Observables to be added to the model:
316-
``dictionary( observableId:{'name':observableName
317-
(optional), 'formula':formulaString)})``.
338+
339+
.. code-block::
340+
341+
dict(
342+
observableId: {
343+
'name': observableName, # optional
344+
'formula': formulaString or sympy expression,
345+
}
346+
)
347+
348+
If the observation function is passed as a string,
349+
it will be passed to :func:`sympy.sympify` (see note above).
318350
319351
:param event_observables:
320352
Event observables to be added to the model:
321-
``dictionary( eventObservableId:{'name':eventObservableName
322-
(optional), 'event':eventId, 'formula':formulaString)})``
353+
354+
.. code-block::
355+
356+
dict(
357+
eventObservableId: {
358+
'name': eventObservableName, # optional
359+
'event':eventId,
360+
'formula': formulaString or sympy expression,
361+
}
362+
)
363+
364+
If the formula is passed as a string, it will be passed to
365+
:func:`sympy.sympify` (see note above).
323366
324367
:param constant_parameters:
325368
list of SBML Ids identifying constant parameters
326369
327370
:param sigmas:
328-
dictionary(observableId: sigma value or (existing) parameter name)
371+
Expression for the scale parameter of the noise distribution for
372+
each observable. This can be a numeric value, a sympy expression,
373+
or an expression string that will be passed to
374+
:func:`sympy.sympify`.
375+
376+
``{observableId: sigma}``
329377
330378
:param event_sigmas:
331-
dictionary(eventObservableId: sigma value or (existing) parameter
332-
name)
379+
Expression for the scale parameter of the noise distribution for
380+
each observable. This can be a numeric value, a sympy expression,
381+
or an expression string that will be passed to
382+
:func:`sympy.sympify`.
383+
384+
``{eventObservableId: sigma}``
333385
334386
:param noise_distributions:
335387
dictionary(observableId: noise type).
@@ -348,8 +400,8 @@ def sbml2amici(
348400
:func:`amici.import_utils.noise_distribution_to_cost_function`.
349401
350402
:param verbose:
351-
verbosity level for logging, ``True``/``False`` default to
352-
``logging.Error``/``logging.DEBUG``
403+
Verbosity level for logging, ``True``/``False`` defaults to
404+
``logging.Error``/``logging.DEBUG``.
353405
354406
:param assume_pow_positivity:
355407
if set to ``True``, a special pow function is
@@ -361,7 +413,7 @@ def sbml2amici(
361413
extension, e.g. ``/usr/bin/clang``.
362414
363415
:param allow_reinit_fixpar_initcond:
364-
see :class:`amici.de_export.ODEExporter`
416+
See :class:`amici.de_export.DEExporter`.
365417
366418
:param compile:
367419
If ``True``, compile the generated Python package,
@@ -385,10 +437,10 @@ def sbml2amici(
385437
case of stoichiometric coefficients with many significant digits.
386438
387439
:param simplify:
388-
see :attr:`amici.DEModel._simplify`
440+
See :attr:`amici.DEModel._simplify`.
389441
390442
:param cache_simplify:
391-
see :meth:`amici.DEModel.__init__`
443+
See :meth:`amici.DEModel.__init__`.
392444
393445
:param log_as_log10:
394446
If ``True``, log in the SBML model will be parsed as ``log10``
@@ -402,7 +454,7 @@ def sbml2amici(
402454
:param hardcode_symbols:
403455
List of SBML entity IDs that are to be hardcoded in the generated model.
404456
Their values cannot be changed anymore after model import.
405-
Currently only parameters that are not targets of rules or
457+
Currently, only parameters that are not targets of rules or
406458
initial assignments are supported.
407459
"""
408460
set_log_level(logger, verbose)
@@ -1929,8 +1981,8 @@ def try_solve_t(expr: sp.Expr) -> list:
19291981
@log_execution_time("processing SBML observables", logger)
19301982
def _process_observables(
19311983
self,
1932-
observables: dict[str, dict[str, str]] | None,
1933-
sigmas: dict[str, str | float],
1984+
observables: dict[str, dict[str, str | sp.Expr]] | None,
1985+
sigmas: dict[str, str | float | sp.Expr],
19341986
noise_distributions: dict[str, str],
19351987
) -> None:
19361988
"""
@@ -2031,8 +2083,8 @@ def _process_observables(
20312083
@log_execution_time("processing SBML event observables", logger)
20322084
def _process_event_observables(
20332085
self,
2034-
event_observables: dict[str, dict[str, str]],
2035-
event_sigmas: dict[str, str | float],
2086+
event_observables: dict[str, dict[str, str | sp.Expr]],
2087+
event_sigmas: dict[str, str | float | sp.Float],
20362088
event_noise_distributions: dict[str, str],
20372089
) -> None:
20382090
"""
@@ -3283,8 +3335,8 @@ def _parse_special_functions_sbml(
32833335

32843336

32853337
def _validate_observables(
3286-
observables: dict[str, dict[str, str]] | None,
3287-
sigmas: dict[str, str | float],
3338+
observables: dict[str, dict[str, str | sp.Expr]] | None,
3339+
sigmas: dict[str, str | float | sp.Expr],
32883340
noise_distributions: dict[str, str],
32893341
events: bool = False,
32903342
) -> None:

0 commit comments

Comments
 (0)