diff --git a/Project.toml b/Project.toml index 702efddf87..89a0320eb5 100644 --- a/Project.toml +++ b/Project.toml @@ -3,6 +3,7 @@ uuid = "479239e8-5488-4da2-87a7-35f2df7eef83" version = "5.0" [deps] +Latexify = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" ModelingToolkit = "961ee093-0014-501f-94e3-6117800e7a78" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" @@ -26,4 +27,4 @@ Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" UnPack = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" [targets] -test = ["DiffEqBase","DiffEqJump","OrdinaryDiffEq","Random","SafeTestsets", "Statistics", "SteadyStateDiffEq", "StochasticDiffEq", "Test", "UnPack"] +test = ["DiffEqBase", "DiffEqJump", "OrdinaryDiffEq", "Random", "SafeTestsets", "Statistics", "SteadyStateDiffEq", "StochasticDiffEq", "Test", "UnPack"] diff --git a/README.md b/README.md index 82e9118687..91276acf65 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,8 @@ the current master branch. - Julia `Expr`s can be obtained for all rate laws and functions determining the deterministic and stochastic terms within resulting ODE, SDE or jump models. - [`Latexify`](https://github.com/korsbo/Latexify.jl) can be used to generate - LaTeX expressions corresponding to generated mathematical models. + LaTeX expressions corresponding to generated mathematical models or the + underlying set of reactions. ## Illustrative Examples #### Gillespie Simulations of Michaelis-Menten Enzyme Kinetics diff --git a/docs/make.jl b/docs/make.jl index 3aa17ed8fd..3837270427 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,6 +1,37 @@ using Documenter using Catalyst, ModelingToolkit + +# supposed hack to get mhchem but doesn't seem to work yet... +# const katex_version = "0.11.1" +# function Documenter.Writers.HTMLWriter.RD.mathengine!(r::Documenter.Utilities.JSDependencies.RequireJS, engine::Documenter.KaTeX) +# push!(r, Documenter.Utilities.JSDependencies.RemoteLibrary( +# "katex", +# "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/$(katex_version)/katex.min.js" +# )) +# push!(r, Documenter.Utilities.JSDependencies.RemoteLibrary( +# "mhchem", +# "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/$(katex_version)/contrib/mhchem.min.js" +# )) +# push!(r, Documenter.Utilities.JSDependencies.RemoteLibrary( +# "katex-auto-render", +# "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/$(katex_version)/contrib/auto-render.min.js", +# deps = ["katex"], +# )) +# push!(r, Documenter.Utilities.JSDependencies.Snippet( +# ["jquery", "katex", "mhchem", "katex-auto-render"], +# ["\$", "katex", "renderMathInElement"], +# """ +# \$(document).ready(function() { +# renderMathInElement( +# document.body, +# $(Documenter.Utilities.JSDependencies.json_jsescape(engine.config, 2)) +# ); +# }) +# """ +# )) +# end + makedocs( sitename = "Catalyst.jl", authors = "Samuel Isaacson", diff --git a/docs/src/index.md b/docs/src/index.md index eb3d51e0d6..9aa1644bfa 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -35,7 +35,8 @@ estimation, machine learning applications, etc). - Julia `Expr`s can be obtained for all rate laws and functions determining the deterministic and stochastic terms within resulting ODE, SDE or jump models. - [`Latexify`](https://github.com/korsbo/Latexify.jl) can be used to generate - LaTeX expressions corresponding to generated mathematical models. + LaTeX expressions corresponding to generated mathematical models or the + underlying set of reactions. ## Installation Catalyst can be installed through the Julia package manager: @@ -46,15 +47,19 @@ using Catalyst ``` ## Illustrative Example -Here is a simple example of generating and solving an SIR ODE model: - +Here is a simple example of generating and solving an SIR ODE model. We first +define the SIR reaction model using Catalyst ```julia -using Catalyst, DiffEqBase, OrdinaryDiffEq +using Catalyst rn = @reaction_network begin - k1, S + I --> 2I - k2, I --> R -end k1 k2 -p = [.1/1000, .01] # [k1,k2] + α, S + I --> 2I + β, I --> R +end α β +``` +To generate and solve a mass action ODE version of the model we use +```julia +using DiffEqBase, OrdinaryDiffEq +p = [.1/1000, .01] # [α,β] tspan = (0.0,250.0) u0 = [999.0,1.0,0.0] # [S,I,R] at t=0 op = ODEProblem(rn, u0, tspan, p) @@ -66,3 +71,4 @@ using Plots plot(sol, lw=2) ``` ![SIR Solution](assets/SIR.svg) + diff --git a/src/Catalyst.jl b/src/Catalyst.jl index 23b8d61aa2..6170f30a5e 100644 --- a/src/Catalyst.jl +++ b/src/Catalyst.jl @@ -4,6 +4,7 @@ using Reexport, ModelingToolkit @reexport using ModelingToolkit import MacroTools import Base: (==), merge!, merge +using Latexify const ExprValues = Union{Expr,Symbol,Float64,Int} @@ -21,4 +22,7 @@ export species, params, reactions, speciesmap, paramsmap, numspecies, numreactio export make_empty_network, addspecies!, addparam!, addreaction! export dependants, dependents +# for Latex printing of ReactionSystems +include("latexify_recipes.jl") + end # module diff --git a/src/latexify_recipes.jl b/src/latexify_recipes.jl new file mode 100644 index 0000000000..49b8efeb8c --- /dev/null +++ b/src/latexify_recipes.jl @@ -0,0 +1,118 @@ +# #Recursively traverses an expression and removes things like X^1, 1*X. Will not actually have any affect on the expression when used as a function, but will make it much easier to look at it for debugging, as well as if it is transformed to LaTeX code. +function recursive_clean!(expr) + (expr isa Symbol) && (expr == :no___noise___scaling) && (return 1) + (typeof(expr)!=Expr) && (return expr) + for i = 1:length(expr.args) + expr.args[i] = recursive_clean!(expr.args[i]) + end + (expr.args[1] == :^) && (expr.args[3] == 1) && (return expr.args[2]) + if expr.args[1] == :* + in(0,expr.args) && (return 0) + i = 1 + while (i = i + 1) <= length(expr.args) + if (typeof(expr.args[i]) == Expr) && (expr.args[i].head == :call) && (expr.args[i].args[1] == :*) + for arg in expr.args[i].args + (arg != :*) && push!(expr.args, arg) + end + end + end + for i = length(expr.args):-1:2 + (typeof(expr.args[i]) == Expr) && (expr.args[i].head == :call) && (expr.args[i].args[1] == :*) && deleteat!(expr.args,i) + (expr.args[i] == 1) && deleteat!(expr.args,i) + end + (length(expr.args) == 2) && (return expr.args[2]) # We have a multiplication of only one thing, return only that thing. + (length(expr.args) == 1) && (return 1) #We have only * and no real argumenys. + (length(expr.args) == 3) && (expr.args[2] == -1) && return :(-$(expr.args[3])) + (length(expr.args) == 3) && (expr.args[3] == -1) && return :(-$(expr.args[2])) + end + if expr.head == :call + (expr.args[1] == :/) && (expr.args[3] == 1) && (return expr.args[2]) + haskey(funcdict, expr.args[1]) && return funcdict[expr.args[1]](expr.args[2:end]) + in(expr.args[1],hill_name) && return hill(expr) + in(expr.args[1],hillR_name) && return hillR(expr) + in(expr.args[1],mm_name) && return mm(expr) + in(expr.args[1],mmR_name) && return mmR(expr) + (expr.args[1] == :binomial) && (expr.args[3] == 1) && return expr.args[2] + #@isdefined($(expr.args[1])) || error("Function $(expr.args[1]) not defined.") + end + return expr +end + + +function chemical_arrows(rn::ModelingToolkit.ReactionSystem; + expand = true, double_linebreak=false, mathjax=true, starred=false, kwargs...) + str = starred ? "\\begin{align*}\n" : "\\begin{align}\n" + eol = double_linebreak ? "\\\\\\\\\n" : "\\\\\n" + + mathjax && (str *= "\\require{mhchem}\n") + + + backwards_reaction = false + rxs = ModelingToolkit.equations(rn) + for (i, r) in enumerate(rxs) + if backwards_reaction + backwards_reaction = false + continue + end + str *= "\\ce{ " + + ### Expand functions to maths expressions + rate = Expr(r.rate) + expand && (rate = recursive_clean!(rate)) + expand && (rate = recursive_clean!(rate)) + + ### Generate formatted string of substrates + substrates = [latexraw("$(substrate[2]== 1 ? "" : "$(substrate[2]) * ") $(substrate[1].op.name)"; kwargs...) for substrate in zip(r.substrates,r.substoich)] + isempty(substrates) && (substrates = ["\\varnothing"]) + + str *= join(substrates, " + ") + + ### Generate reaction arrows + if i + 1 <= length(rxs) && issetequal(r.products,rxs[i+1].substrates) && issetequal(r.substrates,rxs[i+1].products) + ### Bi-directional arrows + rate_backwards = Expr(rxs[i+1].rate) + expand && (rate_backwards = recursive_clean!(rate_backwards)) + expand && (rate_backwards = recursive_clean!(rate_backwards)) + str *= " &<=>" + str *= "[" * latexraw(rate; kwargs...) * "]" + str *= "[" * latexraw(rate_backwards; kwargs...) * "] " + backwards_reaction = true + else + ### Uni-directional arrows + str *= " &->" + str *= "[" * latexraw(rate; kwargs...) * "] " + end + + ### Generate formatted string of products + products = [latexraw("$(product[2]== 1 ? "" : "$(product[2]) * ") $(product[1].op.name)"; kwargs...) for product in zip(r.products,r.prodstoich) ] + isempty(products) && (products = ["\\varnothing"]) + str *= join(products, " + ") + str *= "}$eol" + end + str = str[1:end-length(eol)] * "\n" + + str *= starred ? "\\end{align*}\n" : "\\end{align}\n" + + latexstr = Latexify.LaTeXString(str) + Latexify.COPY_TO_CLIPBOARD && clipboard(latexstr) + return latexstr +end + + +@latexrecipe function f(sys::ModelingToolkit.ReactionSystem) + # Set default option values. + env --> :chem + cdot --> false + + return sys +end + + +function Latexify.infer_output(env, rs::ReactionSystem, args...) + env in [:arrows, :chem, :chemical, :arrow] && return chemical_arrows + + error("The environment $env is not defined.") + latex_function = Latexify.get_latex_function(rs, args...) + + return latex_function +end diff --git a/test/latexify.jl b/test/latexify.jl index 82861af467..d078221f95 100644 --- a/test/latexify.jl +++ b/test/latexify.jl @@ -34,67 +34,37 @@ r = @reaction_network begin (d1,d2,d3,d4,d5), (X1,X2,X3,X4,X5) ⟶ ∅ end v1 K1 n1 v2 K2 n2 v3 K3 n3 v4 K4 n4 v5 K5 n5 k1 k2 k3 k4 k5 k6 d1 d2 d3 d4 d5 -@test latexify(r; noise=true, cdot=false) == +@test latexify(r) == raw"\begin{align} -\mathrm{dX1}\left( t \right) =& \left( \frac{v1 K1^{n1}}{K1^{n1} + X2^{n1}} \frac{v1 X4^{n1}}{K1^{n1} + X4^{n1}} + k1 X2 - \frac{k2}{2} X1 X4^{2} - \frac{k5}{6} X5^{3} X1 + k6 X2 - d1 X1 \right) dt + \sqrt{\left\|\frac{v1 K1^{n1}}{K1^{n1} + X2^{n1}} \frac{v1 X4^{n1}}{K1^{n1} + X4^{n1}}\right\|} dW_{1(t)} + \sqrt{\left\|k1 X2\right\|} dW_{6(t)} + \left( - \sqrt{\left\|\frac{k2}{2} X1 X4^{2}\right\|} \right) dW_{7(t)} + \left( - \sqrt{\left\|\frac{k5}{6} X5^{3} X1\right\|} \right) dW_{10(t)} + \sqrt{\left\|k6 X2\right\|} dW_{11(t)} + \left( - \sqrt{\left\|d1 X1\right\|} \right) dW_{12(t)} \\ -\mathrm{dX2}\left( t \right) =& \left( \frac{v2 X5^{n2}}{K2^{n2} + X5^{n2}} - k1 X2 + \frac{k2}{2} X1 X4^{2} + \frac{k5}{6} X5^{3} X1 - k6 X2 - d2 X2 \right) dt + \sqrt{\left\|\frac{v2 X5^{n2}}{K2^{n2} + X5^{n2}}\right\|} dW_{2(t)} + \left( - \sqrt{\left\|k1 X2\right\|} \right) dW_{6(t)} + \sqrt{\left\|\frac{k2}{2} X1 X4^{2}\right\|} dW_{7(t)} + \sqrt{\left\|\frac{k5}{6} X5^{3} X1\right\|} dW_{10(t)} + \left( - \sqrt{\left\|k6 X2\right\|} \right) dW_{11(t)} + \left( - \sqrt{\left\|d2 X2\right\|} \right) dW_{13(t)} \\ -\mathrm{dX3}\left( t \right) =& \left( \frac{v3 X3^{n3}}{K3^{n3} + X3^{n3}} + k3 X4 - k4 X3 - d3 X3 \right) dt + \sqrt{\left\|\frac{v3 X3^{n3}}{K3^{n3} + X3^{n3}}\right\|} dW_{3(t)} + \sqrt{\left\|k3 X4\right\|} dW_{8(t)} + \left( - \sqrt{\left\|k4 X3\right\|} \right) dW_{9(t)} + \left( - \sqrt{\left\|d3 X3\right\|} \right) dW_{14(t)} \\ -\mathrm{dX4}\left( t \right) =& \left( \frac{v4 K4^{n4}}{K4^{n4} + X1^{n4}} + 2 k1 X2 -2 \frac{k2}{2} X1 X4^{2} - k3 X4 + k4 X3 - d4 X4 \right) dt + \sqrt{\left\|\frac{v4 K4^{n4}}{K4^{n4} + X1^{n4}}\right\|} dW_{4(t)} + 2 \sqrt{\left\|k1 X2\right\|} dW_{6(t)} -2 \sqrt{\left\|\frac{k2}{2} X1 X4^{2}\right\|} dW_{7(t)} + \left( - \sqrt{\left\|k3 X4\right\|} \right) dW_{8(t)} + \sqrt{\left\|k4 X3\right\|} dW_{9(t)} + \left( - \sqrt{\left\|d4 X4\right\|} \right) dW_{15(t)} \\ -\mathrm{dX5}\left( t \right) =& \left( \frac{v5 X2^{n5}}{K5^{n5} + X2^{n5}} -3 \frac{k5}{6} X5^{3} X1 + 3 k6 X2 - d5 X5 \right) dt + \sqrt{\left\|\frac{v5 X2^{n5}}{K5^{n5} + X2^{n5}}\right\|} dW_{5(t)} -3 \sqrt{\left\|\frac{k5}{6} X5^{3} X1\right\|} dW_{10(t)} + 3 \sqrt{\left\|k6 X2\right\|} dW_{11(t)} + \left( - \sqrt{\left\|d5 X5\right\|} \right) dW_{16(t)} +\require{mhchem} +\ce{ \varnothing &->[\frac{v1 K1^{n1}}{K1^{n1} + \left( \mathrm{X2}\left( t \right) \right)^{n1}} \frac{v1 \left( \mathrm{X4}\left( t \right) \right)^{n1}}{K1^{n1} + \left( \mathrm{X4}\left( t \right) \right)^{n1}}] X1}\\ +\ce{ \varnothing &->[\frac{v2 \left( \mathrm{X5}\left( t \right) \right)^{n2}}{K2^{n2} + \left( \mathrm{X5}\left( t \right) \right)^{n2}}] X2}\\ +\ce{ \varnothing &->[\frac{v3 \left( \mathrm{X3}\left( t \right) \right)^{n3}}{K3^{n3} + \left( \mathrm{X3}\left( t \right) \right)^{n3}}] X3}\\ +\ce{ \varnothing &->[\frac{v4 K4^{n4}}{K4^{n4} + \left( \mathrm{X1}\left( t \right) \right)^{n4}}] X4}\\ +\ce{ \varnothing &->[\frac{v5 \left( \mathrm{X2}\left( t \right) \right)^{n5}}{K5^{n5} + \left( \mathrm{X2}\left( t \right) \right)^{n5}}] X5}\\ +\ce{ X2 &<=>[k1][k2] X1 + 2 X4}\\ +\ce{ X4 &<=>[k3][k4] X3}\\ +\ce{ 3 X5 + X1 &<=>[k5][k6] X2}\\ +\ce{ X1 &->[d1] \varnothing}\\ +\ce{ X2 &->[d2] \varnothing}\\ +\ce{ X3 &->[d3] \varnothing}\\ +\ce{ X4 &->[d4] \varnothing}\\ +\ce{ X5 &->[d5] \varnothing} \end{align} " - r = @reaction_network begin (hill(B, p_a, k, n), d_a), 0 ↔ A (p_b, d_b), 0 ↔ B (r_a, r_b), 3B ↔ A end p_a k n d_a p_b d_b r_a r_b - -@test latexify(r; noise=true, bracket=true) == -raw"\begin{align} -\mathrm{\mathrm{d}\left[A\right]}\left( t \right) =& \left( \frac{p_{a} \cdot \left[ B \right]^{n}}{k^{n} + \left[ B \right]^{n}} - d_{a} \cdot \left[ A \right] + \frac{r_{a}}{6} \cdot \left[ B \right]^{3} - r_{b} \cdot \left[ A \right] \right) \cdot dt + \sqrt{\left\|\frac{p_{a} \cdot \left[ B \right]^{n}}{k^{n} + \left[ B \right]^{n}}\right\|} \cdot dW_{1(t)} + \left( - \sqrt{\left\|d_{a} \cdot \left[ A \right]\right\|} \right) \cdot dW_{2(t)} + \sqrt{\left\|\frac{r_{a}}{6} \cdot \left[ B \right]^{3}\right\|} \cdot dW_{5(t)} + \left( - \sqrt{\left\|r_{b} \cdot \left[ A \right]\right\|} \right) \cdot dW_{6(t)} \\ -\mathrm{\mathrm{d}\left[B\right]}\left( t \right) =& \left( p_{b} - d_{b} \cdot \left[ B \right] -3 \cdot \frac{r_{a}}{6} \cdot \left[ B \right]^{3} + 3 \cdot r_{b} \cdot \left[ A \right] \right) \cdot dt + \sqrt{\left\|p_{b}\right\|} \cdot dW_{3(t)} + \left( - \sqrt{\left\|d_{b} \cdot \left[ B \right]\right\|} \right) \cdot dW_{4(t)} -3 \cdot \sqrt{\left\|\frac{r_{a}}{6} \cdot \left[ B \right]^{3}\right\|} \cdot dW_{5(t)} + 3 \cdot \sqrt{\left\|r_{b} \cdot \left[ A \right]\right\|} \cdot dW_{6(t)} -\end{align} -" - - -@test latexify(r; noise_only=true, bracket=true) == -raw"\begin{align} -\mathrm{\mathrm{d}\left[A\right]}\left( t \right) ∝& \sqrt{\left\|\frac{p_{a} \cdot \left[ B \right]^{n}}{k^{n} + \left[ B \right]^{n}}\right\|} \cdot dW_{1(t)} + \left( - \sqrt{\left\|d_{a} \cdot \left[ A \right]\right\|} \right) \cdot dW_{2(t)} + \sqrt{\left\|\frac{r_{a}}{6} \cdot \left[ B \right]^{3}\right\|} \cdot dW_{5(t)} + \left( - \sqrt{\left\|r_{b} \cdot \left[ A \right]\right\|} \right) \cdot dW_{6(t)} \\ -\mathrm{\mathrm{d}\left[B\right]}\left( t \right) ∝& \sqrt{\left\|p_{b}\right\|} \cdot dW_{3(t)} + \left( - \sqrt{\left\|d_{b} \cdot \left[ B \right]\right\|} \right) \cdot dW_{4(t)} -3 \cdot \sqrt{\left\|\frac{r_{a}}{6} \cdot \left[ B \right]^{3}\right\|} \cdot dW_{5(t)} + 3 \cdot \sqrt{\left\|r_{b} \cdot \left[ A \right]\right\|} \cdot dW_{6(t)} -\end{align} -" - - -@test latexify(r; noise_only=true, bracket=true, cdot=false) == -raw"\begin{align} -\mathrm{\mathrm{d}\left[A\right]}\left( t \right) ∝& \sqrt{\left\|\frac{p_{a} \left[ B \right]^{n}}{k^{n} + \left[ B \right]^{n}}\right\|} dW_{1(t)} + \left( - \sqrt{\left\|d_{a} \left[ A \right]\right\|} \right) dW_{2(t)} + \sqrt{\left\|\frac{r_{a}}{6} \left[ B \right]^{3}\right\|} dW_{5(t)} + \left( - \sqrt{\left\|r_{b} \left[ A \right]\right\|} \right) dW_{6(t)} \\ -\mathrm{\mathrm{d}\left[B\right]}\left( t \right) ∝& \sqrt{\left\|p_{b}\right\|} dW_{3(t)} + \left( - \sqrt{\left\|d_{b} \left[ B \right]\right\|} \right) dW_{4(t)} -3 \sqrt{\left\|\frac{r_{a}}{6} \left[ B \right]^{3}\right\|} dW_{5(t)} + 3 \sqrt{\left\|r_{b} \left[ A \right]\right\|} dW_{6(t)} -\end{align} -" - - -@test latexify(r; noise=true, noise_var=:Noise, bracket=true) == +@test latexify(r) == raw"\begin{align} -\mathrm{\mathrm{d}\left[A\right]}\left( t \right) =& \left( \frac{p_{a} \cdot \left[ B \right]^{n}}{k^{n} + \left[ B \right]^{n}} - d_{a} \cdot \left[ A \right] + \frac{r_{a}}{6} \cdot \left[ B \right]^{3} - r_{b} \cdot \left[ A \right] \right) \cdot dt + \sqrt{\left\|\frac{p_{a} \cdot \left[ B \right]^{n}}{k^{n} + \left[ B \right]^{n}}\right\|} \cdot dNoise_{1(t)} + \left( - \sqrt{\left\|d_{a} \cdot \left[ A \right]\right\|} \right) \cdot dNoise_{2(t)} + \sqrt{\left\|\frac{r_{a}}{6} \cdot \left[ B \right]^{3}\right\|} \cdot dNoise_{5(t)} + \left( - \sqrt{\left\|r_{b} \cdot \left[ A \right]\right\|} \right) \cdot dNoise_{6(t)} \\ -\mathrm{\mathrm{d}\left[B\right]}\left( t \right) =& \left( p_{b} - d_{b} \cdot \left[ B \right] -3 \cdot \frac{r_{a}}{6} \cdot \left[ B \right]^{3} + 3 \cdot r_{b} \cdot \left[ A \right] \right) \cdot dt + \sqrt{\left\|p_{b}\right\|} \cdot dNoise_{3(t)} + \left( - \sqrt{\left\|d_{b} \cdot \left[ B \right]\right\|} \right) \cdot dNoise_{4(t)} -3 \cdot \sqrt{\left\|\frac{r_{a}}{6} \cdot \left[ B \right]^{3}\right\|} \cdot dNoise_{5(t)} + 3 \cdot \sqrt{\left\|r_{b} \cdot \left[ A \right]\right\|} \cdot dNoise_{6(t)} +\require{mhchem} +\ce{ \varnothing &<=>[\frac{p_{a} \left( \mathrm{B}\left( t \right) \right)^{n}}{k^{n} + \left( \mathrm{B}\left( t \right) \right)^{n}}][d_{a}] A}\\ +\ce{ \varnothing &<=>[p_{b}][d_{b}] B}\\ +\ce{ 3 B &<=>[r_{a}][r_{b}] A} \end{align} " - -@test latexify(r; bracket=true) == -raw"\begin{align} -\frac{d\left[ A \right](t)}{dt} =& \frac{p_{a} \cdot \left[ B \right]^{n}}{k^{n} + \left[ B \right]^{n}} - d_{a} \cdot \left[ A \right] + \frac{r_{a}}{6} \cdot \left[ B \right]^{3} - r_{b} \cdot \left[ A \right] \\ -\frac{d\left[ B \right](t)}{dt} =& p_{b} - d_{b} \cdot \left[ B \right] -3 \cdot \frac{r_{a}}{6} \cdot \left[ B \right]^{3} + 3 \cdot r_{b} \cdot \left[ A \right] -\end{align} -" - - -@test latexify(r; bracket=false) == -raw"\begin{align} -\frac{dA(t)}{dt} =& \frac{p_{a} \cdot B^{n}}{k^{n} + B^{n}} - d_{a} \cdot A + \frac{r_{a}}{6} \cdot B^{3} - r_{b} \cdot A \\ -\frac{dB(t)}{dt} =& p_{b} - d_{b} \cdot B -3 \cdot \frac{r_{a}}{6} \cdot B^{3} + 3 \cdot r_{b} \cdot A -\end{align} -" diff --git a/test/runtests.jl b/test/runtests.jl index 79f322a758..fb2ec9e7ba 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -29,6 +29,6 @@ using SafeTestsets # Miscellaneous tests #@time @safetestset "Basic Plotting" begin include("plotting.jl") end -#@time @safetestset "Latexify" begin include("latexify.jl") end +@time @safetestset "Latexify" begin include("latexify.jl") end end # @time