Skip to content

Commit 76c91e9

Browse files
authored
Merge pull request #130 from SciML/pl/fix_map_symbolics_ident
return correct variable type/metadata in map_symbolics_ident
2 parents 903ec91 + 8baab5f commit 76c91e9

17 files changed

+290
-208
lines changed

Project.toml

+2-2
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.23"
4+
version = "0.1.24"
55

66
[deps]
77
Catalyst = "479239e8-5488-4da2-87a7-35f2df7eef83"
@@ -12,7 +12,7 @@ SymbolicUtils = "d1185830-fcd6-423d-90d6-eec64667417b"
1212
[compat]
1313
Catalyst = "13"
1414
MathML = "0.1"
15-
SBML = "1.4"
15+
SBML = "1.4.4"
1616
SymbolicUtils = "1"
1717
julia = "1.6"
1818

README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ using SBMLToolkit, ModelingToolkit, OrdinaryDiffEq
3131

3232
SBMLToolkit.checksupport_file("my_model.xml")
3333
mdl = readSBML("my_model.xml", doc -> begin
34-
set_level_and_version(3, 2)(doc)
35-
convert_promotelocals_expandfuns(doc)
36-
end)
34+
set_level_and_version(3, 2)(doc)
35+
convert_promotelocals_expandfuns(doc)
36+
end)
3737

3838
rs = ReactionSystem(mdl) # If you want to create a reaction system
3939
odesys = convert(ODESystem, rs) # Alternatively: ODESystem(mdl)

docs/make.jl

+22-22
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,27 @@ cp("./docs/Project.toml", "./docs/src/assets/Project.toml", force = true)
77
DocMeta.setdocmeta!(SBMLToolkit, :DocTestSetup, :(using SBMLToolkit); recursive = true)
88

99
makedocs(;
10-
modules = [SBMLToolkit],
11-
authors = "paulflang, anandijain",
12-
sitename = "SBMLToolkit.jl",
13-
format = Documenter.HTML(;
14-
prettyurls = get(ENV, "CI", "false") == "true",
15-
canonical = "https://docs.sciml.ai/SBMLToolkit/stable/",
16-
assets = ["assets/favicon.ico"]),
17-
clean = true, doctest = false, linkcheck = true,
18-
linkcheck_ignore = ["https://www.linkedin.com/in/paul-lang-7b54a81a3/"],
19-
strict = [
20-
:doctest,
21-
:linkcheck,
22-
:parse_error,
23-
:example_block,
24-
# Other available options are
25-
# :autodocs_block, :cross_references, :docs_block, :eval_block, :example_block, :footnote, :meta_block, :missing_docs, :setup_block
26-
],
27-
pages = [
28-
"Home" => "index.md",
29-
"API documentation" => "api.md",
30-
])
10+
modules = [SBMLToolkit],
11+
authors = "paulflang, anandijain",
12+
sitename = "SBMLToolkit.jl",
13+
format = Documenter.HTML(;
14+
prettyurls = get(ENV, "CI", "false") == "true",
15+
canonical = "https://docs.sciml.ai/SBMLToolkit/stable/",
16+
assets = ["assets/favicon.ico"]),
17+
clean = true, doctest = false, linkcheck = true,
18+
linkcheck_ignore = ["https://www.linkedin.com/in/paul-lang-7b54a81a3/"],
19+
strict = [
20+
:doctest,
21+
:linkcheck,
22+
:parse_error,
23+
:example_block,
24+
# Other available options are
25+
# :autodocs_block, :cross_references, :docs_block, :eval_block, :example_block, :footnote, :meta_block, :missing_docs, :setup_block
26+
],
27+
pages = [
28+
"Home" => "index.md",
29+
"API documentation" => "api.md",
30+
])
3131

3232
deploydocs(;
33-
repo = "github.com/SciML/SBMLToolkit.jl")
33+
repo = "github.com/SciML/SBMLToolkit.jl")

docs/src/index.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ using SBMLToolkit, ModelingToolkit, OrdinaryDiffEq
4242

4343
SBMLToolkit.checksupport_file("my_model.xml")
4444
mdl = readSBML("my_model.xml", doc -> begin
45-
set_level_and_version(3, 2)(doc)
46-
convert_promotelocals_expandfuns(doc)
47-
end)
45+
set_level_and_version(3, 2)(doc)
46+
convert_promotelocals_expandfuns(doc)
47+
end)
4848
rs = ReactionSystem(mdl) # If you want to create a reaction system
4949
odesys = convert(ODESystem, rs) # Alternatively: ODESystem(mdl)
5050

