viva-munk
Multi-cell simulations with 2D physics, built on process-bigraph and pymunk.
Demos · Composite Gallery investigation
Goal
Provide a composable framework for simulating populations of growing, dividing cells with realistic 2D physics and shared chemical environments. Cells are modeled as capsule-shaped rigid bodies (pymunk segments) — or as multi-segment compound bodies that can flex and bend — that grow, divide, secrete particles, attach to surfaces, and interact physically through collisions and confinement. Concentration fields are modeled with a finite-difference diffusion process and coupled to cells through a per-tick exchange step. The framework uses the bigraph process architecture, making it easy to compose new cell behaviors, environmental structures, and analysis pipelines.
Default parameters are calibrated to E. coli proportions (~1 μm wide, ~2 μm at birth, ~4 μm at division, ~30–40 min doubling time).
Installation
Requires Python 3.11+.
pip install viva-munk
To use as a library:
from viva_munk import core_import
from process_bigraph import Composite
core = core_import() # registers viva_munk types and processes
# ... build a spec dict and run: Composite(spec, core=core)
Quick Start
Run the full experiment suite and generate the HTML report:
git clone https://github.com/vivarium-collective/Viva-munk.git
cd Viva-munk
pip install -e .[dev]
# Run all experiments and open the HTML report
python -m viva_munk.experiments.test_suite
# Run without auto-opening the browser
python -m viva_munk.experiments.test_suite --no-open
Architecture
viva_munk/
pymunk_agent_type.py # Custom PymunkAgent type with optimized dispatch
types/
positive.py # PositiveFloat / PositiveArray / Concentration / SetFloat
processes/
multibody.py # PymunkProcess — 2D physics (rigid + bending cells)
grow_divide.py # GrowDivide — exponential growth, division, mutation
pressure.py # Pressure — vectorized per-cell mechanical pressure
diffusion_advection.py # DiffusionAdvection — 2D field diffusion + advection
cell_field_exchange.py # CellFieldExchange — cell ↔ field uptake/secretion
secrete_eps.py # SecreteEPS — EPS particle secretion
remove_crossing.py # RemoveCrossing — remove cells past a boundary
plots/
multibody_plots.py # GIF rendering with phylogeny / pressure coloring
# and concentration-field heatmap overlays
experiments/
test_suite.py # Experiment registry, runner, HTML report generator
Processes
- PymunkProcess (Process): Manages the pymunk 2D physics space. Handles three kinds of agents — rigid segment cells, multi-segment bending cells (compound bodies linked by pivot joints + damped rotary springs), and circular particles. Syncs state to bodies, steps the physics with sub-stepping, applies damping/jitter, optionally enforces adhesion to a wall, and emits position/velocity/polyline deltas.
- GrowDivide (Process): Per-cell exponential mass growth. Optionally gated by a Monod factor on a local nutrient (
local[nutrient_key]) and inhibited by mechanical pressure (exp(-pressure / pressure_k)). When mass exceeds a threshold, the cell divides into two daughters along its axis; daughters can inherit mutated parameters and (for bending cells) a fresh straight polyline so they don't inherit the mother's pose. - Pressure (Step): Computes a per-cell mechanical pressure proxy from cell-cell and cell-wall overlap depths (vectorized via numpy). Written back to each cell's
pressurefield for downstream consumers. - DiffusionAdvection (Process): Explicit FTCS diffusion + upwind advection on a 2D
map[mol_id → array]field, with ghost-layer boundary conditions (periodic / neumann / dirichlet / dirichlet_ghost). - CellFieldExchange (Process): Couples
pymunk_agentcells to a 2D field map. Each tick it samples each cell's local field concentration intocell.local, and applies each cell'scell.exchangeamounts back into the corresponding field bin (Δconcentration = Δamount / bin_volume). - SecreteEPS (Process): Per-cell EPS particle secretion at a rate proportional to cell mass. Particles are placed on the cell surface and added to the environment. Optionally gated to attached cells only.
- RemoveCrossing (Step): Removes any cell whose position exceeds a configurable x/y boundary. Used to model the flow channel in mother-machine experiments.
Custom types
pymunk_agent is a Node-subclass type with hand-optimized apply/reconcile/realize/check dispatch (no per-field plum dispatch on the hot path). It carries the geometric and physical state of one cell (mass, radius, length, location, velocity, …) plus optional fields used by downstream processes (polyline, attached, pressure, local, exchange).
The viva_munk.types.positive module provides minimal PositiveFloat, PositiveArray, Concentration, and SetFloat types for the field state, accumulator-with-clamp semantics adapted from spatio-flux.
Experiments
The current registry (viva_munk/experiments/test_suite.py):
- daughter_machine — single cell grows in an open chamber with an absorbing right wall.
- mother_machine — narrow dead-end channels (~1.5 μm wide); cells grow vertically and are removed when they reach the flow channel.
- with_particles — cells grow in a chamber seeded with passive particles; cells push and rearrange them.
- attachment — adhesin-bearing cells attach to the bottom surface via PivotJoints; adhesins split between daughters at division.
- glucose_growth — cells on a 2D glucose field.
DiffusionAdvectionspreads glucose,CellFieldExchangeapplies cell consumption every tick, andGrowDividegates rate by Monod kinetics. Cells stop dividing once their local patch is depleted. - bending_pressure — multi-segment bending capsules grow into a colony.
Pressurecomputes mechanical pressure from neighbor / wall contacts andGrowDivideappliesexp(-pressure / pressure_k)inhibition. Cells visibly bend AND slow. - chemotaxis — twelve non-growing cells run/tumble up a static exponential ligand gradient in a long chamber. Each cell maintains a memory of its local concentration and modulates tumble rate as
λ = λ₀ · exp(-k · dc/dt). - inclusion_bodies — a colony grows while each cell accumulates an inclusion-body aggregate (size in nm, logistic growth toward an 800 nm plateau). Aggregation inhibits growth; at division the IB is transferred entirely to one daughter so the IB-free sibling out-grows the laden one. Cells are soft bending capsules and a
Pressurestep adds a second slowdown as the colony packs. Colored by IB size. - quorum_sensing — cells secrete a diffusible autoinducer into a shared 2D field; each cell reads its local concentration and switches to an "ON" state once density-dependent signal crosses a threshold, reproducing the population-density switch of quorum sensing.
test_suite.py runs each one, captures a GIF, a bigraph composition viz, and a serialized state JSON, and generates an HTML report (out/report.html) with timing, cell counts, descriptions, and embedded media.
Investigation: Composite Gallery
Every composite above is also packaged as a viva-superpowers workspace investigation —
composite-gallery — that gathers one
runnable study per composite so each mechanism can be run, visualized, and inspected on its
own. All nine studies re-run end-to-end on the current process-bigraph / vivarium-workbench stack.
- Interactive report: Composite Gallery investigation · full dashboard
- In the repo:
investigations/composite-gallery/and the per-composite studies understudies/
| Study | What it shows |
|---|---|
| attachment | Surface colonization: cells settle, adhere, and begin secreting EPS. |
| bending-pressure | Pressure-inhibited growth in multi-segment (bendable) cells. |
| biofilm | Emergent colony / biofilm architecture from many interacting cells. |
| chemotaxis | Run/tumble chemotaxis up an exponential attractant gradient. |
| daughter-machine | Lineages in an open chamber where cells crossing the right wall are removed. |
| glucose-growth | Growth coupled to a shared, diffusing nutrient field with local depletion. |
| inclusion-bodies | Protein-aggregate burden and asymmetric segregation at division. |
| mother-machine | Single-channel trapping: one cell per dead-end channel, progeny pushed into the flow channel. |
| quorum-sensing | Density-dependent autoinducer signaling: cells switch ON above a local threshold. |
Studies are managed with the viva-superpowers
/viva-* skills (/viva-workbench, /viva-investigation, /viva-study, /viva-report). The
verdict is honest about scope: all nine reproduce their published panel qualitatively;
quantitative calibration and pass/fail behavior tests are tracked as follow-ups in the
investigation.
Dependencies
- process-bigraph — bigraph process framework
- bigraph-schema — typed schemas (via process-bigraph)
- bigraph-viz — bigraph visualization
- pymunk — 2D physics engine
- numpy, matplotlib, Pillow, plum-dispatch
Releasing
Releases are cut from main via ./release.sh, which bumps the patch
version in pyproject.toml, commits + tags vX.Y.Z, pushes the tag, builds
sdist + wheel, and publishes to PyPI (token at ~/.pypi-token).
License
MIT — see LICENSE.
Metadata
Release files for viva-munk 0.0.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| viva_munk-0.0.6.tar.gz | 101.2 MB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| viva_munk-0.0.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 111.2 MB
Release files / viva_munk-0.0.6.tar.gz
| Download URL | viva_munk-0.0.6.tar.gz |
|---|---|
| Size | 101.2 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e8ba48a001418f355470ad430c45336b91f4c61ed71666021b919e8c8c445fd7
|
|
BLAKE2b-256 checksum How to use checksums |
e8eb5b8910876e9e81481489b4785f17789eb0e91f7ae143fe79ef0e755a2ce0
|
| 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 Sep 28, 2026.
Transparency logRelease files / viva_munk-0.0.6-py3-none-any.whl
| Download URL | viva_munk-0.0.6-py3-none-any.whl |
|---|---|
| Size | 10.0 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
86e29be590eb22ffdb65d72e4436f2c678b303a775ee3847310d9cd39bff7383
|
|
BLAKE2b-256 checksum How to use checksums |
9f6bdc49e0e1473114b92041eab5edca2e6ff22f7feffc7a684ad28606733159
|
| 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 Sep 28, 2026.
Transparency log