Catalyst.jl compositions with parameters as stoichiometric constants

I am trying to build a set of reaction models that I can compose together using Catalyst.jl, but running into a small problem.

Say I want to model a system and include stoichiometric terms as parameters. For instance, the A → B reaction parameterized such that A can produce n number of B’s:

using Catalyst
rn_simple = @reaction_network simple begin
    k1, A --> n*B
    k2, B --> C
end k1  k2 n

This evaluates and works just fine with all downstream tools.

However, lets say now I want to decouple the A->B step from the B->C reaction and compose them later:

rn_AB = @reaction_network AB begin
    k1, A --> n*B
end k1 n

rn_BC = @reaction_network BC begin
    k2, B --> C
end k2

This fails:

@variables t
@named rs = ReactionSystem(t; systems = [rn_AB, rn_BC])
MethodError: no method matching Reaction(::Sym{Real, Base.ImmutableDict{DataType, Any}}, ::Vector{Term{Real, Base.ImmutableDict{DataType, Any}}}, ::Vector{Term{Real, Base.ImmutableDict{DataType, Any}}}, ::Vector{Any}, ::Vector{Any}, ::Vector{Pair{Term{Real, Base.ImmutableDict{DataType, Any}}}}, ::Bool)
Closest candidates are:
  Reaction(::Any, ::Vector, ::Vector, ::Vector{T}, ::Vector{T}, ::Array{Pair{S, T}, 1}, ::Bool) where {S, T} at ~/.julia/packages/Catalyst/48igp/src/reactionsystem.jl:74
  Reaction(::Any, ::Any, ::Any, ::Any, ::Any; netstoich, only_use_rate, kwargs...) at ~/.julia/packages/Catalyst/48igp/src/reactionsystem.jl:100
  Reaction(::Any, ::Any, ::Any; kwargs...) at ~/.julia/packages/Catalyst/48igp/src/reactionsystem.jl:155

Stacktrace:
  [1] namespace_equation(rx::Reaction{Any, Any}, name::ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}})
    @ Catalyst ~/.julia/packages/Catalyst/48igp/src/reactionsystem.jl:195
  [2] (::ModelingToolkit.var"#79#80"{ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}}})(eq::Reaction{Any, Any})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/fWNRg/src/systems/abstractsystem.jl:390
  [3] iterate
    @ ./generator.jl:47 [inlined]
  [4] _collect(c::Vector{Reaction}, itr::Base.Generator{Vector{Reaction}, ModelingToolkit.var"#79#80"{ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}}}}, #unused#::Base.EltypeUnknown, isz::Base.HasShape{1})
    @ Base ./array.jl:744
  [5] collect_similar(cont::Vector{Reaction}, itr::Base.Generator{Vector{Reaction}, ModelingToolkit.var"#79#80"{ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}}}})
    @ Base ./array.jl:653
  [6] map(f::Function, A::Vector{Reaction})
    @ Base ./abstractarray.jl:2867
  [7] namespace_equations(sys::ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/fWNRg/src/systems/abstractsystem.jl:390
  [8] _broadcast_getindex_evalf
    @ ./broadcast.jl:670 [inlined]
  [9] _broadcast_getindex
    @ ./broadcast.jl:643 [inlined]
 [10] getindex
    @ ./broadcast.jl:597 [inlined]
 [11] copy
    @ ./broadcast.jl:899 [inlined]
 [12] materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.DefaultArrayStyle{1}, Nothing, typeof(ModelingToolkit.namespace_equations), Tuple{Vector{ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}}}}})
    @ Base.Broadcast ./broadcast.jl:860
 [13] equations(sys::ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}})
    @ Catalyst ~/.julia/packages/Catalyst/48igp/src/reactionsystem.jl:650
 [14] show(io::IOContext{IOBuffer}, mime::MIME{Symbol("text/plain")}, sys::ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}})
    @ ModelingToolkit ~/.julia/packages/ModelingToolkit/fWNRg/src/systems/abstractsystem.jl:715
 [15] limitstringmime(mime::MIME{Symbol("text/plain")}, x::ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}})
    @ IJulia ~/.julia/packages/IJulia/AQu2H/src/inline.jl:43
 [16] display_mimestring
    @ ~/.julia/packages/IJulia/AQu2H/src/display.jl:71 [inlined]
 [17] display_dict(x::ReactionSystem{Nothing, Catalyst.NetworkProperties{Int64, Term{Real, Base.ImmutableDict{DataType, Any}}}})
    @ IJulia ~/.julia/packages/IJulia/AQu2H/src/display.jl:102
 [18] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
 [19] invokelatest
    @ ./essentials.jl:714 [inlined]
 [20] execute_request(socket::ZMQ.Socket, msg::IJulia.Msg)
    @ IJulia ~/.julia/packages/IJulia/AQu2H/src/execute_request.jl:112
 [21] #invokelatest#2
    @ ./essentials.jl:716 [inlined]
 [22] invokelatest
    @ ./essentials.jl:714 [inlined]
 [23] eventloop(socket::ZMQ.Socket)
    @ IJulia ~/.julia/packages/IJulia/AQu2H/src/eventloop.jl:8
 [24] (::IJulia.var"#15#18")()
    @ IJulia ./task.jl:429

WARNING: both Symbolics and ModelingToolkit export "infimum"; uses of it in module Catalyst must be qualified
WARNING: both Symbolics and ModelingToolkit export "supremum"; uses of it in module Catalyst must be qualified

However if I drop the n parameter, it composes just fine:

rn_AB_no_n = @reaction_network AB begin
    k1, A --> B
end k1

@named rs_no_n = ReactionSystem(t; systems = [rn_AB_no_n, rn_BC])

Am I doing something dumb here, or is this a bug?

It looks like when we added parametric stoichiometry we forgot to update the function that handles renaming subsystems for parameters in the stoichiometry. Sorry about that! I’ll put through a fix shortly.

1 Like

Thanks for the confirmation! Looking forward to the fix.

Version 12.2.1 should be out now with the fix. Feel free to let us know if you have further issues – the parametric stoichiometry is relatively new, and probably hasn’t been used with all the compositional features real thoroughly (they’ve been around longer).

Thanks so much for the super fast turnaround and all your great work on Catalyst!

1 Like