src/SBMLToolkit.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ include("utils.jl")
1515

1616
export ReactionSystem, ODESystem
1717
export readSBML, readSBMLFromString, set_level_and_version, convert_simplify_math,
18-
convert_promotelocals_expandfuns
18+
convert_promotelocals_expandfuns
1919
export DefaultImporter, ReactionSystemImporter, ODESystemImporter
2020

2121
end

src/events.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ function get_events(model) # Todo: implement up or downpass and parameters
77
mtk_evs = Pair{Vector{Equation}, Vector{Equation}}[]
88
for (_, e) in evs
99
trigger = SBML.extensive_kinetic_math(model, e.trigger.math)
10-
trigger = Symbolics.unwrap(interpret_as_num(trigger))
10+
trigger = Symbolics.unwrap(interpret_as_num(trigger, model))
1111
lhs, rhs = map(x -> substitute(x, subsdict), trigger.arguments)
1212
trig = [lhs ~ rhs]
1313
mtk_evas = Equation[]
@@ -20,8 +20,8 @@ function get_events(model) # Todo: implement up or downpass and parameters
2020
end
2121
end
2222
var = create_var(eva.variable, IV; irreducible = true)
23-
math = substitute(Symbolics.unwrap(interpret_as_num(math)),
24-
subsdict)
23+
math = substitute(Symbolics.unwrap(interpret_as_num(math, model)),
24+
subsdict)
2525
effect = var ~ math
2626
push!(mtk_evas, effect)
2727
end

src/reactions.jl

+15-15
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,17 @@ function get_reactions(model::SBML.Model)
66
rxs = Reaction[]
77
for reaction in values(model.reactions)
88
extensive_math = SBML.extensive_kinetic_math(model, reaction.kinetic_math)
9-
symbolic_math = interpret_as_num(extensive_math)
9+
symbolic_math = interpret_as_num(extensive_math, model)
1010
reactant_references = reaction.reactants
1111
product_references = reaction.products
1212
if reaction.reversible
1313
symbolic_math = get_unidirectional_components(symbolic_math)
1414
kl_fw, kl_rv = [substitute(x, subsdict) for x in symbolic_math]
1515
enforce_rate = isequal(kl_rv, 0)
1616
add_reaction!(rxs, kl_fw, reactant_references, product_references, model;
17-
enforce_rate = enforce_rate)
17+
enforce_rate = enforce_rate)
1818
add_reaction!(rxs, kl_rv, product_references, reactant_references, model;
19-
enforce_rate = enforce_rate)
19+
enforce_rate = enforce_rate)
2020
else
2121
kl = substitute(symbolic_math, subsdict) # Todo: use SUBSDICT
2222
add_reaction!(rxs, kl, reactant_references, product_references, model)
@@ -53,21 +53,21 @@ function get_unidirectional_components(bidirectional_math)
5353
end
5454

5555
function add_reaction!(rxs::Vector{Reaction},
56-
kl::Num,
57-
reactant_references::Vector{SBML.SpeciesReference},
58-
product_references::Vector{SBML.SpeciesReference},
59-
model::SBML.Model;
60-
enforce_rate = false)
56+
kl::Num,
57+
reactant_references::Vector{SBML.SpeciesReference},
58+
product_references::Vector{SBML.SpeciesReference},
59+
model::SBML.Model;
60+
enforce_rate = false)
6161
reactants, products, rstoichvals, pstoichvals = get_reagents(reactant_references,
62-
product_references, model)
62+
product_references, model)
6363
isnothing(reactants) && isnothing(products) && return
6464
rstoichvals = stoich_convert_to_ints(rstoichvals)
6565
pstoichvals = stoich_convert_to_ints(pstoichvals)
6666
kl, our = use_rate(kl, reactants, rstoichvals)
6767
our = enforce_rate ? true : our
6868
push!(rxs,
69-
Catalyst.Reaction(kl, reactants, products, rstoichvals, pstoichvals;
70-
only_use_rate = our))
69+
Catalyst.Reaction(kl, reactants, products, rstoichvals, pstoichvals;
70+
only_use_rate = our))
7171
end
7272

