Skip to content

Commit 18ebab7

Browse files
authored
Merge pull request #161 from SciML/pl/fix_high_stoichiometries
omit conversion to mass action for stoichiometries > 100 to avoid StackOverflow in simplify_fractions
2 parents 0a74b5d + c909d5a commit 18ebab7

File tree

4 files changed

+32
-14
lines changed

4 files changed

+32
-14
lines changed

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SBMLToolkit"
22
uuid = "86080e66-c8ac-44c2-a1a0-9adaadfe4a4e"
33
authors = ["paulflang", "anandijain"]
4-
version = "0.1.25"
4+
version = "0.1.26"
55

66
[deps]
77
Catalyst = "479239e8-5488-4da2-87a7-35f2df7eef83"

README.md

+27-12
Original file line numberDiff line numberDiff line change
@@ -27,28 +27,43 @@ Pkg.add("SBMLToolkit")
2727
SBML models can be simulated with the following steps (note that `sol` is in absolute quantities rather than concentrations):
2828

2929
```julia
30-
using SBMLToolkit, ModelingToolkit, OrdinaryDiffEq
30+
using SBMLToolkit, OrdinaryDiffEq
3131

32-
SBMLToolkit.checksupport_file("my_model.xml")
33-
mdl = readSBML("my_model.xml", doc -> begin
34-
set_level_and_version(3, 2)(doc)
35-
convert_promotelocals_expandfuns(doc)
36-
end)
37-
38-
rs = ReactionSystem(mdl) # If you want to create a reaction system
39-
odesys = convert(ODESystem, rs) # Alternatively: ODESystem(mdl)
32+
odesys = readSBML("my_model.xml", ODESystemImporter())
4033

4134
tspan = (0.0, 1.0)
4235
prob = ODEProblem(odesys, [], tspan, [])
4336
sol = solve(prob, Tsit5())
4437
```
4538

46-
Alternatively, SBMLToolkit also provides more concise methods to import `SBML.Models`, `Catalyst.ReactionSystems`, and `ModelingToolkit.ODESystems`.
39+
While this imports an `ODESystem` directly, you can also import a Catalyst.jl `ReactionSystem`:
4740

4841
```julia
49-
mdl = readSBML("my_model.xml", DefaultImporter())
42+
using SBMLToolkit
43+
5044
rs = readSBML("my_model.xml", ReactionSystemImporter())
51-
odesys = readSBML("my_model.xml", ODESystemImporter())
45+
```
46+
47+
One common case where this is useful is if you want to run stochastic instead of ODE simulations.
48+
49+
In the very unlikely case that you need fine-grained control over the SBML import, you can create an SBML.jl `Model` (we strongly recommend manually running `SBMLToolkit.checksupport_file("my_model.xml")` before)
50+
51+
```julia
52+
using SBML
53+
54+
mdl = readSBML("my_model.xml", doc -> begin
55+
set_level_and_version(3, 2)(doc)
56+
convert_promotelocals_expandfuns(doc)
57+
end)
58+
```
59+
60+
The conversion to SBML level 3 version 2 is necessary, because older versions are not well supported in SBMLToolkit. `convert_promotelocals_expandfuns` basically flattens the SBML before the import. Once you have obtained the `Model`, you can convert it to a `ReactionSystem` and `ODESystem`.
61+
62+
```julia
63+
using SBMLToolkit
64+
65+
rs = ReactionSystem(mdl)
66+
odesys = convert(ODESystem, rs)
5267
```
5368

5469
## License

src/reactions.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ function get_reagents(reactant_references::Vector{SBML.SpeciesReference},
8989
sn = rr.species
9090
stoich = rr.stoichiometry
9191
if isnothing(stoich)
92-
@warn "Stoichiometries of SpeciesReferences are not defined. Setting to 1." maxlog=1
92+
@warn "SBML SpeciesReferences does not contain stoichiometries. Assuming stoichiometry of 1." maxlog=1
9393
stoich = 1.0
9494
end
9595
iszero(stoich) && @error("Stoichiometry of $sn must be non-zero")
@@ -183,6 +183,8 @@ function get_massaction(kl::Num, reactants::Union{Vector{Num}, Nothing},
183183
rate_const = kl
184184
elseif isnothing(reactants) | isnothing(stoich)
185185
throw(ErrorException("`reactants` and `stoich` are inconsistent: `reactants` are $(reactants) and `stoich` is $(stoich)."))
186+
elseif max(stoich...) > 100 # simplify_fractions might StackOverflow
187+
rate_const = kl
186188
else
187189
rate_const = SymbolicUtils.simplify_fractions(kl / *((.^(reactants, stoich))...))
188190
end

test/reactions.jl

+1
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ m = SBML.Model(species = Dict("s" => s), reactions = Dict("r1" => r))
135135
@test isequal(SBMLToolkit.get_massaction(k1 + c1, nothing, nothing), k1 + c1) # Case zero order kineticLaw
136136
@test isnan(SBMLToolkit.get_massaction(k1 * s1 * s2 / (c1 + s2), [s1], [1])) # Case Michaelis-Menten kinetics
137137
@test isnan(SBMLToolkit.get_massaction(k1 * s1 * IV, [s1], [1])) # Case kineticLaw with time
138+
@test isnan(SBMLToolkit.get_massaction(k1 * s1, [s1], [101])) # Case no simplification performed due to large rstoich
138139

139140
@test isnan(SBMLToolkit.get_massaction(k1 * s1 * s2, [s1], [1]))
140141
@test isnan(SBMLToolkit.get_massaction(k1 + c1, [s1], [1]))

0 commit comments

Comments
 (0)