Simulation experiments¶
A SimulationExperiment is the reproducible description of an experiment: the models, the datasets, the simulations, the tasks which apply a simulation to a model, the data derived from the results, and the figures and reports. The experiment is a python class; the ExperimentRunner executes it and writes results, figures and a JSON serialization.
Defining an experiment¶
An experiment subclasses SimulationExperiment and overrides the methods for its parts. Every method returns a dictionary keyed by identifier, and the parts reference each other by these identifiers:
from pathlib import Path
from sbmlsim.data import Data
from sbmlsim.experiment import SimulationExperiment
from sbmlsim.model import AbstractModel
from sbmlsim.plot import Axis, Figure
from sbmlsim.resources import REPRESSILATOR_SBML
from sbmlsim.simulation import AbstractSim, Timecourse, TimecourseSim
from sbmlsim.task import Task
class RepressilatorExperiment(SimulationExperiment):
"""Repressilator with a perturbation of X."""
def models(self) -> dict[str, AbstractModel | Path]:
return {"model": REPRESSILATOR_SBML}
def simulations(self) -> dict[str, AbstractSim]:
return {
"tc": TimecourseSim(
[
Timecourse(start=0, end=100, steps=100),
Timecourse(start=0, end=100, steps=100, changes={"X": 10}),
]
)
}
def tasks(self) -> dict[str, Task]:
return {"task_tc": Task(model="model", simulation="tc")}
def data(self) -> dict[str, Data]:
data = [Data(sid, task="task_tc") for sid in ["time", "[X]", "[Y]", "[Z]"]]
return {d.sid: d for d in data}
def figures(self) -> dict[str, Figure]:
fig = Figure(experiment=self, sid="fig1", name="Repressilator", num_rows=1)
plots = fig.create_plots(
xaxis=Axis("time", unit="second"),
yaxis=Axis("concentration", unit="dimensionless"),
legend=True,
)
for sid in ["[X]", "[Y]", "[Z]"]:
plots[0].curve(
x=Data("time", task="task_tc"), y=Data(sid, task="task_tc"), label=sid
)
return {"fig1": fig}
- models are paths, URLs or
AbstractModelobjects with changes, see Models. They are resolved relative to thebase_pathof the experiment. - simulations are
TimecourseSimorScanSimobjects, see Timecourse simulations and Parameter scans. - tasks apply a simulation to a model; the results of the experiment are keyed by task.
- data are
Dataobjects referencing a task or a dataset, see Data. - figures are
Figureobjects with plots and curves, see Plots and reports. - datasets (not used here) are
DataSetobjects with experimental data, see Data.
Running an experiment¶
The ExperimentRunner creates the experiments, loads their models into a simulator and runs them. The results, the figures (svg by default) and the JSON serialization of every experiment are written below output_path:
from sbmlsim.experiment import ExperimentRunner
from sbmlsim.simulator import SimulatorSerial
runner = ExperimentRunner(
[RepressilatorExperiment],
simulator=SimulatorSerial(),
base_path=Path.cwd(),
data_path=Path.cwd(),
)
results = runner.run_experiments(output_path=Path.cwd() / "results")
print(results[0].experiment)
print(sorted(p.name for p in (Path.cwd() / "results").rglob("*") if p.is_file()))
base_path is the directory the model sources are resolved against, data_path the directory of the datasets. The results of an experiment are the XResult of every task:
experiment = results[0].experiment
xres = experiment.results["task_tc"]
print(xres["[X]"].values[-3:])
run_experiments(reduced_selections=True) records only the variables the data of the experiment refer to, which speeds up large experiments; reduced_selections=False records everything.
Reports¶
ExperimentReport renders the results of one or several experiments into an HTML (or markdown) report with the figures, the models and the simulations of every experiment:
from sbmlsim.report.experiment_report import ExperimentReport
report = ExperimentReport(results)
report_path = report.create_report(output_path=Path.cwd() / "results")
print(report_path)
Serialization¶
Every experiment is serialized to JSON when it is run, <ExperimentId>.json below the output path, with the models, simulations, tasks, data and figures. The serialization is the basis of the SED-ML export of an experiment:
Where to look¶
The examples contain complete experiments: examples/initial_assignment for a model with changes and two simulations, examples/curve_types for the curve types of the plots, examples/glucose for an experiment with datasets and a dose response scan, and examples/hctz for pharmacokinetics experiments with data from two studies and the parameter fitting problems built on them.