7373
function stoich_convert_to_ints(xs)
@@ -78,8 +78,8 @@ end
7878
Get reagents
7979
"""
8080
function get_reagents(reactant_references::Vector{SBML.SpeciesReference},
81-
product_references::Vector{SBML.SpeciesReference},
82-
model::SBML.Model)
81+
product_references::Vector{SBML.SpeciesReference},
82+
model::SBML.Model)
8383
reactants = String[]
8484
products = String[]
8585
rstoich = Float64[]
@@ -146,7 +146,7 @@ end
146146
Get kineticLaw for use in MTK.Reaction
147147
"""
148148
function use_rate(kl::Num, react::Union{Vector{Num}, Nothing},
149-
stoich::Union{Vector{<:Real}, Nothing})
149+
stoich::Union{Vector{<:Real}, Nothing})
150150
rate_const = get_massaction(kl, react, stoich)
151151
if !isnan(rate_const)
152152
kl = rate_const
@@ -161,7 +161,7 @@ end
161161
Get rate constant of mass action kineticLaws
162162
"""
163163
function get_massaction(kl::Num, reactants::Union{Vector{Num}, Nothing},
164-
stoich::Union{Vector{<:Real}, Nothing})
164+
stoich::Union{Vector{<:Real}, Nothing})
165165
function check_args(x::SymbolicUtils.BasicSymbolic{Real})
166166
check_args(Val(SymbolicUtils.istree(x)), x)
167167
end

src/rules.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ function get_rules(model)
55
raterules = Equation[]
66
for r in model.rules
77
if r isa SBML.AlgebraicRule
8-
push!(algeqs, 0 ~ interpret_as_num(r.math))
8+
push!(algeqs, 0 ~ interpret_as_num(r.math, model))
99
elseif r isa SBML.AssignmentRule
1010
var, ass = get_var_and_assignment(model, r)
1111
push!(obseqs, var ~ ass)
@@ -17,7 +17,7 @@ function get_rules(model)
1717
end
1818
end
1919
algeqs, obseqs, raterules = map(x -> substitute(x, subsdict),
20-
(algeqs, obseqs, raterules))
20+
(algeqs, obseqs, raterules))
2121
algeqs, obseqs, raterules
2222
end
2323

@@ -31,7 +31,7 @@ function get_var_and_assignment(model, rule)
3131
if !isnothing(vc)
3232
math = SBML.MathApply("*", [SBML.MathIdent(vc), math])
3333
end
34-
assignment = interpret_as_num(math)
34+
assignment = interpret_as_num(math, model)
3535
if rule isa SBML.RateRule && haskey(model.species, rule.variable)
3636
sp = model.species[rule.variable]
3737
comp = model.compartments[sp.compartment]
@@ -52,6 +52,6 @@ function get_volume_correction(model, s_id)
5252
isnothing(comp.size) && !SBML.seemsdefined(sp.compartment, model) &&
5353
comp.spatial_dimensions != 0 && # remove this line when SBML test suite is fixed
5454
throw(DomainError(sp.compartment,
55-
"compartment size is insufficiently defined"))
55+
"compartment size is insufficiently defined"))
5656
sp.compartment
5757
end

src/systems.jl

+27-23
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ Create a `ModelingToolkit.ODESystem` from an SBML file, using default import set
3838
See also [`Model`](@ref) and [`ODESystemImporter`](@ref).
3939
"""
4040
function SBML.readSBML(sbmlfile::String, ::ODESystemImporter;
41-
include_zero_odes::Bool = true, kwargs...) # Returns an MTK.ODESystem
41+
include_zero_odes::Bool = true, kwargs...) # Returns an MTK.ODESystem
4242
convert(ODESystem, readSBML(sbmlfile, ReactionSystemImporter(), kwargs...),
43-
include_zero_odes = include_zero_odes)
43+
include_zero_odes = include_zero_odes)
4444
end
4545

