Trouble with interacting components
Hi all! I'm trying to use Catalyst to model two interacting systems in E. coli: a nutrient sensor and a motor subsystem. The sensor measures nutrient concentrations L and outputs the target motor speed λ. The motor moves depending on λ and measures the nutrient concentration L based on the current position of the cell.
In my case λ is best described as an observable, so I tried
using Catalyst
t = default_t()
@variables L(t) λ(t)
rec = @network_component rec begin
@observables begin
$λ ~ E / (E + Ep)
end
$(ParentScope(L)), E --> Ep
1., Ep --> 0
end
mot = @network_component mot begin
@equations begin
D($(ParentScope(L))) ~ $(ParentScope(λ))
end
end
rn = complete(ReactionSystem(t; name=:rn, systems=[rec, mot]))
u0 = [ rec.E => 0, rec.Ep => 10, L => 5 ]
tmax = 100.
prob = ODEProblem(rn, u0, (0, tmax); structural_simplify=true)
This yields
ERROR: ExtraVariablesSystemException: The system is unbalanced. There are 4 highest order derivative variables and 3 equations.
More variables than equations, here are the potential extra variable(s):
rec₊E(t)
rec₊Ep(t)
L(t)
λ(t)
Note that the process of determining extra variables is a best-effort heuristic. The true extra variables are dependent on the model and may not be in this list.
This is despite the system being well-defined (it can be written as an ODE in terms of E, Ep and L only. I am not sure how to eliminate λ. I'm not quite sure why structural_simplify is needed either, I guess this has to do with dependency resolution? Doing that manually (ouch) as follows:
mot = @network_component mot begin
@equations begin
D($L) ~ $(rec.E) / ($(rec.E) + $(rec.Ep))
end
end
yields
ERROR: LoadError: MethodError: no method matching recursive_escape_functions!(::QuoteNode, ::Vector{Union{Expr, Symbol}})
The function `recursive_escape_functions!` exists, but no method is defined for this combination of argument types.
Closest candidates are:
recursive_escape_functions!(!Matched::Union{Bool, Float64, Int64, Expr, Symbol}, ::Any)
@ Catalyst ~/.julia/packages/Catalyst/8qDWw/src/dsl.jl:983
recursive_escape_functions!(!Matched::Union{Bool, Float64, Int64, Expr, Symbol})
@ Catalyst ~/.julia/packages/Catalyst/8qDWw/src/dsl.jl:983
in expression starting at /home/user/code/mcpop/models/chemotaxis/testall.jl:15
Stacktrace:
(::Catalyst.var"#recursive_escape_functions!##0#recursive_escape_functions!##1"{Expr, Vector{Union{…}}})(i::Int64) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
foreach at [abstractarray.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
recursive_escape_functions!(expr::Expr, syms_skip::Vector{Union{Expr, Symbol}}) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
(::Catalyst.var"#recursive_escape_functions!##0#recursive_escape_functions!##1"{Expr, Vector{Union{…}}})(i::Int64) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
foreach at [abstractarray.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
recursive_escape_functions!(expr::Expr, syms_skip::Vector{Union{Expr, Symbol}}) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
(::Catalyst.var"#recursive_escape_functions!##0#recursive_escape_functions!##1"{Expr, Vector{Union{…}}})(i::Int64) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
foreach at [abstractarray.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
recursive_escape_functions!(expr::Expr, syms_skip::Vector{Union{Expr, Symbol}}) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
escape_equation!(eqexpr::Expr, all_syms::Vector{Union{Expr, Symbol}}) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
#get_rxexprs##2 at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
foreach(f::Catalyst.var"#get_rxexprs##2#get_rxexprs##3"{Vector{Union{Expr, Symbol}}, Expr}, itr::Vector{Expr}) at [abstractarray.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
get_rxexprs(reactions::Vector{Catalyst.DSLReaction}, equations::Vector{Expr}, all_syms::Vector{Union{Expr, Symbol}}) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
make_reaction_system(ex::Expr, name::QuoteNode) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
make_rs_expr(name::QuoteNode, network_expr::Expr; complete::Bool) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
kwcall(::@NamedTuple{complete::Bool}, ::typeof(Catalyst.make_rs_expr), name::QuoteNode, network_expr::Expr) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
var"@network_component"(__source__::LineNumberNode, __module__::Module, name::Symbol, network_expr::Expr) at [dsl.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
eval(m::Module, e::Any) at [boot.jl](vscode-file://vscode-app/opt/vscodium-bin/resources/app/out/vs/code/electron-browser/workbench/workbench.html)
Adding ParentScope at random (I'm not sure how this works) doesn't fix anything. Any advice would be much appreciated!
Thanks for the report. Haven't worked too much with the MTK's componnet-based stuff myself, but will try to look into this.
This error has been mystifying. Depending on the flavour of the system, sometimes replacing @observables by @equation works - I need to look up the exact difference. More weirdly, at one point changing the variable name from lambda to something else fixed the issue. I do not have the exact system where that happened anymore, but I will post it if I find it!