17 libraries live on PyPI biobabel 1.1.0 →

The classics of bioinformatics,
in more than one tongue.

Scientific software gets locked in the language it was written in. A bridge like rpy2 lets an agent call an R tool; it does not let anyone extend or build on it natively — and the classics go unmaintained as their language and dependencies move on.

Bio-Babel rebuilds them natively in the target ecosystem, and ships each package with a machine-readable contract so an agent that has never seen it still calls it correctly. Nothing in that is specific to R, or to graphics. R → Python is where we are proving it: seventeen classics so far, each its own repository and its own caretaker.

“And the whole earth was of one language, and of one speech.” Genesis 11:1

17libraries stewarded
1,606contracted symbols
21public repositories
0runtime bridges

Why Babel

Translation became impossible.
That is the part we are fixing.

The punishment in the story was never difference — a field's diversity of thought is its wealth. It was that ideas could no longer travel. Bioinformatics lives a small version of that: a beautiful tool blooms on one side of the language line, and the half of the field on the other side can reach across for it at best — never build on it.

Locked in the source language

Callable from another language, but not natively extended or built upon. A bridge gets you the call and nothing more: you cannot write a new geom against a tool you reach through rpy2, and you cannot compose it with anything native. The tool is reachable and still stranded.

The behaviour is not in the signature

It is in the object system, the data containers, the numerical conventions, the ecosystem dependencies. Match every signature and a reimplementation will still run while silently diverging — or run correctly while sitting outside the idioms of the ecosystem it now belongs to.

Fidelity and usability are separate problems

The rebuild has to behave like the original. And an agent that has never seen it has to use it correctly. Neither implies the other — a faithful port whose API the model has to guess at fails just as hard. So every package ships a _biobabel/ contract alongside the implementation.

The Stack

One lineage, rebuilt from the ground up.

The visualization stack is the first worked example: R's grid → {gtable, scales} → ggplot2 chain and everything downstream of it, carried into pure Python on a Cairo backend. No matplotlib. Publication-quality output by construction — and one self-consistent API for an agent to reason about, instead of four.

Tier 1 · Foundation

The graphics engine itself

R's grid — viewports, grobs, units, the whole device model — reimplemented on Cairo, plus the scales transform/break/palette machinery and the gtable layout algebra. Everything above stands on these three.

  • grid_py261 symbols
  • scales226 symbols
  • gtable_py21 symbols

Tier 2 · Grammar

The grammar of graphics, whole

geoms, stats, scales, facets, coords, themes and guides — composed with +, exactly as in R. The largest single contract in the project, and the one an agent is most likely to hallucinate against.

  • ggplot2_py626 symbols · 18 concepts · 30 idioms

Tier 2–3 · Extensions

The ecosystem that grew on top

The extension packages that make R plots publication-ready: repelled labels, alluvial flows, independent scales, facet surgery, plot composition and the two heatmap standards of genomics.

  • patchworkcompose with | and /
  • complexheatmapannotated heatmap lists
  • ggrepel_pynon-overlapping labels
  • ggalluvialflow diagrams
  • ggh4xfacet & axis hooks
  • ggnewscalemultiple colour scales
  • pheatmapclustered heatmaps

Tier 2–3 · Analysis

The methods people actually cite

Single-cell trajectories, intercellular communication, CNV calling. These build their entire visualization layer on the tiers below — so a Monocle 2 trajectory plot renders like the R tutorial.

  • monocle2pyDDRTree · BEAM · pseudotime
  • monocle3AnnData-native trajectories
  • nichenetrligand → target modelling
  • tradeseqNB-GAM lineage DE
  • copykatCNV aneuploidy detection
  • ddrtreereversed graph embedding

The spire

What reaches the agent

Every tier below publishes a _biobabel/ contract through a Python entry point. biobabel discovers them and serves 12 read-only tools over MCP to PantheonOS, Claude Code, Codex and Continue. It runs no business logic and never executes code.

  • biobabelcontract registry + MCP server

How a library becomes agent-legible

  1. 01

    Port

    A controller drives coding agents through a 13-step workflow — preparation, implementation, validation. Implementation operates on the package, not the function: the whole export surface is resolved into a dependency graph and cut into slices, each built and tested only after the ones it depends on.

  2. 02

    Annotate

    An agent writes each package's _biobabel/ contract from that package's own source, never from a neighbour's. Seven deterministic checks gate it — among them that every public export is covered, and that each anti-pattern's detector fires on its own bad example and stays silent on the good one.

  3. 03

    Serve

    biobabel enumerates one Python entry-point group — no central registry — and serves what it finds as 12 read-only MCP tools. An agent sees exactly the packages the user has installed; a package without a contract is invisible.

The catalog

Seventeen classics, on PyPI today.

