HallSim: A Differentiable, Composable Multi-Scale Modelling Framework for Aging Biology
HallSim composes independently-published systems-biology models into one multi-scale dynamical system and calibrates the whole thing by gradient descent through the ODE solve. Built on JAX / Equinox / Diffrax, with a focus on aging biology, where no single model captures the crosstalk between hallmarks.
- End-to-end differentiable. The entire composite of multiple stiff models, operator-split across timescales, is a single differentiable function.
- Agent-friendly by construction.
- Scale is central, not an edge case.
Goals
- Serve as an in-silico testbed for perturbations (rapamycin, caloric restriction, …).
- Make large multi-model composition, tractable for AI agents building at a scale no one assembles by hand.
- Educational material letting students see what happens across a range of processes when a perturbation is applied
Architecture
| Concept | Role |
|---|---|
| Process | eqx.Module with typed ports and a kind (CONTINUOUS / DISCRETE / EVENT); parameters are JAX arrays. |
| Port | Named connection point with a role (INPUT / EVOLVED / EXCLUSIVE / LATCHED / ASSIGNED), units, and ontology. |
| Topology | Static wiring {proc: {port: store_path}}, outside the processes. |
| Composite | Bundles processes + topology into a flat, JAX-compatible ODE RHS; auto-groups by timescale. |
| Scheduler | The one runner for every composite shape — timescale groups, discrete dispatch, events, batched populations. |
| Store | Flat dict[str, jnp.ndarray] with path-like keys; a JAX PyTree. |
A composition-time validation layer (units via pint, ontology IDs, feedback/fan-in graph analysis, duplicate-reaction heuristics) runs warnings-by-default and raises on hard conflicts.
Quickstart
make install # or: make install-dev
import jax.numpy as jnp
from hallsim.process import Process, Port, PortRole
from hallsim.composite import Composite
from hallsim.scheduler import Scheduler
class Decay(Process):
rate: float = 0.1
def ports_schema(self):
return {"x": Port(role=PortRole.EVOLVED, default=1.0, units="uM")}
def derivative(self, t, state):
return {"x": -self.rate * state["x"]}
class Growth(Process):
rate: float = 0.05
def ports_schema(self):
return {"x": Port(role=PortRole.EVOLVED, default=1.0, units="uM")}
def derivative(self, t, state):
return {"x": self.rate * state["x"]}
composite = Composite(
processes={"decay": Decay(), "growth": Growth()},
topology={"decay": {"x": "pool/x"}, "growth": {"x": "pool/x"}},
semantic_validation=True, # optional unit/semantic checks
)
result = Scheduler().run(composite, t_span=(0.0, 100.0), macro_dt=1.0, save_dt=1.0)
print(result.get("pool/x").shape)
Workflow
- Find —
simulate find <query>: search the repositories for a deposit that emits what you need;simulate find-data <query>does the same for a time course to calibrate against, across GEO, ArrayExpress, PRIDE, MetaboLights, Metabolomics Workbench, the BioImage Archive and Zenodo, reading each hit's arms and timepoints from its sample titles;--compositekeeps the hits that measure something your composite carries, and--paperlists a paper's own data. When nothing is deposited,simulate discover <topic>finds the papers and the code they link.simulate censusmeasures how much of BioModels, curated and uncurated, clears the gate at all and keeps the stamped verdict table underresults/census/;simulate census-datadoes the same for the data repositories: every deposited time course, and which screened models it could score. - Screen —
simulate screen <id-or-path>: triage and the numerical screen of that one model on its own. Nothing joins a composite unscreened. - Import —
process_from_sbml/process_from_xpp, thenreconciled_toto put it on the composite's clock. - Compose —
Compositewith a topology;analyze_composabilitywhere two models overlap. - Calibrate —
CalibrationProblemwith held-out arms
Demos & tests
simulate demo --help lists examples: framework mechanics on
toy processes, and one case study that composes three published SBML
models and calibrates them against GSE248823 (simulate demo multi-hallmark run; the first run fetches the dataset).
simulate view module:name serves any composite as a page: levers over
its handles and its wiring with a signal trace; --bake DIR writes the
levers as a static site instead.
make test runs the unit suite.
What you can do with it
- Compose published models. Search BioModels, JWS Online, ModelDB, BioSimulations, Physiome and Europe PMC supplements from one call, filtered by what a deposit emits; import SBML, COPASI
.cpsor XPPAUT.ode. - Pull a perturbation handle. A named, differentiable severity that moves the right parameters across models. The demos ship the hallmarks of aging as one registry on their models; a drug or a gene dosage is another entry, applied the same way.
- Calibrate against data. Gene-reporter concordance, log2-fold-change loss, MAP priors, differentiation through the stiff solve.
- Run batched population studies. A
(batch, n_vars)y0flows through the solve as one computation — novmapto write.
License
MIT.
References
If you use hallsim, please cite our paper: https://doi.org/10.64898/2026.09.22.753641
Release files for hallsim 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| hallsim-0.1.0.tar.gz | 3.1 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| hallsim-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 4.9 MB
Release files / hallsim-0.1.0.tar.gz
| Download URL | hallsim-0.1.0.tar.gz |
|---|---|
| Size | 3.1 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
792b7cfd636720c25e4cf5fc8a7117f64c5dcda3d4e53ca633b502ef71446377
|
|
BLAKE2b-256 checksum How to use checksums |
7a172c1255ed4af64d3af0ad226c72bd14f30205f58cc69ed0ba7a359d4f29c9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|
Release files / hallsim-0.1.0-py3-none-any.whl
| Download URL | hallsim-0.1.0-py3-none-any.whl |
|---|---|
| Size | 1.8 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2d9bb9c937f257180651382c1ee3de1a6c5e70824e749e79e5a554e274c7f706
|
|
BLAKE2b-256 checksum How to use checksums |
3730603334b5c3f22911c075164e432c7d9b482ad27f9542c57ac162285ea68b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.3
|