µODE
An ODE-based simulation engine for microbial community dynamics, built directly from metagenome-assembled genomes.
µODE (pronounced micro-O-D-E) takes you from compositional metagenomics — knowing who is in a sample — to functional, predictive systems biology — knowing what the community does and how it changes over time. It reconstructs genome-scale metabolic models from MAGs, couples them through a shared extracellular pool, and integrates the whole community forward in time with dynamic Flux Balance Analysis (dFBA).
On top of the metabolic core, µODE layers the chemistry and ecology that actually shape a gut community — pH and short-chain-fatty-acid inhibition, bile-acid transformation, sporulation, antibiotic pharmacokinetics, bacteriocins, oxygen gradients, and bacteriophage predation — and runs bacteria, archaea, fungi and viruses through one engine.
Contents
- Why µODE
- Features
- Installation
- Quick start
- The pipeline
- Command-line interface
- Ecology and multi-kingdom modeling
- Inputs and outputs
- Mathematical framework
- Worked examples
- Documentation
- Citation
- License
Why µODE
Metagenomics tells you the roster of a community. It does not tell you how that roster behaves — who feeds whom, which species a perturbation will knock out, how an intervention propagates through the cross-feeding network. µODE closes that gap with a mechanistic, dynamic model assembled automatically from the genomes themselves:
- From genomes, not assumptions. Metabolic capabilities come from the MAGs. Interactions are emergent — cross-feeding, competitive exclusion and secondary extinctions arise from a shared metabolite pool, never from hard-coded rules.
- Dynamic, not static. A native dynamic-FBA integrator produces full time courses of biomass, metabolites and growth rates, not a single steady-state snapshot.
- Metabolism and ecology. A composable ecology layer adds the non-metabolic processes that govern real communities, so µODE can model colonization resistance, recurrence after antibiotics, and phage therapy — not just carbon flux.
- Runs anywhere. The core engine uses the free HiGHS solver and has no commercial-license requirement; a dependency-light backend runs the entire pipeline offline on any architecture.
Features
- Automated GEM reconstruction from MAGs: CarveMe (default, BiGG namespace) and gapseq (ModelSEED) for prokaryotes, a MetaEuk→CarveFungi route for fungi, and a dependency-free offline engine for portable runs.
- Kinetic parameterization: Michaelis–Menten uptake bounds ($K_m$, $V_{max}$) couple the intracellular linear program to the extracellular ODEs; GECKO-lite enzyme constraints cap intracellular velocities from $k_{cat}$, with an optional shared protein-pool budget that drives overflow metabolism. A built-in predictor assigns parameters with no external dependencies; deep-learning predictors (DLKcat, Kroll $K_m$) are available through the
mlextra. - Community dynamic FBA: a native Static-Optimization-Approach integrator solves community dynamics — cross-feeding, nutrient depletion, biomass growth — over a shared extracellular pool, with parallel per-species solves.
- Ecology layer: pH / SCFA inhibition, bile-acid transformation and secondary-bile-acid toxicity, sporulation and germination, time-varying antibiotic PK/PD, and bacteriocin antagonism — composable modifiers on top of the metabolic core.
- Multi-kingdom: bacteria, archaea, fungi and protists run through the same engine; oxygen-tolerance gating and facultative O₂ scavenging couple the kingdoms; bacteriophages enter as Levin–Stewart infection ODEs.
- Perturbations and interventions: antibiotic pathway attenuation, reaction knockouts, species removal, and timed biomass injection (fecal microbiota transplant, probiotic dosing) — all producing emergent community responses.
- Spatial dynamic FBA: a 2D reaction–diffusion colony/biofilm engine that resolves spatial cross-feeding gradients.
- Validation and interoperability: a benchmark framework that scores a run against known expectations (relative-abundance error, metabolite error, cross-feeding-edge F1), a self-contained HTML report, and a COMETS export bridge for independent cross-validation.
- Scale: a Snakemake workflow that fans reconstruction out per MAG (quality-control gating and a SLURM profile included) and abundance-aware subsampling for large communities.
Installation
µODE's core engine runs on the free, open-source HiGHS solver — no commercial license required. Gurobi or CPLEX are drop-in alternatives for very large communities.
Prerequisites: Python 3.10+, Conda or Mamba. (Optional: a Gurobi/CPLEX academic license for large-scale FBA.)
git clone https://github.com/cumbof/muODE.git
cd muODE
# Create and activate the environment (core engine, CLI, workflow driver)
mamba env create -f environment.yml
conda activate muode
# Install the package
pip install -e .
# Verify
muode demo
The external per-phase tools (CarveMe, CheckM2, gapseq, CarveFungi) are provisioned automatically by Snakemake from workflow/envs/ when you run with --use-conda.
Quick start
The built-in two-species cross-feeding simulation runs immediately, with only numpy and scipy:
muode demo --outdir results/demo
A_glucose ferments glucose and secretes acetate; B_acetate grows only on that acetate. B blooms after A has produced its substrate — the canonical cross-feeding motif. Remove the feeder and watch the dependent species go secondarily extinct:
muode demo --outdir results/demo_ko --remove A_glucose
The pipeline
µODE orchestrates a phased, reproducible pipeline from raw MAGs to a dynamic community simulation.
Phase 0 — MAG quality control. CheckM2 gates MAGs on completeness and contamination before any modeling effort is spent. Controlled by run_checkm2; when disabled, all MAGs pass.
Phase 1 — Network reconstruction. Genes are called with Prodigal/Pyrodigal (prokaryotes) or MetaEuk (eukaryotes). CarveMe is the default reconstructor (BiGG namespace, consistent across MAGs, which a shared community pool requires); gapseq is available as an alternative (ModelSEED namespace), never mixed with CarveMe in one community. Domain-aware routing (muode.traits.reconstruction_route) sends bacteria and archaea to CarveMe, fungi to MetaEuk + CarveFungi, other eukaryotes to a MetaEuk + eggNOG/ModelSEEDpy draft, and viruses to the ecology layer as PhageInfection models rather than GEMs.
Phase 2 — Gap filling. A minimal-cardinality LP gap-fill (cobra) ensures every model can produce biomass on a defined medium. MetaPathPredict can optionally flag probable KEGG modules in incomplete MAGs.
Phase 3 — Kinetics. $K_m$ and $V_{max}$ constrain substrate uptake through Michaelis–Menten bounds — the coupling between the intracellular LP and the extracellular ODEs. $k_{cat}$ constrains intracellular velocities through enzyme-constrained (GECKO-lite) bounds, with an optional shared protein-pool budget that forces the cell to allocate a finite enzyme mass between pathways. The default predictor is dependency-free; DLKcat and Kroll $K_m$ predictors are available through the ml extra.
Phase 4 — Community simulation. A native Static-Optimization-Approach integrator (Mahadevan et al., 2002) updates extracellular concentrations and per-species biomass at each time step, with species interacting through one shared extracellular pool under a defined diet. A MICOM/cobra community model can serve as the per-step solver; COMETS is supported as an export target for independent cross-validation.
Phase 5 — Perturbation, intervention and ecology. Antibiotic pathway attenuation, reaction knockouts, species removal and timed biomass injections (FMT, probiotics) drive the run; the ecology layer adds pH, bile, spores, antibiotic PK, bacteriocins, oxygen and phages. Secondary extinctions from disrupted cross-feeding emerge naturally.
Command-line interface
µODE exposes one subcommand per pipeline phase. Each step notes what it consumes and produces so the chain is unambiguous.
Try the engine immediately — no data needed:
muode demo --outdir results/demo
1. Build draft GEMs from MAGs. Consumes MAG FASTA files; produces one SBML model per MAG.
muode build --mags ./data/raw_mags/ --outdir ./models/draft_gems/ --engine carveme
For dozens to thousands of MAGs, use the Snakemake workflow: it fans reconstruction out per MAG with CheckM2 gating and domain-aware routing.
2. Gap-fill and predict kinetics. Consumes draft GEMs; produces gap-filled GEMs and one {stem}.kinetics.json per model.
muode refine --models ./models/draft_gems/ --outdir ./models/kinetic_gems/ --predict-kinetics
# deep-learning kinetics (needs the `ml` extra):
# muode refine ... --predictor dlkcat
3. Assemble the community. Consumes gap-filled GEMs and an abundance TSV; produces community.json, consumed by all downstream commands.
muode assemble \
--models ./models/kinetic_gems/ \
--abundance ./data/abundance.tsv \
--diet western_gut \
--outdir ./simulation_env/
The abundance TSV is a simple 2-column file (mag_id, rel_abundance) produced by whatever profiler you ran — MetaSBT, Bracken, Kraken2, mOTUs, MetaPhlAn, or a manual estimate. µODE is agnostic to how the sample was profiled; the TSV is the interface. Omit it for equal abundance. For large communities, subsample by abundance:
muode assemble ... --coverage 0.95 # fewest top MAGs covering 95% of abundance
muode assemble ... --max-species 100 # at most 100 MAGs
muode assemble ... --min-abundance 0.001 # drop anything below 0.1%
4. Run the dynamic simulation. Consumes community.json; produces biomass.csv, metabolites.csv, growth_rates.csv, cross_feeding.csv and figures.
# basic simulation:
muode simulate --community ./simulation_env/community.json \
--time 24 --step 0.1 --outdir ./results/
# with predicted kinetics, GECKO-lite enzyme constraints and a protein-pool budget:
muode simulate --community ./simulation_env/community.json \
--kinetics ./models/kinetic_gems/ --enzyme-constraints --protein-pool 0.2 \
--time 24 --step 0.1 --outdir ./results/
# transplant a donor community mid-run (FMT) at t = 24 h:
muode simulate --community ./recipient_env/community.json \
--inject ./donor_env/community.json --inject-time 24 \
--time 96 --step 0.1 --outdir ./results_fmt/
5. Validate against a known community. Consumes a results directory and a benchmark YAML.
muode validate --results ./results/ \
--expected examples/benchmarks/toy_cross_feeding.yaml
6. Spatial (colony / biofilm) simulation. Standalone; runs the built-in cross-feeding community on a 2D reaction–diffusion grid.
muode spatial --nx 24 --time 12 --outdir ./results/spatial/
7. Report and COMETS export.
muode report --results ./results/ # one self-contained report.html
muode export-comets --community ./simulation_env/community.json --outdir ./comets_run/
Run the whole pipeline with Snakemake (recommended for many MAGs):
conda activate muode
snakemake --use-conda --cores 8 --configfile config/config.yaml
A dependency-free configuration runs the entire DAG (reconstruct → refine → QC → assemble → simulate) offline, on any architecture, with no external tools:
snakemake --cores 4 --configfile config/config.demo.yaml
Ecology and multi-kingdom modeling
The dFBA core models metabolism. Real communities are also shaped by chemistry, pharmacology, antagonism, dormancy and predation, which µODE adds as composable ecology layers (muode.ecology.EcologyModel). An empty model is a strict no-op — numerically identical to the bare engine.
| Layer | Models | Module |
|---|---|---|
WeakAcidInhibition |
pH dynamics and undissociated-SCFA toxicity (self-limiting fermentation; colonization resistance) | muode.ph |
BileAcidTransform + BileAcidInhibition |
BSH and 7α-dehydroxylation of the bile pool; secondary-bile-acid growth inhibition | muode.bile |
SporeForming |
vegetative↔spore life cycle; spores survive antibiotics and germinate on a bile germinant | muode.lifecycle |
Antibiotic |
one-compartment PK and Emax kill on vegetative cells | muode.antibiotic |
Bacteriocin |
diffusible-toxin interference competition | muode.antagonism |
OxygenSensitivity |
O₂-tolerance growth gating and facultative O₂ scavenging | muode.oxygen |
PhageInfection |
Levin–Stewart lytic/temperate predation, coupled to host biomass | muode.phage |
Multi-kingdom. µODE's core is paradigm-defined, not taxon-defined: any GEM satisfying the OrganismModel interface — bacterial, archaeal, fungal or protist — simulates with the same code. What differs between kingdoms is the reconstruction tooling (Phase 1 routing) and the oxygen relationship (the OxygenSensitivity layer). Phages have no metabolism, so they are infection ODEs rather than metabolic species. See docs/ecology.md and docs/kingdoms.md.
Inputs and outputs
Inputs
- Genomes:
.fasta/.fnaMAG files, one per bin. - Abundance profile: a 2-column TSV (
mag_id,rel_abundance). Any upstream profiler works; omit it for equal abundance. - Traits (optional): a side file (
mag_id,domain,oxygen) carrying kingdom and oxygen relationship, keeping the abundance TSV a plain 2-column file. - Diet / medium: a preset name (e.g.
western_gut) or a CSV of metabolite concentrations (mmol/L) with an optional influx column.
Outputs
- Metabolic models: standard SBML (
.xml) / JSON per species. - Time-course data:
biomass.csv,metabolites.csv,growth_rates.csv; with the ecology layer, alsoenvironment.csv(pH, drug, germination signal) andspores.csv. - Interactions:
cross_feeding.csv(producer → metabolite → consumer). - Visualization and report: stacked-area composition charts, metabolite trajectories, cross-feeding network graphs, and a one-file
report.html.
Mathematical framework
µODE implements dynamic Flux Balance Analysis through the Static Optimization Approach. Inside each cell, a pseudo-steady-state linear program maximizes the biomass objective $Z$:
$$ \text{Maximize } Z = c^T v $$ $$ \text{Subject to } S \cdot v = 0 $$ $$ v_{min} \leq v \leq v_{max} $$
where $S$ is the stoichiometric matrix and $v$ the flux vector. Outside the cell, the environment evolves by ODEs. For biomass $X_i$ and metabolite $M_j$:
$$ \frac{dX_i}{dt} = (\mu_i - \delta - D), X_i $$ $$ \frac{dM_j}{dt} = \sum_{i} v_{j,i}, X_i + \phi_j - D, M_j $$
Here $\mu_i$ is the growth rate of species $i$ (the LP objective value), $v_{j,i}$ the exchange flux of metabolite $j$ by species $i$, $\delta$ an optional death rate, $D$ a chemostat dilution rate, and $\phi_j$ a nutrient influx. At each step the substrate uptake bound is set by Michaelis–Menten kinetics, $v^{up}{j,i} = V{max},M_j/(K_m + M_j)$, capped so a step cannot over-deplete a metabolite. Ecology layers compose by multiplying growth/uptake factors and summing death/metabolite rates. See docs/engine.md and docs/ecology.md.
Worked examples
Each example ships a README.md, an abundance TSV, a config, a download_genomes.sh, and (where relevant) a dependency-light mechanistic_demo.py that runs anywhere.
| Example | What it shows |
|---|---|
examples/gut_western/ |
A dense Western-diet gut community: carbon competition and SCFA cross-feeding. |
examples/fmt_cdiff/ |
Fecal microbiota transplant for recurrent C. difficile: control and treatment differ only by a timed donor injection, and the full ecology stack (bile acids, spores, antibiotic PK, pH) reproduces the recurrence-vs-cure contrast. |
examples/multikingdom/ |
Bacteria + fungus + phage: dropping the fungus collapses the obligate anaerobe (oxygen), dropping the phage unleashes the pathobiont (predation) — both emergent. |
examples/strain_competition/ |
One species, three strains: on glucose the best grower excludes the rest; a colicin producer overturns it (interference); a private-niche strain coexists. |
examples/phage_therapy/ |
A lytic phage crashes a Klebsiella bloom and releases the resources a commensal needs (predation and resource-release emerge together). |
examples/benchmarks/ |
Benchmark-expectation YAMLs for muode validate. |
# run a mechanistic demo on any machine (no GEMs needed):
PYTHONPATH=$(git rev-parse --show-toplevel) python examples/multikingdom/mechanistic_demo.py
PYTHONPATH=$(git rev-parse --show-toplevel) python examples/strain_competition/mechanistic_demo.py
Documentation
Per-feature documentation lives in docs/:
| Document | Covers |
|---|---|
| engine.md | SOA integrator, solver abstraction, cross-feeding |
| reconstruction.md | CarveMe / gapseq / offline / eukaryote engines, gene calling, namespaces, gap-fill, CheckM2 |
| kinetics.md | Km/Vmax uptake, kcat enzyme constraints, protein-pool budget, predictors |
| assembly.md | Community manifest, abundance TSV, diet, subsampling |
| perturbation.md | Antibiotic / knockout / species-removal engine |
| injection.md | Timed biomass injection (FMT, probiotics) |
| ecology.md | pH/SCFA, bile acids, spores, antibiotic PK, bacteriocins, oxygen, phage |
| kingdoms.md | Fungi/protists, phages, archaea |
| validation.md | Benchmark framework, metrics, pass/fail report |
| spatial.md | 2D reaction–diffusion colony/biofilm engine |
| workflow.md | Snakemake pipeline, rules, config reference, SLURM |
| visualization.md | Static figures and the self-contained HTML report |
Citation
A manuscript describing µODE is in preparation. If you use µODE in your research in the meantime, please cite this repository:
@software{muode,
author = {Cumbo, Fabio},
title = {{µODE}: an ODE-based simulation engine for microbial community dynamics},
url = {https://github.com/cumbof/muODE},
year = {2026}
}
License
µODE is released under the MIT License. See LICENSE for the full text.
© 2026 Fabio Cumbo.
Metadata
Release files for muode 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 | |
|---|---|---|---|
| muode-0.1.0.tar.gz | 221.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| muode-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 377.4 kB
Release files / muode-0.1.0.tar.gz
| Download URL | muode-0.1.0.tar.gz |
|---|---|
| Size | 221.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4d17fa7df503da308be6db915a30d6252040781935d4af38b3d891456a3f58dd
|
|
BLAKE2b-256 checksum How to use checksums |
90230bddb1be99fa09382f6e8d3c5dd7f3869b030094b19f151c00d8703f9429
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency logRelease files / muode-0.1.0-py3-none-any.whl
| Download URL | muode-0.1.0-py3-none-any.whl |
|---|---|
| Size | 155.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4d5faed1a200b8130eb40d736dd118aa2de35eeb0baff67d394e3c62e2cce513
|
|
BLAKE2b-256 checksum How to use checksums |
452d0169d1fc8c3c54baa39f977cc6d26f21433ec076ac977bd6d06fc1ebd3b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.
Transparency log