Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SbmlModel.get_free_parameter_ids_with_values to handle InitialA… #248

Merged
merged 2 commits into from
Mar 6, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Fix SbmlModel.get_free_parameter_ids_with_values to handle InitialA…
…ssignments

So far, `SbmlModel.get_free_parameter_ids_with_values` ignored InitialAssignments,
resulting in incorrect parameter values in the parameter mapping.
  • Loading branch information
dweindl committed Mar 5, 2024
commit 15d210a1dc72ab68de9eca2df501c9f4787e9cca
26 changes: 25 additions & 1 deletion petab/models/sbml_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import Iterable, Optional, Tuple

import libsbml
import sympy as sp

from ..sbml import (
get_sbml_model,
Expand Down Expand Up @@ -103,8 +104,31 @@ def get_free_parameter_ids_with_values(
ar.getVariable() for ar in self.sbml_model.getListOfRules()
}

parser_settings = libsbml.L3ParserSettings(
self.sbml_model,
libsbml.L3P_PARSE_LOG_AS_LOG10,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is pretty unintuitive, to me it looks like this will convert log to log10, and I'm not sure if the libsbml docs make sense. e.g. this for L3P_PARSE_LOG_AS_ERROR

Collapse unary minuses where possible when parsing text-string formulas.

https://synonym.caltech.edu/software/libsbml/5.18.0/docs/formatted/python-api/namespacelibsbml.html#a9ef0398726fb45bd1cb24c4a5ed671f0

The docstring for L3P_PARSE_LOG_AS_LOG10 looks like it actually parses log as log, not parsing log as log10, but I'm not sure I trust the docs given the docstring for L3P_PARSE_LOG_AS_ERROR. Should we instead use L3P_PARSE_LOG_AS_LN?

I think most users would expect log to be ln, and that log10 is only when explicitly specified with log(10, x) or log10(x).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Those are the libsbml default settings. The only relevant thing here is ignoring units.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, if it actually keeps log as log, not log10, then no problem

Copy link
Member Author

@dweindl dweindl Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this is about parsing MathML, not any observableFormula or the like. In MathML log without explicit base means log10. In plain text formulae, log will be interpreted as ln.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! Good to know that log means different things in PEtab and the model 😬 Then I think we could be more careful about a math spec in the next version of PEtab, I added a comment to the draft timecourse spec.

libsbml.L3P_EXPAND_UNARY_MINUS,
libsbml.L3P_NO_UNITS,
libsbml.L3P_AVOGADRO_IS_CSYMBOL,
libsbml.L3P_COMPARE_BUILTINS_CASE_INSENSITIVE,
None,
libsbml.L3P_MODULO_IS_PIECEWISE,
)

def get_initial(p):
# return the initial assignment value if there is one, and it is a
# number, otherwise the parameter value
if ia := self.sbml_model.getInitialAssignmentBySymbol(p.getId()):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if ia := self.sbml_model.getInitialAssignmentBySymbol(p.getId()):
if ia := self.sbml_model.getInitialAssignmentBySymbol(p.getId()) is not None:

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's implied.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 was just a PEP 8 recommendation

sym_expr = sp.sympify(
libsbml.formulaToL3StringWithSettings(
ia.getMath(), parser_settings
)
)
return float(sym_expr) if sym_expr.is_Number else p.getValue()
return p.getValue()

return (
(p.getId(), p.getValue())
(p.getId(), get_initial(p))
for p in self.sbml_model.getListOfParameters()
if p.getId() not in rule_targets
)
Expand Down
Loading