Skip to content

Commit 68c22c1

Browse files
committed
update with new completeness handling
1 parent f4deb3a commit 68c22c1

File tree

9 files changed

+88
-106
lines changed

9 files changed

+88
-106
lines changed

docs/src/catalyst_functionality/compositional_modeling.md

Lines changed: 10 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,12 @@ identically repressed genes, and how to use compositional modeling to create
66
compartments.
77

88
## A note on *completeness*
9-
Catalyst `ReactionSystem` can either be *complete* or *incomplete*. *By default they are created as complete*. Here, only complete `ReactionSystem`s can be used to create the various problem types (e.g. `ODEProblem`). However, only incomplete `ReactionSystem`s can be composed using the features described below. Hence, for compositional modeling, `ReactionSystem` must be created as incomplete, and later set to complete before simulation.
9+
Catalyst `ReactionSystem` can either be *complete* or *incomplete*. When created using the `@reaction_network` DSL they are *created as complete*. Here, only complete `ReactionSystem`s can be used to create the various problem types (e.g. `ODEProblem`). However, only incomplete `ReactionSystem`s can be composed using the features described below. Hence, for compositional modeling, `ReactionSystem` must be created as incomplete, and later set to complete before simulation.
1010

11-
To set a `ReactionSystem` created via the DSL as complete, use the `@incomplete` option:
11+
To create incomplete `ReactionSystem`s using the DSL as complete, use the `@network_component` instead of `@reaction_network`:
1212
```@example ex0
1313
using Catalyst
14-
degradation_component = @reaction_network begin
15-
@incomplete
14+
degradation_component = @network_component begin
1615
d, X --> 0
1716
end
1817
```
@@ -40,12 +39,10 @@ Catalyst supports two ModelingToolkit interfaces for composing multiple
4039
extending a system is the `extend` command
4140
```@example ex1
4241
using Catalyst
43-
basern = @reaction_network rn1 begin
44-
@incomplete
42+
basern = @network_component rn1 begin
4543
k, A + B --> C
4644
end
47-
newrn = @reaction_network rn2 begin
48-
@incomplete
45+
newrn = @network_component rn2 begin
4946
r, C --> A + B
5047
end
5148
@named rn = extend(newrn, basern)
@@ -58,8 +55,7 @@ The second main compositional modeling tool is the use of subsystems. Suppose we
5855
now add to `basern` two subsystems, `newrn` and `newestrn`, we get a
5956
different result:
6057
```@example ex1
61-
newestrn = @reaction_network rn3 begin
62-
@incomplete
58+
newestrn = @network_component rn3 begin
6359
v, A + D --> 2D
6460
end
6561
@named rn = compose(basern, [newrn, newestrn])
@@ -131,8 +127,7 @@ modular fashion. We start by defining a function that creates a negatively
131127
repressed gene, taking the repressor as input
132128
```@example ex1
133129
function repressed_gene(; R, name)
134-
@reaction_network $name begin
135-
@incomplete
130+
@network_component $name begin
136131
hillr($R,α,K,n), ∅ --> m
137132
(δ,γ), m <--> ∅
138133
β, m --> m + P
@@ -189,15 +184,13 @@ In our model we'll therefore add the conversions of the last column to properly
189184
account for compartment volumes:
190185
```@example ex1
191186
# transcription and regulation
192-
nuc = @reaction_network nuc begin
193-
@incomplete
187+
nuc = @network_component nuc begin
194188
α, G --> G + M
195189
(κ₊/V,κ₋), D + G <--> DG
196190
end
197191
198192
# translation and dimerization
199-
cyto = @reaction_network cyto begin
200-
@incomplete
193+
cyto = @network_component cyto begin
201194
β, M --> M + P
202195
(k₊/V,k₋), 2P <--> D
203196
σ, P --> 0
@@ -206,8 +199,7 @@ end
206199
207200
# export reactions,
208201
# γ,δ=probability per time to be exported/imported
209-
model = @reaction_network model begin
210-
@incomplete
202+
model = @network_component model begin
211203
γ, $(nuc.M) --> $(cyto.M)
212204
δ, $(cyto.D) --> $(nuc.D)
213205
end