Each is its own repository, its own distribution, its own maintainer. Versions track the upstream R package — rgrid-python 4.5.3.post6 tracks R grid 4.5.3; a Python-side fix without an R bump becomes a PEP 440 .postN.

Foundation tier 1

rgrid-python

ports R grid  ·  imports as grid_py

R's grid graphics engine — viewports, grobs, units, the device model — reimplemented on a Cairo backend. The floor everything else stands on.

261 symbols v4.5.3.post6
Foundation tier 1

scales-python

ports R scales  ·  imports as scales

Breaks, labels, transforms and palettes. The scale machinery the grammar depends on, down to the tick-placement heuristics.

226 symbols v1.4.0.9000.post3
Foundation tier 1

gtable-python

ports R gtable  ·  imports as gtable_py

Layout tables of grobs — the skeleton a plot is assembled into: panels, axes, strips and guides.

21 symbols v0.3.6.9000.post1
Grammar tier 2

ggplot2-python

ports R ggplot2  ·  imports as ggplot2_py

The grammar of graphics, whole. geoms, stats, scales, facets, coords, themes and guides — composed with +, exactly as in R.

626 symbols v4.0.2.9000.post7
Extension tier 3

patchwork-python

ports R patchwork  ·  imports as patchwork

Compose plots into arbitrary layouts with |, / and insets. Alignment that actually respects the gtable.

29 symbols v1.3.2.9000.post1
Extension tier 3

complexheatmap-python

ports R ComplexHeatmap  ·  imports as complexheatmap

Annotated heatmaps, splits and heatmap lists — the de-facto standard for genomics figures.

103 symbols v2.25.3
Extension tier 2

pheatmap-python

ports R pheatmap  ·  imports as pheatmap

Pretty heatmaps with row/column clustering and annotation bars, built on the original grid model.

29 symbols v1.0.13.post1
Extension tier 3

ggrepel-python

ports R ggrepel  ·  imports as ggrepel_py

Text and label geoms that repel each other and the plot edges. The reason gene labels are readable.

11 symbols v0.9.8.9999
Extension tier 2

ggalluvial-python

ports R ggalluvial  ·  imports as ggalluvial

Alluvial diagrams and flow plots for categorical longitudinal data — clone tracking, fate mapping, cohort flows.

38 symbols v0.12.6
Extension tier 2

ggh4x-python

ports R ggh4x  ·  imports as ggh4x

Hooks into facets, axes and strips that the grammar does not expose on its own.

78 symbols v0.3.1.9000
Extension tier 2

ggnewscale-python

ports R ggnewscale  ·  imports as ggnewscale

Multiple independent colour and fill scales in a single plot, without fighting the guide system.

11 symbols v0.5.2.9000
Analysis tier 2

monocle2-python

ports R monocle 2.9.0  ·  imports as monocle2py

Single-cell trajectory inference — DDRTree, BEAM, pseudotime — with its entire visualization layer on the Bio-Babel stack. No matplotlib, no seaborn.

44 symbols v2.9.0
Analysis tier 2

monocle3-python

ports R monocle3  ·  imports as monocle3

AnnData-native trajectories, clustering and differential expression.

42 symbols v1.4.26.post1
Analysis tier 3

nichenet-python

ports R nichenetr  ·  imports as nichenetr

Ligand → target modelling of intercellular communication, with the prior networks intact.

56 symbols v2.2.1.1
Analysis tier 2

tradeSeq-python

ports R tradeSeq  ·  imports as tradeseq

NB-GAM trajectory-based differential expression along lineages.

9 symbols v1.13.12
Analysis tier 3

copykat-python

ports R copykat  ·  imports as copykat

CNV-based aneuploidy detection from scRNA-seq — separating tumour from stroma.

17 symbols v1.1.0.post1
Analysis tier 3

ddrtree-python

ports R DDRTree  ·  imports as ddrtree

Reversed graph embedding for principal-graph learning. The engine underneath Monocle 2.

5 symbols v0.1.6

Every library in the catalog is under active testing — APIs stabilizing, edges still being filed. Use it for verifiable work, and tell us when it is wrong.

Extensibility

Three components change with the language pair.

R → Python is the demonstration, not the definition. Carrying the toolkit to another pair means re-specifying three language-specific components — the steps, the scripts and the skills.

  1. 01

    The steps

    The 13-step spine keeps its order; the target adds what it needs. Python → C++ adds a sanitizer step, because undefined behaviour compiles and runs while looking correct.

  2. 02

    The scripts

    The target toolchain, automated: configure, compile and test the C++, verify the toolchain, generate the project and record state.

  3. 03

    The skills

    The target-language references: Python-to-C++ translation patterns, build and dependency handling, undefined behaviour and parity.

Python → C++ second pair