4646
"""
@@ -54,7 +54,11 @@ function Catalyst.ReactionSystem(model::SBML.Model; kwargs...) # Todo: requires
5454
# length(model.events) > 0 ? error("Model contains events. Please import with `ODESystem(model)`") : nothing @Anand: how to suppress this when called from ODESystem
5555
rxs = get_reactions(model)
5656
u0map, parammap = get_mappings(model)
57-
defs = ModelingToolkit._merge(Dict(u0map), Dict(parammap))
57+
defs = Dict{Num, Any}()
58+
for (k, v) in vcat(u0map, parammap)
59+
defs[k] = v
60+
end
61+
# defs = ModelingToolkit._merge(Dict(u0map), Dict(parammap))
5862
algrules, obsrules, raterules = get_rules(model)
5963
obsrules_rearranged = Equation[]
6064
for o in obsrules
@@ -64,9 +68,9 @@ function Catalyst.ReactionSystem(model::SBML.Model; kwargs...) # Todo: requires
6468
rhs = r.rhs
6569
end
6670
end
67-
defs[o.lhs] = substitute(rhs,
68-
ModelingToolkit._merge(defs,
69-
Dict(Catalyst.DEFAULT_IV.val => 0)))
71+
defs[o.lhs] = ModelingToolkit.fixpoint_sub(rhs, defs)
72+
# ModelingToolkit._merge(defs,
73+
# Dict(Catalyst.DEFAULT_IV.val => 0)))
7074
push!(obsrules_rearranged, 0 ~ rhs - o.lhs)
7175
end
7276
raterules_subs = []
@@ -77,20 +81,20 @@ function Catalyst.ReactionSystem(model::SBML.Model; kwargs...) # Todo: requires
7781
rhs = r.rhs
7882
end
7983
end
80-
defs[o.lhs] = substitute(rhs,
81-
ModelingToolkit._merge(defs,
82-
Dict(Catalyst.DEFAULT_IV.val => 0)))
84+
defs[o.lhs] = ModelingToolkit.fixpoint_sub(rhs, defs)
85+
# ModelingToolkit._merge(defs,
86+
# Dict(Catalyst.DEFAULT_IV.val => 0)))
8387
push!(raterules_subs, rhs ~ o.lhs)
8488
end
8589
if haskey(kwargs, :defaults)
8690
defs = ModelingToolkit._merge(defs, kwargs[:defaults])
8791
kwargs = filter(x -> !isequal(first(x), :defaults), kwargs)
8892
end
8993
ReactionSystem([rxs..., algrules..., raterules_subs..., obsrules_rearranged...],
90-
IV, first.(u0map), first.(parammap);
91-
defaults = defs, name = gensym(:SBML),
92-
continuous_events = get_events(model),
93-
combinatoric_ratelaws = false, kwargs...)
94+
IV, first.(u0map), first.(parammap);
95+
defaults = defs, name = gensym(:SBML),
96+
continuous_events = get_events(model),
97+
combinatoric_ratelaws = false, kwargs...)
9498
end
9599

96100
"""
@@ -101,7 +105,7 @@ Create an `ODESystem` from an `SBML.Model`.
101105
See also [`ReactionSystem`](@ref).
102106
"""
103107
function ModelingToolkit.ODESystem(model::SBML.Model; include_zero_odes::Bool = true,
104-
kwargs...)
108+
kwargs...)
105109
rs = ReactionSystem(model; kwargs...)
106110
convert(ODESystem, rs; include_zero_odes = include_zero_odes)
107111
end
@@ -116,12 +120,12 @@ function get_mappings(model::SBML.Model)
116120
push!(parammap, var => inits[k])
117121
else
118122
var = create_var(k, IV;
119-
isbcspecies = has_rule_type(k, model, SBML.RateRule) ||
120-
has_rule_type(k, model, SBML.AssignmentRule) ||
121-
(has_rule_type(k, model, SBML.AlgebraicRule) &&
122-
(all([netstoich(k, r) == 0
123-
for r in values(model.reactions)]) ||
124-
v.boundary_condition == true))) # To remove species that are otherwise defined
123+
isbcspecies = has_rule_type(k, model, SBML.RateRule) ||
124+
has_rule_type(k, model, SBML.AssignmentRule) ||
125+
(has_rule_type(k, model, SBML.AlgebraicRule) &&
126+
(all([netstoich(k, r) == 0
127+
for r in values(model.reactions)]) ||
128+
v.boundary_condition == true))) # To remove species that are otherwise defined
125129
push!(u0map, var => inits[k])
126130
end
127131
end
@@ -133,7 +137,7 @@ function get_mappings(model::SBML.Model)
133137
elseif v.constant == true && isnothing(v.value) # Todo: maybe add this branch also to model.compartments
134138
var = create_param(k)
135139
val = model.initial_assignments[k]
136-
push!(parammap, var => interpret_as_num(val))
140+
push!(parammap, var => interpret_as_num(val, model))
137141
else
138142
var = create_param(k)
139143
push!(parammap, var => v.value)
@@ -154,9 +158,9 @@ end
154158
function netstoich(id, reaction)
155159
netstoich = 0
156160
rdict = Dict(getproperty.(reaction.reactants, :species) .=>
157-
getproperty.(reaction.reactants, :stoichiometry))
161+
getproperty.(reaction.reactants, :stoichiometry))
158162
pdict = Dict(getproperty.(reaction.products, :species) .=>
159-
getproperty.(reaction.products, :stoichiometry))
163+
getproperty.(reaction.products, :stoichiometry))
160164
netstoich -= get(rdict, id, 0)
161165
netstoich += get(pdict, id, 0)
162166
end

0 commit comments

Comments
 (0)