Skip to content

Commit 409a058

Browse files
committed
update after Sam's comments
1 parent b5542f0 commit 409a058

File tree

7 files changed

+124
-120
lines changed

7 files changed

+124
-120
lines changed

src/dsl.jl

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -868,4 +868,31 @@ function get_reaction(line)
868868
error("Malformed reaction. @reaction macro only creates a single reaction. E.g. double arrows, such as `<-->` are not supported.")
869869
end
870870
return reaction[1]
871+
end
872+
873+
874+
### Generic Expression Manipulation ###
875+
876+
# Recursively traverses an expression and replaces special function call like "hill(...)" with the actual corresponding expression.
877+
function recursive_expand_functions!(expr::ExprValues)
878+
(typeof(expr) != Expr) && (return expr)
879+
foreach(i -> expr.args[i] = recursive_expand_functions!(expr.args[i]),
880+
1:length(expr.args))
881+
if expr.head == :call
882+
!isdefined(Catalyst, expr.args[1]) && (expr.args[1] = esc(expr.args[1]))
883+
end
884+
expr
885+
end
886+
887+
# Returns the length of a expression tuple, or 1 if it is not an expression tuple (probably a Symbol/Numerical).
888+
function tup_leng(ex::ExprValues)
889+
(typeof(ex) == Expr && ex.head == :tuple) && (return length(ex.args))
890+
return 1
891+
end
892+
893+
# Gets the ith element in a expression tuple, or returns the input itself if it is not an expression tuple
894+
# (probably a Symbol/Numerical).
895+
function get_tup_arg(ex::ExprValues, i::Int)
896+
(tup_leng(ex) == 1) && (return ex)
897+
return ex.args[i]
871898
end

src/expression_utils.jl

Lines changed: 0 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,6 @@ function is_escaped_expr(expr)
2020
end
2121

2222

23-
### Generic Expression Manipulation ###
24-
25-
# Recursively traverses an expression and replaces special function call like "hill(...)" with the actual corresponding expression.
26-
function recursive_expand_functions!(expr::ExprValues)
27-
(typeof(expr) != Expr) && (return expr)
28-
foreach(i -> expr.args[i] = recursive_expand_functions!(expr.args[i]),
29-
1:length(expr.args))
30-
if expr.head == :call
31-
!isdefined(Catalyst, expr.args[1]) && (expr.args[1] = esc(expr.args[1]))
32-
end
33-
expr
34-
end
35-
36-
# Returns the length of a expression tuple, or 1 if it is not an expression tuple (probably a Symbol/Numerical).
37-
function tup_leng(ex::ExprValues)
38-
(typeof(ex) == Expr && ex.head == :tuple) && (return length(ex.args))
39-
return 1
40-
end
41-
42-
# Gets the ith element in a expression tuple, or returns the input itself if it is not an expression tuple
43-
# (probably a Symbol/Numerical).
44-
function get_tup_arg(ex::ExprValues, i::Int)
45-
(tup_leng(ex) == 1) && (return ex)
46-
return ex.args[i]
47-
end
48-
49-
5023
### Parameters/Species/Variables Symbols Correctness Checking ###
5124

5225
# Throws an error when a forbidden symbol is used.

src/reaction_structure.jl renamed to src/reaction.jl

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -242,17 +242,9 @@ end
242242
# Union type for `Reaction`s and `Equation`s.
243243
const CatalystEqType = Union{Reaction, Equation}
244244

245-
### Base Functions ###
246-
247-
# Show function for `Reaction`s.
248-
function Base.show(io::IO, rx::Reaction)
249-
print(io, rx.rate, ", ")
250-
print_rxside(io, rx.substrates, rx.substoich)
251-
arrow = rx.only_use_rate ? "" : "-->"
252-
print(io, " ", arrow, " ")
253-
print_rxside(io, rx.products, rx.prodstoich)
254-
end
245+
### Base Function Dispatches ###
255246

247+
# Used by `Base.show`.
256248
function print_rxside(io::IO, specs, stoich)
257249
# reactants/substrates
258250
if isempty(specs)
@@ -275,6 +267,15 @@ function print_rxside(io::IO, specs, stoich)
275267
nothing
276268
end
277269

