@@ -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
32853337def _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