UMI-tools-cpp

ports Python umi_tools  ·  builds with CMake  ·  MIT

Seven subcommands — whitelist, extract, group, dedup, count, count_tab, prepare_for_em — and the dispatcher, rebuilt on a C++ core library.

tracks 1.1.7.dev53

The framework

A build side, a read side, and the contract between them.

Fidelity and usability are met by two agent-driven systems, coupled by the contract that each package carries: a build side that reconstructs the software, and a read side that serves its operating knowledge to the agent. Two of the three are not public yet.

Build side 01

bio-babel-toolkit

Drives coding agents through the 13-step workflow that reconstructs a package natively. A controller keeps state in a report tree on disk rather than in the model's context, so progress survives an agent losing it — and implementation is ordered by a dependency-graph partition, package-wide, instead of proceeding function by function.

Coming soon
The contract 02

bio-babel-annotator

Writes each package's _biobabel/ contract from that package's own source, in an isolated session that can never read a neighbour's. Seven deterministic checks gate the result, so coverage of the public surface cannot silently shrink and no detector ships without firing on its own bad example.

Coming soon
Read side 03

bio-babel-MCP

Assembles those contracts from every installed package through one Python entry-point group and serves them as 12 read-only tools over MCP. There is no central registry, and the server neither plans nor executes: an agent sees exactly what the user installed, and a package without a contract is invisible.

Open source ↗
grid_py/_biobabel/
├── __init__.py        # get_manifest() → PackageManifest
├── package.yaml       # identity · tier · class · foundation
├── skill.md           # the narrative, for the LLM
├── symbols/*.yaml     # 261 signatures + requires/writes/mutates
├── concepts/*.yaml    # 6 invariants, "for R users / for Python users"
├── idioms/*.yaml      # 15 verbatim runnable templates
├── anti_patterns/*    # 4 detectable mistakes + the correct form
├── templates/*.py     # real code that actually runs
└── detectors.py       # the AST (abstract syntax tree) checks, owned by the package
agent session
# the agent guesses — R muscle memory
grid.viewport(width=unit(0.5, "npc"))   ✗ silently wrong

# the agent asks first
biobabel.describe_symbol(pkg="grid_py",
                        symbol="Unit")
→ Unit(value, units) — class, not a function.
→ anti-pattern: unit_kw — lowercase unit() is R.

grid_py.Viewport(width=Unit(0.5, "npc")) ✓

12 read-only tools

All prefixed biobabel., all returning the same envelope, all served over line-delimited JSON-RPC on stdio. The server holds no business logic and never executes your code.

Discovery 8

  • list_packages
  • describe_package
  • list_workflows
  • describe_workflow
  • list_symbols
  • describe_symbol
  • list_templates
  • describe_template

Concept 3

  • describe_concept
  • list_idioms
  • describe_idiom

Validation 1

  • check_code — static AST scan

Hard invariants

  • Contract is mandatory. No _biobabel/, no registration. There is no reflection fallback and no degraded mode.
  • Entry points only. The registry never scans site-packages. The producer declares itself.
  • Never executes code. No exec, no subprocess, no eval. Running a snippet is the calling agent's job.
  • No silent degradation. Broken entry points, duplicate ids and unregistered detectors surface as explicit errors.
  • Domain knowledge stays with its owner. Core ships zero detectors; the package that owns the domain owns its AST checks.
bio-babel-MCP on GitHub ↗

Principles

01

Semantic parity, idiomatic surface

Behaviour trusts the reference; the API feels native to the target language. Not a line-for-line transliteration — a sibling.

02

No runtime bridges

No rpy2, no second interpreter, no R install. If you can pip install it, it works.

03

Validated against the origin

Every public function is checked against its reference — numerically where possible, visually where not. Divergence is a bug, not a feature.

04

Docs and stewardship, first-class

A port is alive when someone is learning it and someone is maintaining it. Every package has a caretaker, not just an author.

Community

Three ways in, in rough order of commitment.

  1. 01

    Tell us what is missing, or what is wrong

    Name a classic you wish existed on the other side, and the workflow that is painful without it. Better still, report a port behaving differently from its reference — that one belongs on the port's own repository. Divergence is a bug, and it is the most useful thing you can send us.

    Open an issue ↗
  2. 02

    Bring one over

    Tell us which classic you would like to help carry across and we will help you scope it — or simply start, in public. Rough drafts are welcome: the pipeline assists the draft, and what needs more hands is the review and the stewardship that follow it.

    Say hello ↗
  3. 03

    Adopt a package

    The scarcest resource here is not code, it is long-term maintainers. Every library is its own repository with its own caretaker; if one of them matters to your work, consider becoming that caretaker.

    Volunteer ↗

The classics, kept alive
in more than one tongue.