diff --git a/src/dsl.jl b/src/dsl.jl index aba3f08bc8..4989f25a68 100644 --- a/src/dsl.jl +++ b/src/dsl.jl @@ -23,11 +23,13 @@ macro species(ex...) lastarg = vars.args[end] # start adding metadata statements where the vector of symbols was previously declared + # adds `[latexwrapper = string]` metadata which improves latexify printing. idx = length(vars.args) resize!(vars.args, idx + length(lastarg.args) + 1) for sym in lastarg.args - vars.args[idx] = :($sym = ModelingToolkit.wrap(setmetadata( - ModelingToolkit.value($sym), Catalyst.VariableSpecies, true))) + vars.args[idx] = :($sym = ModelingToolkit.wrap(setmetadata(setmetadata( + ModelingToolkit.value($sym), Catalyst.VariableSpecies, true), + Symbolics.SymLatexWrapper, string))) idx += 1 end diff --git a/src/reactionsystem.jl b/src/reactionsystem.jl index ca11373820..648f646ec8 100644 --- a/src/reactionsystem.jl +++ b/src/reactionsystem.jl @@ -1445,7 +1445,7 @@ function MT.flatten(rs::ReactionSystem; name = nameof(rs)) end function complete_check(sys, method) - if MT.iscomplete(sys) + if MT.iscomplete(sys) error("$method with one or more `ReactionSystem`s requires systems to not be marked complete, but system: $(MT.get_name(sys)) is marked complete.") end nothing @@ -1506,7 +1506,7 @@ function ModelingToolkit.extend(sys::MT.AbstractSystem, rs::ReactionSystem; complete_check(sys, "ModelingToolkit.extend") complete_check(rs, "ModelingToolkit.extend") - + any(T -> sys isa T, (ReactionSystem, ODESystem, NonlinearSystem)) || error("ReactionSystems can only be extended with ReactionSystems, ODESystems and NonlinearSystems currently. Received a $(typeof(sys)) system.") diff --git a/src/reactionsystem_serialisation/serialisation_support.jl b/src/reactionsystem_serialisation/serialisation_support.jl index bb6e7305ed..98e8b85622 100644 --- a/src/reactionsystem_serialisation/serialisation_support.jl +++ b/src/reactionsystem_serialisation/serialisation_support.jl @@ -150,6 +150,7 @@ x_2_string(x::Symbol) = ":$x" x_2_string(x::Number) = string(x) x_2_string(x::Pair) = "$(x_2_string(x[1])) => $(x_2_string(x[2]))" x_2_string(x::Nothing) = "nothing" +x_2_string(x::Function) = String(Symbol(x)) function x_2_string(x::Vector) output = "[" for val in x @@ -212,30 +213,32 @@ end # List of all recognised metadata (we should add as many as possible), and th keyword used to declare # them in code. -const RECOGNISED_METADATA = Dict([Catalyst.ParameterConstantSpecies => "isconstantspecies" - Catalyst.VariableBCSpecies => "isbcspecies" - Catalyst.VariableSpecies => "isspecies" - Catalyst.EdgeParameter => "edgeparameter" - Catalyst.CompoundSpecies => "iscompound" - Catalyst.CompoundComponents => "components" - Catalyst.CompoundCoefficients => "coefficients" - ModelingToolkit.VariableDescription => "description" - ModelingToolkit.VariableBounds => "bounds" - ModelingToolkit.VariableUnit => "unit" - ModelingToolkit.VariableConnectType => "connect" - ModelingToolkit.VariableNoiseType => "noise" - ModelingToolkit.VariableInput => "input" - ModelingToolkit.VariableOutput => "output" - ModelingToolkit.VariableIrreducible => "irreducible" - ModelingToolkit.VariableStatePriority => "state_priority" - ModelingToolkit.VariableMisc => "misc" - ModelingToolkit.TimeDomain => "timedomain"]) +const RECOGNISED_METADATA = Dict([Catalyst.ParameterConstantSpecies => "isconstantspecies", + Catalyst.VariableBCSpecies => "isbcspecies", + Catalyst.VariableSpecies => "isspecies", + Catalyst.EdgeParameter => "edgeparameter", + Catalyst.CompoundSpecies => "iscompound", + Catalyst.CompoundComponents => "components", + Catalyst.CompoundCoefficients => "coefficients", + ModelingToolkit.VariableDescription => "description", + ModelingToolkit.VariableBounds => "bounds", + ModelingToolkit.VariableUnit => "unit", + ModelingToolkit.VariableConnectType => "connect", + ModelingToolkit.VariableNoiseType => "noise", + ModelingToolkit.VariableInput => "input", + ModelingToolkit.VariableOutput => "output", + ModelingToolkit.VariableIrreducible => "irreducible", + ModelingToolkit.VariableStatePriority => "state_priority", + ModelingToolkit.VariableMisc => "misc", + ModelingToolkit.TimeDomain => "timedomain", + Symbolics.SymLatexWrapper => "latexwrapper"]) # List of metadata that does not need to be explicitly declared to be added (or which is handled separately). const SKIPPED_METADATA = [ Catalyst.VariableSpecies, ModelingToolkit.MTKVariableTypeCtx, ModelingToolkit.SymScope, + Symbolics.SymLatexWrapper, Symbolics.VariableDefaultValue, Symbolics.VariableSource] diff --git a/test/visualisation/latexify.jl b/test/visualisation/latexify.jl index 550288a109..3a2c34e8b4 100644 --- a/test/visualisation/latexify.jl +++ b/test/visualisation/latexify.jl @@ -67,7 +67,7 @@ raw"\begin{align*} \mathrm{X3} &\xrightarrow{d3} \varnothing \\ \mathrm{X4} &\xrightarrow{d4} \varnothing \\ \mathrm{X5} &\xrightarrow{d5} \varnothing \\ -\mathrm{X6} &\xrightarrow{d6} \varnothing +\mathrm{X6} &\xrightarrow{d6} \varnothing \end{align*} ", "\r\n"=>"\n") @@ -88,10 +88,10 @@ raw"\begin{align*} \mathrm{X3} &\xrightarrow{d3} \varnothing \\ \mathrm{X4} &\xrightarrow{d4} \varnothing \\ \mathrm{X5} &\xrightarrow{d5} \varnothing \\ -\mathrm{X6} &\xrightarrow{d6} \varnothing +\mathrm{X6} &\xrightarrow{d6} \varnothing \end{align*} ", "\r\n"=>"\n") - + # Latexify.@generate_test latexify(rn, mathjax = false) @test latexify(rn, mathjax = false) == replace( raw"\begin{align*} @@ -109,7 +109,7 @@ raw"\begin{align*} \mathrm{X3} &\xrightarrow{d3} \varnothing \\ \mathrm{X4} &\xrightarrow{d4} \varnothing \\ \mathrm{X5} &\xrightarrow{d5} \varnothing \\ -\mathrm{X6} &\xrightarrow{d6} \varnothing +\mathrm{X6} &\xrightarrow{d6} \varnothing \end{align*} ", "\r\n"=>"\n") end @@ -127,7 +127,7 @@ let raw"\begin{align*} \varnothing &\xrightleftharpoons[d_{a}]{\frac{p_{a} B^{n}}{k^{n} + B^{n}}} \mathrm{A} \\ \varnothing &\xrightleftharpoons[d_{b}]{p_{b}} \mathrm{B} \\ -3 \mathrm{B} &\xrightleftharpoons[r_{b}]{r_{a}} \mathrm{A} +3 \mathrm{B} &\xrightleftharpoons[r_{b}]{r_{a}} \mathrm{A} \end{align*} ", "\r\n"=>"\n") @@ -136,7 +136,7 @@ raw"\begin{align*} raw"\begin{align*} \varnothing &\xrightleftharpoons[d_{a}]{\frac{p_{a} B^{n}}{k^{n} + B^{n}}} \mathrm{A} \\ \varnothing &\xrightleftharpoons[d_{b}]{p_{b}} \mathrm{B} \\ -3 \mathrm{B} &\xrightleftharpoons[r_{b}]{r_{a}} \mathrm{A} +3 \mathrm{B} &\xrightleftharpoons[r_{b}]{r_{a}} \mathrm{A} \end{align*} ", "\r\n"=>"\n") end @@ -150,7 +150,7 @@ let # Latexify.@generate_test latexify(rn) @test latexify(rn) == replace( raw"\begin{align*} -\varnothing &\xrightarrow{p} (m + n)\mathrm{X} +\varnothing &\xrightarrow{p} (m + n)\mathrm{X} \end{align*} ", "\r\n"=>"\n") end @@ -241,7 +241,7 @@ let # Latexify.@generate_test latexify(rn) @test latexify(rn) == replace( raw"\begin{align*} -\mathrm{Y} &\xrightarrow{Y k} \varnothing +\mathrm{Y} &\xrightarrow{Y k} \varnothing \end{align*} ", "\r\n"=>"\n") end @@ -258,7 +258,7 @@ let @test latexify(rn) == replace( raw"\begin{align*} \varnothing &\xrightleftharpoons[\frac{d}{V\left( t \right)}]{\frac{p}{V\left( t \right)}} \mathrm{X} \\ -\frac{\mathrm{d} V\left( t \right)}{\mathrm{d}t} &= X\left( t \right) - V\left( t \right) +\frac{\mathrm{d} V\left( t \right)}{\mathrm{d}t} &= X\left( t \right) - V\left( t \right) \end{align*} ", "\r\n"=>"\n") end @@ -280,3 +280,52 @@ let # Latexify.@generate_test latexify(extended, mathjax=false) @test_broken false end + +# Checks that the `SymLatexWrapper` metadata option is correctly added to all symbolics created +# by the DSL. Checks that this is also the case for species created through the `@species` macro. +# Currently only implemented for species. +let + # Via the DSL (@reaction_network). + rn1 = @reaction_network begin + @species Y(t) + @variables W(t) + @parameters p + @equations D(V) ~ - V + k1, 0 --> X + end + @test_broken all(hasmetadata(u, Symbolics.SymLatexWrapper) && (getmetadata(u, Symbolics.SymLatexWrapper) == string) for u in unknowns(rn1)) + @test_broken all(hasmetadata(p, Symbolics.SymLatexWrapper) && (getmetadata(p, Symbolics.SymLatexWrapper) == string) for p in parameters(rn1)) + + # Via the DSL but using `begin .. end` in declarations and additional options. + rn2 = @reaction_network begin + @species begin + X(t) + Y(t), [description = "A species"] + Z(t) = 1.0 + end + @variables begin + V(t) + W(t), [description = "A variable"] + U(t) = 2.0 + end + @parameters begin + k1 + q, [description = "A parameter"] + r = 3.0 + end + @equations D(V) ~ - V + k1, 0 --> X + end + @test_broken all(hasmetadata(u, Symbolics.SymLatexWrapper) && (getmetadata(u, Symbolics.SymLatexWrapper) == string) for u in unknowns(rn2)) + @test_broken all(hasmetadata(p, Symbolics.SymLatexWrapper) && (getmetadata(p, Symbolics.SymLatexWrapper) == string) for p in parameters(rn2)) + + # Via the DSL (@reaction). + rx = @reaction p, 0 --> x + @test_broken hasmetadata(rx.rate, Symbolics.SymLatexWrapper) && (getmetadata(rx.rate, Symbolics.SymLatexWrapper) == string) + @test hasmetadata(rx.products[1], Symbolics.SymLatexWrapper) && (getmetadata(rx.products[1], Symbolics.SymLatexWrapper) == string) + + # Via the @species. + t = default_t() + @species XYZ(t) + @test hasmetadata(XYZ, Symbolics.SymLatexWrapper) && (getmetadata(XYZ, Symbolics.SymLatexWrapper) == string) +end