src/Catalyst.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ export ODEProblem,
7777
const ExprValues = Union{Expr, Symbol, Float64, Int, Bool}
7878
include("expression_utils.jl")
7979
include("reaction_network.jl")
80-
export @reaction_network, @add_reactions, @reaction, @species
80+
export @reaction_network, @network_component, @add_reactions, @reaction, @species
8181

8282
# registers CRN specific functions using Symbolics.jl
8383
include("registered_functions.jl")

src/reaction_network.jl

Lines changed: 41 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,4 @@
11
### Temporary deprecation warning - Eventually to be removed. ###
2-
deprication_message = """
3-
@reaction_network notation where parameters are declared after "end", e.g. like:
4-
5-
```julia
6-
@reaction_network begin
7-
p, 0 --> X
8-
d, X --> 0
9-
end p d
10-
```
11-
12-
has been deprecated in favor of a notation where the parameters are inferred, e.g:
13-
14-
```julia
15-
@reaction_network begin
16-
p, 0 --> X
17-
d, X --> 0
18-
end
19-
```
20-
21-
Parameters and species can be explicitly indicated using the @parameters and @species
22-
macros, e.g:
23-
24-
```julia
25-
@reaction_network begin
26-
@parameters p d
27-
@species X(t)
28-
p, 0 --> X
29-
d, X --> 0
30-
end
31-
```
32-
"""
33-
macro reaction_network(name::Symbol, ex::Expr, parameters...)
34-
error(deprication_message)
35-
end
36-
macro reaction_network(name::Expr, ex::Expr, parameters...)
37-
error(deprication_message)
38-
end
39-
macro reaction_network(ex::Expr, parameters...)
40-
error(deprication_message)
41-
end
42-
432
"""
443
Macro that inputs an expression corresponding to a reaction network and outputs
454
a `ReactionNetwork` that can be used as input to generation of ODE, SDE, and
@@ -123,7 +82,7 @@ const forbidden_variables_error = let
12382
end
12483

12584
# Declares the keys used for various options.
126-
const option_keys = (:species, :parameters, :variables, :ivs, :compounds, :observables, :default_noise_scaling, :incomplete)
85+
const option_keys = (:species, :parameters, :variables, :ivs, :compounds, :observables, :default_noise_scaling)
12786

12887
### The @species macro, basically a copy of the @variables macro. ###
12988
macro species(ex...)
@@ -186,19 +145,55 @@ emptyrn = @reaction_network empty
186145
# an empty network with random generated name
187146
emptyrn = @reaction_network
188147
```
148+
149+
ReactionSystems generated through `@reaction_network` are compelte.
189150
"""
190151
macro reaction_network(name::Symbol, ex::Expr)
191-
make_reaction_system(MacroTools.striplines(ex); name = :($(QuoteNode(name))))
152+
:(complete($(make_reaction_system(MacroTools.striplines(ex); name = :($(QuoteNode(name)))))))
192153
end
193154

194155
# allows @reaction_network $name begin ... to interpolate variables storing a name
195156
macro reaction_network(name::Expr, ex::Expr)
196-
make_reaction_system(MacroTools.striplines(ex); name = :($(esc(name.args[1]))))
157+
:(complete($(make_reaction_system(MacroTools.striplines(ex); name = :($(esc(name.args[1])))))))
197158
end
198159

199160
macro reaction_network(ex::Expr)
200161
ex = MacroTools.striplines(ex)
201162

