Skip to content

Commit bd0c99e

Browse files
committed
add test for accuracy
1 parent 6edd64f commit bd0c99e

File tree

3 files changed

+120
-7
lines changed

3 files changed

+120
-7
lines changed

src/systems/reaction/reactionsystem.jl

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ function Reaction(rate, subs, prods; kwargs...)
9292
Reaction(rate, subs, prods, sstoich, pstoich; kwargs...)
9393
end
9494

95+
function namespace_equation(rx::Reaction, name, iv)
96+
Reaction(namespace_expr(rx.rate, name, iv),
97+
namespace_expr(rx.substrates, name, iv),
98+
namespace_expr(rx.products, name, iv),
99+
rx.substoich, rx.prodstoich,
100+
[namespace_expr(n[1],name,iv) => n[2] for n in rx.netstoich], rx.only_use_rate)
101+
end
102+
95103
# calculates the net stoichiometry of a reaction as a vector of pairs (sub,substoich)
96104
function get_netstoich(subs, prods, sstoich, pstoich)
97105
# stoichiometry as a Dictionary
@@ -134,7 +142,7 @@ struct ReactionSystem <: AbstractSystem
134142
"""The name of the system"""
135143
name::Symbol
136144
"""systems: The internal systems"""
137-
systems::Vector{ReactionSystem}
145+
systems::Vector
138146

139147
function ReactionSystem(eqs, iv, states, ps, observed, name, systems)
140148
new(eqs, value(iv), value.(states), value.(ps), observed, name, systems)
@@ -143,13 +151,31 @@ end
143151

144152
function ReactionSystem(eqs, iv, species, params;
145153
observed = [],
146-
systems = ReactionSystem[],
154+
systems = [],
147155
name = gensym(:ReactionSystem))
148156

149-
isempty(species) && error("ReactionSystems require at least one species.")
157+
#isempty(species) && error("ReactionSystems require at least one species.")
150158
ReactionSystem(eqs, iv, species, params, observed, name, systems)
151159
end
152160

