An R toolkit for systems-biology and systems-pharmacology models in Heta, SBML, and DynMS formats.
DynMSR helps you take a Heta project, an SBML model, or a DynMS JSON file
and run it from R. It provides one convenient interface between these model
formats and simulation backends: load a model, select it, and build it for
simulation. DynMS (Dynamic Model Specification) is a lightweight, portable
intermediate representation for dynamical simulation models. DynMS files are
read directly; Heta projects and SBML files are converted to DynMS with
heta-compiler first.
Heta project ── heta-compiler ──> DynMS JSON ───────┐
SBML file ───── heta-compiler ──> DynMS JSON ───────┼──> DynMSR ──> R backend
DynMS JSON ─────────────────────────────────────────┘
heta-compiler and DynMS.heta-compiler and DynMS.Install the released version from CRAN:
install.packages("DynMSR")
To install the development version from GitHub:
# install.packages("devtools")
# devtools::install_github("hetalang/DynMSR")
install.packages("DynMSR", repos = c('https://hetalang.r-universe.dev', 'https://cloud.r-project.org'))
DynMSR can also build a Heta project. This workflow,
as well as sbml_load(), requires a compatible heta-compiler installation.
DynMSR works with heta-compiler starting from version 0.12.2.
Install the compiler by following the official Heta installation
instructions.
Then create an empty directory, such as
heta-quick-start, and save this file as heta-quick-start/index.heta:
comp1 @Compartment .= 1;
A @Species { compartment: comp1 } .= 10;
B @Species { compartment: comp1 } .= 0;
r1 @Reaction { actors: A => 2B } := k1 * A * comp1;
k1 @Const = 1.2e-1;
The model describes a reaction in which one unit of A produces two units of
B.
library(DynMSR)
# heta_check()
platform <- heta_load("path/to/heta-quick-start")
model <- get_model(platform, 1)
# install.packages("mrgsolve")
require(mrgsolve)
mrgsolve_model <- build_mrgsolve(model)
result <- mrgsim(mrgsolve_model, end = 100, delta = 1)
plot(result)
With heta-compiler installed as above, create a file named
sbml-quick-start.xml with this SBML Level 2 Version 5 model. Like the Heta
example, it describes the reaction A → 2B.
<?xml version="1.0" encoding="UTF-8"?>
<sbml xmlns="http://www.sbml.org/sbml/level2/version5" level="2" version="5">
<model id="simple_conversion">
<listOfCompartments>
<compartment id="comp1" size="1"/>
</listOfCompartments>
<listOfSpecies>
<species id="A" compartment="comp1" initialAmount="10"/>
<species id="B" compartment="comp1" initialAmount="0"/>
</listOfSpecies>
<listOfParameters>
<parameter id="k1" value="0.12"/>
</listOfParameters>
<listOfReactions>
<reaction id="r1" reversible="false">
<listOfReactants>
<speciesReference species="A"/>
</listOfReactants>
<listOfProducts>
<speciesReference species="B" stoichiometry="2"/>
</listOfProducts>
<kineticLaw>
<math xmlns="http://www.w3.org/1998/Math/MathML"><apply><times/><ci>k1</ci><ci>A</ci></apply></math>
</kineticLaw>
</reaction>
</listOfReactions>
</model>
</sbml>
Load and simulate the model from R:
library(DynMSR)
platform <- sbml_load("path/to/sbml-quick-start.xml")
model <- get_model(platform, 1)
require(mrgsolve)
mrgsolve_model <- build_mrgsolve(model)
result <- mrgsim(mrgsolve_model, end = 100, delta = 1)
plot(result)
Use dynms_lib() to start with a bundled DynMS JSON document. Replace its
call with a path to your own DynMS JSON document when needed.
library(DynMSR)
# Load the DynMS JSON file as a platform
platform <- dynms_load(dynms_lib("repeated-dose"))
# Select the first model in the platform
model <- get_model(platform, 1)
# Build a compiled mrgsolve model object
mrgsolve_model <- build_mrgsolve(model)
# Run a simulation with the mrgsolve model
library(mrgsolve)
res <- mrgsim(mrgsolve_model)
DynMSR treats mrgsolve and deSolve (planned) as backend targets in its architecture: the same loaded DynMS model is intended to support either backend without changing the core loader or validator. The mrgsolve backend is available now. The deSolve backend is planned, but is not yet implemented and cannot currently be used for code generation or simulation.
The mrgsolve backend does not use root finding for DynMS state-event triggers.
The current exporter evaluates such conditions in $ODE; mrgsolve may call
that block at internal trial times rather than only at output records.
Consequently, the generated state update can occur at an output record before
or after the true threshold crossing. This limitation does not apply to DynMS
time events, whose scheduled times are passed directly to mrgsolve.
For a closer step-based approximation, use a smaller output interval:
res <- mrgsolve::mrgsim(mrgsolve_model, delta = 0.01)
Reducing delta and limiting hmax can sometimes make the approximation
closer, but neither reproduces the exact root-crossing time nor guarantees
which side of the threshold an event will be placed. A robust step-based
implementation would evaluate and latch state-event conditions in $TABLE,
where they run on the output grid, rather than in $ODE.
This section presents automated DynMS simulation checks for the main branch.
Each selected SBML Semantic Test Suite case is converted with Heta, loaded by
DynMSR, simulated with mrgsolve, and compared with its reference time course.
| Test set | Simulation check | Latest main
|
|---|---|---|
| sbmlteam/sbml-test-suite | SBML L2V5 → Heta → DynMSR/mrgsolve | |
| sbmlteam/sbml-test-suite | SBML L3V1 → Heta → DynMSR/mrgsolve |
The compiler compatibility rule and installation URL are stored in
inst/config/heta-compiler.json. Heta integration tests run only in CI jobs
that install the optional compiler.
Run the local test suite with:
Rscript -e "pkgload::load_all('.'); testthat::test_dir('tests/testthat')"
Heta integration tests are disabled by default. They require
heta-compiler and can be enabled with:
Rscript -e "Sys.setenv(DYNMSR_RUN_HETA_INTEGRATION = 'true'); pkgload::load_all('.'); testthat::test_dir('tests/testthat')"
Regenerate roxygen2 documentation, including NAMESPACE and man/*.Rd, with:
Rscript -e "roxygen2::roxygenise()"
Bundled DynMS JSON Schemas are stored in inst/schema/. Supported versions,
schema paths, and upstream sources are listed in inst/config/dynms.json.
Schema validation selects the local schema using the document's dynms version.
To refresh all configured local schemas during development:
Rscript tools/update-dynms-schema.R
Heta is an optional DynMS producer; it is not required to read or validate
DynMS JSON files. The compiler compatibility rule is defined in
inst/config/heta-compiler.json.
This is a manual developer step. Package installation, examples, and tests use the bundled local schema and do not download files from the internet.