163+
# no name but equations: @reaction_network begin ... end ...
164+
if ex.head == :block
165+
:(complete($(make_reaction_system(ex))))
166+
else # empty but has interpolated name: @reaction_network $name
167+
networkname = :($(esc(ex.args[1])))
168+
return Expr(:block, :(@parameters t),
169+
:(complete(ReactionSystem(Reaction[], t, [], []; name = $networkname))))
170+
end
171+
end
172+
173+
#Returns a empty network (with, or without, a declared name)
174+
macro reaction_network(name::Symbol = gensym(:ReactionSystem))
175+
return Expr(:block, :(@parameters t),
176+
:(complete(ReactionSystem(Reaction[], t, [], []; name = $(QuoteNode(name))))))
177+
end
178+
179+
180+
"""
181+
@network_component
182+
183+
As @reaction_network, but the output system is not complete.
184+
"""
185+
macro network_component(name::Symbol, ex::Expr)
186+
make_reaction_system(MacroTools.striplines(ex); name = :($(QuoteNode(name))))
187+
end
188+
189+
# allows @reaction_network $name begin ... to interpolate variables storing a name
190+
macro network_component(name::Expr, ex::Expr)
191+
make_reaction_system(MacroTools.striplines(ex); name = :($(esc(name.args[1]))))
192+
end
193+
194+
macro network_component(ex::Expr)
195+
ex = MacroTools.striplines(ex)
196+
202197
# no name but equations: @reaction_network begin ... end ...
203198
if ex.head == :block
204199
make_reaction_system(ex)
@@ -210,12 +205,12 @@ macro reaction_network(ex::Expr)
210205
end
211206

212207
#Returns a empty network (with, or without, a declared name)
213-
# @reaction_network name
214-
macro reaction_network(name::Symbol = gensym(:ReactionSystem))
208+
macro network_component(name::Symbol = gensym(:ReactionSystem))
215209
return Expr(:block, :(@parameters t),
216210
:(ReactionSystem(Reaction[], t, [], []; name = $(QuoteNode(name)))))
217211
end
218212