161+
function ReactionSystem(iv; kwargs...)
162+
ReactionSystem(Reaction[], iv, [], []; kwargs...)
163+
end
164+
165+
function equations(sys::ModelingToolkit.ReactionSystem)
166+
eqs = get_eqs(sys)
167+
systems = get_systems(sys)
168+
if isempty(systems)
169+
return eqs
170+
else
171+
eqs = [eqs;
172+
reduce(vcat,
173+
namespace_equations.(get_systems(sys));
174+
init=[])]
175+
return eqs
176+
end
177+
end
178+
153179
"""
154180
oderatelaw(rx; combinatoric_ratelaw=true)
155181
@@ -191,7 +217,7 @@ function assemble_oderhs(rs; combinatoric_ratelaws=true)
191217
species_to_idx = Dict((x => i for (i,x) in enumerate(sts)))
192218
rhsvec = Any[0 for i in eachindex(sts)]
193219

194-
for rx in equations(rs)
220+
for rx in get_eqs(rs)
195221
rl = oderatelaw(rx; combinatoric_ratelaw=combinatoric_ratelaws)
196222
for (spec,stoich) in rx.netstoich
197223
i = species_to_idx[spec]
@@ -212,9 +238,9 @@ function assemble_drift(rs; combinatoric_ratelaws=true, as_odes=true)
212238
rhsvec = assemble_oderhs(rs; combinatoric_ratelaws=combinatoric_ratelaws)
213239
if as_odes
214240
D = Differential(get_iv(rs))
215-
eqs = [Equation(D(x),rhs) for (x,rhs) in zip(get_states(rs),rhsvec)]
241+
eqs = [Equation(D(x),rhs) for (x,rhs) in zip(get_states(rs),rhsvec) if (!_iszero(rhs))]
216242
else
217-
eqs = [Equation(0,rhs) for rhs in rhsvec]
243+
eqs = [Equation(0,rhs) for rhs in rhsvec if (!_iszero(rhs))]
218244
end
219245
eqs
220246
end
@@ -381,7 +407,7 @@ ignored.
381407
function Base.convert(::Type{<:ODESystem}, rs::ReactionSystem;
382408
name=nameof(rs), combinatoric_ratelaws=true, kwargs...)
383409
eqs = assemble_drift(rs; combinatoric_ratelaws=combinatoric_ratelaws)
384-
systems = convert.(ODESystem, get_systems(rs))
410+
systems = map(sys -> (sys isa ODESystem) ? sys : convert(ODESystem, sys), get_systems(rs))
385411
ODESystem(eqs, get_iv(rs), get_states(rs), get_ps(rs), name=name, systems=systems)
386412
end
387413

test/reactionsystem_components.jl

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using ModelingToolkit, LinearAlgebra, OrdinaryDiffEq, Test
2+
MT = ModelingToolkit
3+
4+
# Repressilator model
5+
@parameters t α₀ α K n δ β μ
6+
@variables m(t) P(t) R(t)
7+
rxs = [Reaction(α₀, nothing, [m]),
8+
Reaction/ (1 + (R/K)^n), nothing, [m]),
9+
Reaction(δ, [m], nothing),
10+
Reaction(β, [m], [m,P]),
11+
Reaction(μ, [P], nothing)
12+
]
13+
14+
specs = [m,P,R]
15+
pars = [α₀,α,K,n,δ,β,μ]
16+
@named rs = ReactionSystem(rxs, t, specs, pars)
17+
18+
# using ODESystem components
19+
@named os₁ = convert(ODESystem, rs)
20+
@named os₂ = convert(ODESystem, rs)
21+
@named os₃ = convert(ODESystem, rs)
22+
connections = [os₁.R ~ os₃.P,
23+
os₂.R ~ os₁.P,
24+
os₃.R ~ os₂.P]
25+
@named connected = ODESystem(connections, t, [], [], systems=[os₁,os₂,os₃])
26+
oderepressilator = structural_simplify(connected)
27+
28+
pvals = [os₁.α₀ => 5e-4,
29+
os₁.α => .5,
30+
os₁.K => 40.0,
31+
os₁.n => 2,
32+
os₁.δ => (log(2)/120),
33+
os₁.β => (20*log(2)/120),
34+
os₁.μ => (log(2)/600),
35+
os₂.α₀ => 5e-4,
36+
os₂.α => .5,
37+
os₂.K => 40.0,
38+
os₂.n => 2,
39+
os₂.δ => (log(2)/120),
40+
os₂.β => (20*log(2)/120),
41+
os₂.μ => (log(2)/600),
42+
os₃.α₀ => 5e-4,
43+
os₃.α => .5,
44+
os₃.K => 40.0,
45+
os₃.n => 2,
46+
os₃.δ => (log(2)/120),
47+
os₃.β => (20*log(2)/120),
48+
os₃.μ => (log(2)/600)]
49+
u₀ = [os₁.m => 0.0, os₁.P => 20.0, os₂.m => 0.0, os₂.P => 0.0, os₃.m => 0.0, os₃.P => 0.0]
50+
tspan = (0.0, 100000.0)
51+
oprob = ODEProblem(oderepressilator, u₀, tspan, pvals)
52+
sol = solve(oprob, Tsit5())
53+
54+
# hardcoded network
55+
function repress!(f, y, p, t)
56+
α = p.α; α₀ = p.α₀; β = p.β; δ = p.δ; μ = p.μ; K = p.K; n = p.n
57+
f[1] = α / (1 + (y[6] / K)^n) - δ * y[1] + α₀
58+
f[2] = α / (1 + (y[4] / K)^n) - δ * y[2] + α₀
59+
f[3] = α / (1 + (y[5] / K)^n) - δ * y[3] + α₀
60+
f[4] = β * y[1] - μ * y[4]
61+
f[5] = β * y[2] - μ * y[5]
62+
f[6] = β * y[3] - μ * y[6]
63+
nothing
64+
end
65+
ps = (α₀=5e-4, α=.5, K=40.0, n=2, δ=(log(2)/120), β=(20*log(2)/120), μ=(log(2)/600))
66+
u0 = [0.0,0.0,0.0,20.0,0.0,0.0]
67+
oprob2 = ODEProblem(repress!, u0, tspan, ps)
68+
sol2 = solve(oprob2, Tsit5())
69+
tvs = 0:1:tspan[end]
70+
71+
indexof(sym,syms) = findfirst(isequal(sym),syms)
72+
i = indexof(os₁.P, states(oderepressilator))
73+
@test all(isapprox(u[1],u[2],atol=1e-4) for u in zip(sol(tvs, idxs=2), sol2(tvs, idxs=4)))
74+
75+
# using ReactionSystem components
76+
77+
# @named rs₁ = ReactionSystem(rxs, t, specs, pars)
78+
# @named rs₂ = ReactionSystem(rxs, t, specs, pars)
79+
# @named rs₃ = ReactionSystem(rxs, t, specs, pars)
80+
# connections = [rs₁.R ~ rs₃.P,
81+
# rs₂.R ~ rs₁.P,
82+
# rs₃.R ~ rs₂.P]
83+
# @named csys = ODESystem(connections, t, [], [])
84+
# @named repressilator = ReactionSystem(t; systems=[csys,rs₁,rs₂,rs₃])
85+
# @named oderepressilator2 = convert(ODESystem, repressilator)
86+
# sys2 = structural_simplify(oderepressilator2) # FAILS currently

test/runtests.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ using SafeTestsets, Test
1515
@safetestset "NonlinearSystem Test" begin include("nonlinearsystem.jl") end
1616
@safetestset "OptimizationSystem Test" begin include("optimizationsystem.jl") end
1717
@safetestset "ReactionSystem Test" begin include("reactionsystem.jl") end
18+
@safetestset "ReactionSystem Test" begin include("reactionsystem_components.jl") end
1819
@safetestset "JumpSystem Test" begin include("jumpsystem.jl") end
1920
@safetestset "ControlSystem Test" begin include("controlsystem.jl") end
2021
@safetestset "Domain Test" begin include("domains.jl") end

0 commit comments

Comments
 (0)