FAQs
Why do I get the error Any[...] are either missing from the variable map or missing from the system's states/parameters list
?
This error probably occurs because the model has an SBML assignment rule. Assignment rules describe the assignment of an equation to a variable:
var = assignment # var ~ assignment in ModelingToolkit syntax
To be able to simulate the model assignment rules must be inlined into the model equations. This can be done with the structural_simplify
function from ModelingToolkit. For example, for an ODE model do:
using SBMLImporter, ModelingToolkit
prn, cb = load_SBML(path)
sys = structural_simplify(convert(ODESystem, prn.rn))
oprob = ODEProblem(sys, prn.u0, tspan, prn.p)
How can I check if my model follows mass action kinetics?
For efficient jump simulations (Gillespie type), the model should ideally follow chemical mass action kinetics. To inform the importer about mass action kinetics simply set the keyword argument massaction=true
in load_SBML
. Now, if you are unsure whether the model follows mass action kinetics, simply provide massaction=true
. If the model does not adhere to mass action kinetics, a warning is thrown:
Warning: That the system is massaction was provided, however, the reaction r is not massaction. It is parsed as non massaction reaction, which can negatively impact simulation times
The massaction
keyword argument is only relevant for jump simulations. If you import the model as a SDEProblem
or an ODEProblem
, you can (and should) ignore this keyword argument.
Why does one of the SBML model parameters not appear among the system parameters?
If one of the model parameters does not appear among the system parameters:
prn, cb = load_SBML(path)
parameters(prn)
but appears in the model variables:
unknowns(prn)
this is likely because the parameter is not set as constant in the SBML file, e.g.:
<parameter id="c" value="1.0" constant="false"/>
If a parameter is set to have constant="false"
, the importer must treat the parameter as a variable since it can change over time (explicitly depend on time), as Julia ReactionSystem
parameters are assumed to time invariant. If the parameter should indeed be constant (e.g. at most be changed by an event), change the parameter in the model file:
<parameter id="c" value="1.0" constant="true"/>
How do I access SBML reaction ID and reaction name?
SBML reactions have both an ID
and a name
that can differ. When importing an SBML model, SBMLImporter stores these as metadata
in every Catalyst.Reaction
. This metadata
can be accessed with the Catalyst getmetadata
function. For example, to retrieve both the ID and name for the first reaction in a model, do:
using SBMLImporter, Catalyst
prn, cb = load_SBML(path_SBML)
sbml_reactions = reactions(prn.rn)
getmetadata(sbml_reactions[1], :id)
getmetadata(sbml_reactions[1], :name)
How do I get the compartment of an SBML specie?
Every SBML specie
has a compartment
. SBMLImporter stores the compartment as Catalyst.Species
metadata, which can be accessed via the getcompartment
function. For more details, see the API.
Why does my simulation fail with DomainError
while the model imports fine?
This typically happens due to two reasons. Firstly, the model might contain a function call where the argument must be positive, such as:
log(specie)
Even though the model might be written such that specie
should never go below 0 (e.g., the model follows mass action kinetics), numerical errors can cause specie
to go below zero. Therefore, instead of encoding risky statements into the model such as log(specie)
, it might be better to encode something like log(specie + 1e-8)
.
Secondly DomainError
might arise due to how SBMLImporter parses SBML piecewise expressions. Piecewise expressions are first parsed into ifelse
functions:
ifelse(condition, x, y)
Which when condition == true
evaluates to x
, otherwise to y
. In SBMLImporter ifelse
expressions are further rewritten to callbacks (events). Hence, in the model equations the ifelse
is converted to:
(1 - condition_bool) * x + condition_bool * y
Here condition_bool
is assigned via a callback (event) to be 1
when condition
is true
, and to 0
when condition
if false
. This has the same functionality as an ifelse
, but is numerically more stable because the integrator (e.g., ODE solver) actually stops at points condition
changes. Instead, with ifelse
, the integrator does not know an event happens and thus must typically reduce its step size to handle the sudden change in models dynamics. This increases simulation time, and reduces simulation stability (e.g. ODE solvers fail more frequently). However, sometimes the formulas in the ifelse
might depend on the condition
. For example, let's say we have:
ifelse(t > 1, 0, log(t - 1))
With the ifelse
formulation, log(t - 1)
is never evaluated until t > 1
. With the callback formulation:
(1 - condition_bool) * 0 + condition_bool * log(t-1)
log(t-1)
is evaluated for time-points t < 1
which causes DomainError
. This can be solved by simply not rewriting ifelse
to callback when importing the model:
prn, cb = load_SBML(path; ifelse_to_callback = false)
If neither of the above solutions work, please file an issue on GitHub.
Why did I get the SBMLSupport
error?
You likely got this error because your SBML model contains an SBML feature that SBMLImporter does not support yet. An extensive list of supported features can be found here. If SBMLImporter lacks support for a feature you would like to have, please file an issue on GitHub.
Do you support SBML export?
We currently do not support exporting Catalyst ReactionSystem
to SBML. Most things are available in Julia for supporting SBML export though, so if anyone is interested, we would be happy to provide guidance for creating a SBMLExporter package.