213+
219214
### Macros used for manipulating, and successively builing up, reaction systems. ###
220215
@doc raw"""
221216
@reaction

src/reactionsystem.jl

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ struct ReactionSystem{V <: NetworkProperties} <:
544544
# inner constructor is considered private and may change between non-breaking releases.
545545
function ReactionSystem(eqs, rxs, iv, sivs, unknowns, spcs, ps, var_to_name, observed,
546546
name, systems, defaults, connection_type, nps, cls, cevs, devs,
547-
metadata = nothing, complete::Bool = false; checks::Bool = true)
547+
metadata, complete; checks::Bool = true)
548548

549549
# unit checks are for ODEs and Reactions only currently
550550
nonrx_eqs = Equation[eq for eq in eqs if eq isa Equation]
@@ -610,8 +610,7 @@ function ReactionSystem(eqs, iv, unknowns, ps;
610610
spatial_ivs = nothing,
611611
continuous_events = nothing,
612612
discrete_events = nothing,
613-
metadata = nothing,
614-
complete = true)
613+
metadata = nothing)
615614

616615
name === nothing &&
617616
throw(ArgumentError("The `name` keyword must be provided. Please consider using the `@named` macro"))
@@ -681,7 +680,7 @@ function ReactionSystem(eqs, iv, unknowns, ps;
681680

682681
ReactionSystem(eqs′, rxs, iv′, sivs′, unknowns′, spcs, ps′, var_to_name, observed, name,
683682
systems, defaults, connection_type, nps, combinatoric_ratelaws,
684-
ccallbacks, dcallbacks, metadata, complete; checks = checks)
683+
ccallbacks, dcallbacks, metadata, false; checks = checks)
685684
end
686685

687686
function ReactionSystem(rxs::Vector, iv = Catalyst.DEFAULT_IV; kwargs...)
@@ -1472,6 +1471,8 @@ function spatial_convert_err(rs::ReactionSystem, systype)
14721471
isspatial(rs) && error("Conversion to $systype is not supported for spatial networks.")
14731472
end
14741473

1474+
COMPLETENESS_ERROR = "A ReactionSystem must be complete before it can be converted to other system types. A ReactionSystem can be marked as complete using the `compelte` function."
1475+
14751476
"""
14761477
```julia
14771478
Base.convert(::Type{<:ODESystem},rs::ReactionSystem)
@@ -1493,8 +1494,9 @@ function Base.convert(::Type{<:ODESystem}, rs::ReactionSystem; name = nameof(rs)
14931494
include_zero_odes = true, remove_conserved = false, checks = false,
14941495
default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)),
14951496
kwargs...)
1497+
iscomplete(rs) || error(COMPLETENESS_ERROR)
14961498
spatial_convert_err(rs::ReactionSystem, ODESystem)
1497-
fullrs = Catalyst.flatten(rs; complete = true)
1499+
fullrs = Catalyst.flatten(rs)
14981500
remove_conserved && conservationlaws(fullrs)
14991501
ists, ispcs = get_indep_sts(fullrs, remove_conserved)
15001502
eqs = assemble_drift(fullrs, ispcs; combinatoric_ratelaws, remove_conserved,
@@ -1509,7 +1511,7 @@ function Base.convert(::Type{<:ODESystem}, rs::ReactionSystem; name = nameof(rs)
15091511
continuous_events = MT.get_continuous_events(fullrs),
15101512
discrete_events = MT.get_discrete_events(fullrs),
15111513
kwargs...)
1512-
return iscomplete(rs) ? complete(osys) : osys
1514+
return osys
15131515
end
15141516

15151517
"""
@@ -1534,6 +1536,7 @@ function Base.convert(::Type{<:NonlinearSystem}, rs::ReactionSystem; name = name
15341536
include_zero_odes = true, remove_conserved = false, checks = false,
15351537
default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)),
15361538
kwargs...)
1539+
iscomplete(rs) || error(COMPLETENESS_ERROR)
15371540
spatial_convert_err(rs::ReactionSystem, NonlinearSystem)
15381541
fullrs = Catalyst.flatten(rs; complete = true)
15391542
remove_conserved && conservationlaws(fullrs)
@@ -1549,7 +1552,7 @@ function Base.convert(::Type{<:NonlinearSystem}, rs::ReactionSystem; name = name
15491552
defaults = _merge(defaults,defs),
15501553
checks,
15511554
kwargs...)
1552-
return iscomplete(rs) ? complete(nlsys) : nlsys
1555+
return nlsys
15531556
end
15541557

15551558
"""
@@ -1576,6 +1579,7 @@ function Base.convert(::Type{<:SDESystem}, rs::ReactionSystem;
15761579
include_zero_odes = true, checks = false, remove_conserved = false,
15771580
default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)),
15781581
kwargs...)
1582+
iscomplete(rs) || error(COMPLETENESS_ERROR)
15791583
spatial_convert_err(rs::ReactionSystem, SDESystem)
15801584

15811585
flatrs = Catalyst.flatten(rs; complete = true)
@@ -1600,7 +1604,7 @@ function Base.convert(::Type{<:SDESystem}, rs::ReactionSystem;
16001604
continuous_events = MT.get_continuous_events(flatrs),
16011605
discrete_events = MT.get_discrete_events(flatrs),
16021606
kwargs...)
1603-
return iscomplete(rs) ? complete(ssys) : ssys
1607+
return ssys
16041608
end
16051609

16061610
"""
@@ -1626,6 +1630,7 @@ function Base.convert(::Type{<:JumpSystem}, rs::ReactionSystem; name = nameof(rs
16261630
remove_conserved = nothing, checks = false,
16271631
default_u0 = Dict(), default_p = Dict(), defaults = _merge(Dict(default_u0), Dict(default_p)),
16281632
kwargs...)
1633+
iscomplete(rs) || error(COMPLETENESS_ERROR)
16291634
spatial_convert_err(rs::ReactionSystem, JumpSystem)
16301635

16311636
(remove_conserved !== nothing) &&
@@ -1651,7 +1656,7 @@ function Base.convert(::Type{<:JumpSystem}, rs::ReactionSystem; name = nameof(rs
16511656
checks,
16521657
discrete_events = MT.discrete_events(flatrs),
16531658
kwargs...)
1654-
return iscomplete(rs) ? complete(jsys) : jsys
1659+
return jsys
16551660
end
16561661

16571662
### Converts a reaction system to ODE or SDE problems ###
@@ -1667,6 +1672,7 @@ function DiffEqBase.ODEProblem(rs::ReactionSystem, u0, tspan,
16671672
pmap = symmap_to_varmap(rs, p)
16681673
osys = convert(ODESystem, rs; name, combinatoric_ratelaws, include_zero_odes, checks,
16691674
remove_conserved)
1675+
osys = complete(osys)
16701676
return ODEProblem(osys, u0map, tspan, pmap, args...; check_length, kwargs...)
16711677
end
16721678

@@ -1681,6 +1687,7 @@ function DiffEqBase.NonlinearProblem(rs::ReactionSystem, u0,
16811687
pmap = symmap_to_varmap(rs, p)
16821688
nlsys = convert(NonlinearSystem, rs; name, combinatoric_ratelaws, include_zero_odes,
16831689
checks, remove_conserved)
1690+
nlsys = complete(nlsys)
16841691
return NonlinearProblem(nlsys, u0map, pmap, args...; check_length, kwargs...)
16851692
end
16861693

@@ -1695,6 +1702,7 @@ function DiffEqBase.SDEProblem(rs::ReactionSystem, u0, tspan,
16951702
pmap = symmap_to_varmap(rs, p)
16961703
sde_sys = convert(SDESystem, rs; name, combinatoric_ratelaws,
16971704
include_zero_odes, checks, remove_conserved)
1705+
sde_sys = complete(sde_sys)
16981706
p_matrix = zeros(length(get_unknowns(sde_sys)), numreactions(rs))
16991707
return SDEProblem(sde_sys, u0map, tspan, pmap, args...; check_length,
17001708
noise_rate_prototype = p_matrix, kwargs...)
@@ -1709,6 +1717,7 @@ function DiffEqBase.DiscreteProblem(rs::ReactionSystem, u0, tspan::Tuple,
17091717
u0map = symmap_to_varmap(rs, u0)
17101718
pmap = symmap_to_varmap(rs, p)
17111719
jsys = convert(JumpSystem, rs; name, combinatoric_ratelaws, checks)
1720+
jsys = complete(jsys)
17121721
return DiscreteProblem(jsys, u0map, tspan, pmap, args...; kwargs...)
17131722
end
17141723

@@ -1718,6 +1727,7 @@ function JumpProcesses.JumpProblem(rs::ReactionSystem, prob, aggregator, args...
17181727
combinatoric_ratelaws = get_combinatoric_ratelaws(rs),
17191728
checks = false, kwargs...)
17201729
jsys = convert(JumpSystem, rs; name, combinatoric_ratelaws, checks)
1730+
jsys = complete(jsys)
17211731
return JumpProblem(jsys, prob, aggregator, args...; kwargs...)
17221732
end
17231733

@@ -1732,6 +1742,7 @@ function DiffEqBase.SteadyStateProblem(rs::ReactionSystem, u0,
17321742
pmap = symmap_to_varmap(rs, p)
17331743
osys = convert(ODESystem, rs; name, combinatoric_ratelaws, include_zero_odes, checks,
17341744
remove_conserved)
1745+
osys = complete(osys)
17351746
return SteadyStateProblem(osys, u0map, pmap, args...; check_length, kwargs...)
17361747
end
17371748

@@ -1792,7 +1803,7 @@ Notes:
17921803
- The default value of `combinatoric_ratelaws` will be the logical or of all
17931804
`ReactionSystem`s.
17941805
"""
1795-
function MT.flatten(rs::ReactionSystem; name = nameof(rs), complete = false)
1806+
function MT.flatten(rs::ReactionSystem; name = nameof(rs))
17961807
isempty(get_systems(rs)) && return rs
17971808

17981809
# right now only NonlinearSystems and ODESystems can be handled as subsystems
@@ -1810,8 +1821,7 @@ function MT.flatten(rs::ReactionSystem; name = nameof(rs), complete = false)
18101821
balanced_bc_check = false,
18111822
spatial_ivs = get_sivs(rs),
18121823
continuous_events = MT.continuous_events(rs),
1813-
discrete_events = MT.discrete_events(rs),
1814-
complete = complete)
1824+
discrete_events = MT.discre)
18151825
end
18161826

18171827
"""
@@ -1868,6 +1878,5 @@ function ModelingToolkit.extend(sys::MT.AbstractSystem, rs::ReactionSystem;
18681878
balanced_bc_check = false,
18691879
spatial_ivs = sivs,
18701880
continuous_events,
1871-
discrete_events,
1872-
complete = false)
1881+
discrete_events)
18731882
end

0 commit comments

Comments
 (0)