270+
# Show function for `Reaction`s.
271+
function Base.show(io::IO, rx::Reaction)
272+
print(io, rx.rate, ", ")
273+
print_rxside(io, rx.substrates, rx.substoich)
274+
arrow = rx.only_use_rate ? "" : "-->"
275+
print(io, " ", arrow, " ")
276+
print_rxside(io, rx.products, rx.prodstoich)
277+
end
278+
278279
"""
279280
==(rx1::Reaction, rx2::Reaction)
280281
@@ -311,10 +312,18 @@ function hash(rx::Reaction, h::UInt)
311312
end
312313

313314

314-
### ModelingToolkit-inherited Functions ###
315+
### ModelingToolkit Function Dispatches ###
316+
317+
# Used by ModelingToolkit.namespace_equation.
318+
function apply_if_nonempty(f, v)
319+
isempty(v) && return v
320+
s = similar(v)
321+
map!(f, s, v)
322+
s
323+
end
315324

316325
# Returns a name-spaced version of a reaction.
317-
function ModelingToolkit.namespace_equation(rx::Reaction, name; kw...)
326+
function MT.namespace_equation(rx::Reaction, name; kw...)
318327
f = Base.Fix2(namespace_expr, name)
319328
rate = f(rx.rate)
320329
subs = apply_if_nonempty(f, rx.substrates)
@@ -330,22 +339,15 @@ function ModelingToolkit.namespace_equation(rx::Reaction, name; kw...)
330339
Reaction(rate, subs, prods, substoich, prodstoich, netstoich, rx.only_use_rate, rx.metadata)
331340
end
332341

333-
function apply_if_nonempty(f, v)
334-
isempty(v) && return v
335-
s = similar(v)
336-
map!(f, s, v)
337-
s
338-
end
339-
340342
# Overwrites equation-type functions to give the correct input for `Reaction`s.
341-
ModelingToolkit.is_diff_equation(rx::Reaction) = false
342-
ModelingToolkit.is_alg_equation(rx::Reaction) = false
343+
MT.is_diff_equation(rx::Reaction) = false
344+
MT.is_alg_equation(rx::Reaction) = false
343345

344346

345347
### Dependency-related Functions ###
346348

347349
# determine which unknowns a reaction depends on
348-
function ModelingToolkit.get_variables!(deps::Set, rx::Reaction, variables)
350+
function MT.get_variables!(deps::Set, rx::Reaction, variables)
349351
(rx.rate isa Symbolic) && get_variables!(deps, rx.rate, variables)
350352
for s in rx.substrates
351353
# parametric stoichiometry means may have a parameter as a substrate
@@ -355,14 +357,14 @@ function ModelingToolkit.get_variables!(deps::Set, rx::Reaction, variables)
355357
end
356358

357359
# determine which species a reaction modifies
358-
function ModelingToolkit.modified_unknowns!(munknowns, rx::Reaction, sts::Set)
360+
function MT.modified_unknowns!(munknowns, rx::Reaction, sts::Set)
359361
for (species, stoich) in rx.netstoich
360362
(species in sts) && push!(munknowns, species)
361363
end
362364
munknowns
363365
end
364366

365-
function ModelingToolkit.modified_unknowns!(munknowns, rx::Reaction, sts::AbstractVector)
367+
function MT.modified_unknowns!(munknowns, rx::Reaction, sts::AbstractVector)
366368
for (species, stoich) in rx.netstoich
367369
any(isequal(species), sts) && push!(munknowns, species)
368370
end

src/reactionsystem_structure.jl renamed to src/reactionsystem.jl

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ function make_ReactionSystem_internal(rxs_and_eqs::Vector, iv, us_in, ps_in; spa
523523
end
524524

525525

526-
### Base Functions ###
526+
### Base Function Dispatches ###
527527

528528
"""
529529
==(rn1::ReactionSystem, rn2::ReactionSystem)
@@ -574,38 +574,6 @@ function isequivalent(rn1::ReactionSystem, rn2::ReactionSystem; ignorenames = tr
574574
end
575575

576576

577-
### ModelingToolkit-inherited Functions ###
578-
579-
# Retrives events.
580-
MT.get_continuous_events(sys::ReactionSystem) = getfield(sys, :continuous_events)
581-
# `MT.get_discrete_events(sys::ReactionSystem) = getfield(sys, :get_discrete_events)` should be added here.
582-
583-
# need a custom equations since ReactionSystem.eqs are a mix of Reactions and Equations
584-
function MT.equations(sys::ReactionSystem)
585-
ivs = independent_variables(sys)
586-
eqs = get_eqs(sys)
587-
systems = get_systems(sys)
588-
if !isempty(systems)
589-
eqs = CatalystEqType[eqs;
590-
reduce(vcat, MT.namespace_equations.(systems, (ivs,));
591-
init = Any[])]
592-
return sort!(eqs; by = eqsortby)
593-
end
594-
return eqs
595-
end
596-
597-
function MT.unknowns(sys::ReactionSystem)
598-
sts = get_unknowns(sys)
599-
systems = get_systems(sys)
600-
if !isempty(systems)
601-
sts = unique!([sts; reduce(vcat, namespace_variables.(systems))])
602-
sort!(sts; by = !isspecies)
603-
return sts
604-
end
605-
return sts
606-
end
607-
608-
609577
### Basic `ReactionSystem`-specific Accessors ###
610578

611579
"""
@@ -663,6 +631,24 @@ function combinatoric_ratelaws(sys::ReactionSystem)
663631
mapreduce(combinatoric_ratelaws, |, subsys; init = crl)
664632
end
665633

634+
# Gets sub systems that are also reaction systems.
635+
# Used by several subsequent API functions.
636+
function filter_nonrxsys(network)
637+
systems = get_systems(network)
638+
rxsystems = ReactionSystem[]
639+
for sys in systems
640+
(sys isa ReactionSystem) && push!(rxsystems, sys)
641+
end
642+
rxsystems
643+
end
644+
645+
# Special species but which take a set of states and names spaces them according to another
646+
# `ReactionSystem`.
647+
# Used by `species(network)`.
648+
function species(network::ReactionSystem, sts)
649+
[MT.renamespace(network, st) for st in sts]
650+
end
651+
666652
"""
667653
species(network)
668654
@@ -681,12 +667,6 @@ function species(network)
681667
unique([sts; reduce(vcat, map(sys -> species(sys, species(sys)), systems))])
682668
end
683669

684-
# Special species but which take a set of states and names spaces them according to another
685-
# `ReactionSystem`.
686-
function species(network::ReactionSystem, sts)
687-
[MT.renamespace(network, st) for st in sts]
688-
end
689-
690670
"""
691671
numspecies(network)
692672
@@ -863,14 +843,36 @@ Returns whether `rn` has any spatial independent variables (i.e. is a spatial ne
863843
"""
864844
isspatial(rn::ReactionSystem) = !isempty(get_sivs(rn))
865845

866-
# Gets sub systems that are also reaction systems.
867-
function filter_nonrxsys(network)
868-
systems = get_systems(network)
869-
rxsystems = ReactionSystem[]
870-
for sys in systems
871-
(sys isa ReactionSystem) && push!(rxsystems, sys)
846+
847+
### ModelingToolkit Function Dispatches ###
848+
849+
# Retrives events.
850+
MT.get_continuous_events(sys::ReactionSystem) = getfield(sys, :continuous_events)
851+
# `MT.get_discrete_events(sys::ReactionSystem) = getfield(sys, :get_discrete_events)` should be added here.
852+
853+
# need a custom equations since ReactionSystem.eqs are a mix of Reactions and Equations
854+
function MT.equations(sys::ReactionSystem)
855+
ivs = independent_variables(sys)
856+
eqs = get_eqs(sys)
857+
systems = get_systems(sys)
858+
if !isempty(systems)
859+
eqs = CatalystEqType[eqs;
860+
reduce(vcat, MT.namespace_equations.(systems, (ivs,));
861+
init = Any[])]
862+
return sort!(eqs; by = eqsortby)
872863
end
873-
rxsystems
864+
return eqs
865+
end
866+
867+
function MT.unknowns(sys::ReactionSystem)
868+
sts = get_unknowns(sys)
869+
systems = get_systems(sys)
870+
if !isempty(systems)
871+
sts = unique!([sts; reduce(vcat, namespace_variables.(systems))])
872+
sort!(sts; by = !isspecies)
873+
return sts
874+
end
875+
return sts
874876
end
875877

876878

@@ -1435,4 +1437,4 @@ function validate(rs::ReactionSystem, info::String = "")
14351437
end
14361438

14371439
# Checks if a unit consist of exponents with base 1 (and is this unitless).
1438-
(u) = istree(u) && (operation(u) == ^) && (arguments(u)[1] == 1)
1440+
unitless_exp(u) = istree(u) && (operation(u) == ^) && (arguments(u)[1] == 1)

src/reactionsystem_conversions.jl

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ function oderatelaw(rx; combinatoric_ratelaw = true)
4242
rl
4343
end
4444

45+
# Function returning `true` for species which shouldn't change from the reactions,
46+
# including non-species variables.
47+
drop_dynamics(s) = isconstant(s) || isbc(s) || (!isspecies(s))
48+
4549
function assemble_oderhs(rs, ispcs; combinatoric_ratelaws = true, remove_conserved = false)
4650
nps = get_networkproperties(rs)
4751
species_to_idx = Dict(x => i for (i, x) in enumerate(ispcs))
@@ -432,10 +436,6 @@ end
432436

433437
### Utility ###
434438

435-
# Function returning `true` for species which shouldn't change from the reactions,
436-
# including non-species variables.
437-
drop_dynamics(s) = isconstant(s) || isbc(s) || (!isspecies(s))
438-
439439
# Throws an error when attempting to convert a spatial system to an unssuported type.
440440
function spatial_convert_err(rs::ReactionSystem, systype)
441441
isspatial(rs) && error("Conversion to $systype is not supported for spatial networks.")
@@ -789,6 +789,24 @@ end
789789

790790
### Symbolic Variable/Symbol Conversions ###
791791

792+
# convert symbol of the form :sys.a.b.c to a symbolic a.b.c
793+
function _symbol_to_var(sys, sym)
794+
if hasproperty(sys, sym)
795+
var = getproperty(sys, sym, namespace = false)
796+
else
797+
strs = split(String(sym), "") # need to check if this should be split of not!!!
798+
if length(strs) > 1
799+
var = getproperty(sys, Symbol(strs[1]), namespace = false)
800+
for str in view(strs, 2:length(strs))
801+
var = getproperty(var, Symbol(str), namespace = true)
802+
end
803+
else
804+
throw(ArgumentError("System $(nameof(sys)): variable $sym does not exist"))
805+
end
806+
end
807+
var
808+
end
809+
792810
"""
793811
symmap_to_varmap(sys, symmap)
794812
@@ -853,24 +871,6 @@ end
853871
symmap_to_varmap(sys, symmap) = symmap
854872
#error("symmap_to_varmap requires a Dict, AbstractArray or Tuple to map Symbols to values.")
855873

856-
# convert symbol of the form :sys.a.b.c to a symbolic a.b.c
857-
function _symbol_to_var(sys, sym)
858-
if hasproperty(sys, sym)
859-
var = getproperty(sys, sym, namespace = false)
860-
else
861-
strs = split(String(sym), "") # need to check if this should be split of not!!!
862-
if length(strs) > 1
863-
var = getproperty(sys, Symbol(strs[1]), namespace = false)
864-
for str in view(strs, 2:length(strs))
865-
var = getproperty(var, Symbol(str), namespace = true)
866-
end
867-
else
868-
throw(ArgumentError("System $(nameof(sys)): variable $sym does not exist"))
869-
end
870-
end
871-
var
872-
end
873-
874874

875875
### Other Conversion-related Functions ###
876876

0 commit comments

Comments
 (0)