A fixed, reproducible protocol for porting R / Bioconductor packages to pure-Python py-<pkg> standalones, with cryptographic-grade numerical parity against the R reference.
π¨π³ δΈζη: README.zh.md
Single-cell genomics, statistical genetics, proteomics and adjacent fields have hundreds of canonical algorithms that exist only in R / Bioconductor: TSCAN, tradeSeq, Slingshot, DESeq2, edgeR, mclust, miloR, DoubletFinder, WGCNA, gsMap, condiments, β¦
When a Python user needs one of these, their options today are bad:
- Shell out via rpy2 / reticulate β adds R install + serialisation overhead + GPU-runtime fragmentation; agent workflows hate it.
- Use a "close-enough" Python alternative β silently a different algorithm with different statistical behaviour.
- Manually re-port β weeks to months of specialist effort; usually the result diverges from R and the divergence isn't measured.
Omicverse-RebuildR is the engineering recipe that takes a port from "I want this in Python" to "the wheel is on PyPI and provably matches R on the canonical fixture" β in a small number of agent-driven iterations, with the proof of parity shipped alongside the wheel.
Three core ideas:
- The R source is the executable spec. No reverse-engineering from papers. The agent runs the R reference on a fixed input and compares its own draft to that output, every iteration.
- Parity is class-aware. "Same output" means different things for an embedding (rotation-invariant), a clustering (label-permutation-invariant), or a pseudotime (correlation-invariant). The protocol pre-registers which numerical metric applies to which output and locks the threshold before any agent code is written.
- Reconstruction is not metric optimization. We never tune the algorithm to "look better" β we tune it to be identical to R, then search for speed under provably-equivalent algebraic rewrites.
What ships at the end of every port:
- A pip-installable wheel on PyPI.
- A
RECONSTRUCTION_REPORT.mdwith full R-function coverage audit, per-output parity values, two-panel time-vs-accuracy plot, and ecosystem-reuse accounting. - Three pre-executed notebooks: pipeline parity, Python tutorial, RβPython function dictionary.
- A reproducible parity gate as a pytest test.
# 1. Clone the kit
git clone <your-repo-url> omicverse-rebuildr
cd omicverse-rebuildr
# 2. Provision Python + R conda envs (see SETUP.md for full instructions)
conda create -n rebuild-py python=3.10 -y
conda activate rebuild-py
pip install -r requirements.txt
conda create -n rebuild-r -c conda-forge r-base=4.3 r-essentials -y
# 3. Export the two paths the kit needs
export PYTHON_TEST_ENV=$(conda info --envs | awk '/rebuild-py/ {print $NF}')
export R_TEST_ENV=$(conda info --envs | awk '/rebuild-r/ {print $NF}')
# 4. Authenticate GitHub CLI (needed for Discovery step)
gh auth login
# 5. Verify the kit installs cleanly (30 seconds)
python -m engine.smoke_test
# Expected: [smoke] OK -- 5/5 checks passed.
# 6. Check if your target R package is already ported
python -m engine.discover_omicverse_deps --check <YourRPackage>If the smoke test passes and the discovery says "no existing port", you're ready to start a port β follow PROTOCOL.md.
π Full setup walkthrough: SETUP.md (~30 minutes including conda env provisioning).
Point an agent (Claude Code, Cursor, etc.) at this folder and say:
Port R package X. Follow omicverse-rebuildr/README.md.
The agent will execute the 6-step protocol end-to-end and produce, at the end:
- a
omicverse/py-Xrepository (or under your$REBUILDR_ORG) with installable wheel, - the pre-registered numerical parity gate clearing on the canonical fixture,
- a structured
RECONSTRUCTION_REPORT.md, - three mandatory pre-executed notebooks (pipeline parity, Python tutorial, RβPython function dictionary),
- a PyPI release.
ββ 0.5 Discovery ββββββ
β β’ Is target already β β if YES: stop, reuse existing repo
β ported? β
β β’ Which R deps β β matches added to pyproject.toml as
β already have β hard / optional deps
β py-mirrors? β
βββββββββββββββββββββββ
β
ββ 1 Shape template βββ
β Copy layout from a β
β prior port matching β
β the algorithm class β
βββββββββββββββββββββββ
β
ββ 2 Dual envs ββββββββ
β Python target env β
β R reference env β
β Both see same data β
βββββββββββββββββββββββ
β
ββ 3 Two-agent inner loop ββββββββββββββββββββββββββββββββββββββββββββββ
β β
β ββ Equivalence Agent βββββ ββ Acceleration Agent βββββββββββββββ β
β β Translate R β Python β β β Search algebraic rewrites for β β
β β Iterate until parity β β speed; each requires admissibilityβ β
β β gate clears (Pearson, β β proof: exact / bounded-Ξ΅ / β β
β β ARI, Procrustes, etc.) β β class-containment. Reject if it β β
β β β β breaks parity. β β
β ββββββββββββββββββββββββββ βββββββββββββββββββββββββββββββββββββ β
β β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
ββ 4 Validate βββββββββ
β Re-confirm gate. β
β Threshold is read- β
β only; never widened β
βββββββββββββββββββββββ
β
ββ 5 Release ββββββββββ
β Publish to PyPI + β
β GitHub. Become a β
β seed template for β
β the next port. β
βββββββββββββββββββββββ
Each step is documented in detail:
| Step | What happens | Document |
|---|---|---|
| 0.5 Discovery | Check whether the target itself is already ported; check whether each R dep already has a py-mirror under github.com/<org>. STOP if duplicate; reuse deps as pyproject.toml deps if found. |
DISCOVERY.md |
| 1 Shape template | Copy directory layout + test scaffold from a prior port (e.g., py-DoubletFinder for classification, py-monocle2 for ordinal). Do NOT copy algorithmic code. |
TEMPLATE.md |
| 2 Dual environments | Provision a Python target env (Python + in-progress port) and an R reference env (R 4.x + Bioconductor + upstream reference). Both see the same fixture files. | SETUP.md |
| 3 Two-agent inner loop | (a) Equivalence Agent: translate R β Python, iterate until the pre-registered class-aware parity gate clears. (b) Acceleration Agent: verifier-guided test-time search over algebraic rewrites for speed, each requiring one of three admissibility proofs. | PROTOCOL.md, PARITY_TAXONOMY.md, ACCELERATION_PLAYBOOK.md |
| 4 Validate | Re-confirm the gate. The threshold is committed before agent work begins β never tightened or loosened. | PARITY_TAXONOMY.md |
| 5 Release | Ship the wheel to PyPI, publish the repo under github.com/<org>/py-X, complete the structured RECONSTRUCTION_REPORT.md + four mandatory notebooks. |
NOTEBOOKS.md |
Different algorithms have different invariance structures, so "same output" needs different metrics. The protocol pre-registers one class per port output:
| # | Class | Parity criterion | Default threshold | Example R packages |
|---|---|---|---|---|
| 1 | Deterministic numerical (3 sub-tiers β see PARITY_TAXONOMY.md) | element-wise max_abs_err < tol, optional rtol-scaled |
standard 1e-8 / strict 1e-13 / bounded 1e-6; hard ceiling 1e-6 |
BandNorm, scHiCluster kernels |
| 2 | Stochastic numerical | KolmogorovβSmirnov β€ Ο or Wasserstein-1 β€ Ο | KS-p β₯ 0.05 | MCMC draws, Bayesian posteriors |
| 3 | Combinatorial clustering | label-invariant: ARI / NMI / FowlkesβMallows | ARI β₯ 0.95 | mclust, scDblFinder, sc3 |
| 4 | Continuous embedding | rotation-invariant: Procrustes similarity | Procrustes β₯ 0.95 | Seurat CCA, PCA, UMAP, t-SNE |
| 5 | Ranked output | top-K Jaccard / Spearman correlation | top-50 Jaccard β₯ 0.8 | COSG markers, DE rankings |
| 6 | Ordinal output (pseudotime) | Pearson / Spearman correlation | Pearson β₯ 0.99 (β₯ 1 β 1e-12 treated as exact) |
Monocle 2, Slingshot, TSCAN |
| 7 | Classification | label agreement / F1 | F1 β₯ 0.95 | DoubletFinder, scDblFinder labels |
| 8 | Statistical inference | rank corr on βlog10 p + top-K Jaccard | Spearman β₯ 0.90 | miloR DA, limma, DESeq2, tradeSeq |
If the R function returns multiple outputs of different classes, the manifest declares one gate per output and ALL must pass.
The 8 metric implementations live in engine/parity_metrics.py β import from there rather than redefining.
π Full taxonomy: PARITY_TAXONOMY.md β includes "when the gate fails: ordered suspicion list" (off-by-one, transpose, log base, sparse-vs-dense, NA handling, β¦).
Every algebraic rewrite the Acceleration Agent commits must carry one of these proofs:
| Proof class | Meaning | Examples |
|---|---|---|
| (E) Exact identity | The rewrite produces bit-equivalent output by mathematical identity. | X^T X cached outside a loop; Woodbury (I + Ξ» U Ξ U^T)^{-1}; Schur complement; Cholesky vs LU. |
| (B) Bounded Ξ΅-approximation | The rewrite introduces an error bounded by a closed-form expression in some small Ξ΅; the bound is derived in MATH.md, not handwaved. |
Sparse soft-assignment via row truncation at Ξ΅ = 1e-12 (with βW_new β Wβ_F β€ ΞΊ n K Ξ΅); top-K kNN truncation of pairwise-distance matrix when downstream is local. |
| (C) Class-containment theorem | A known theorem guarantees the rewrite produces the same output for the relevant input class. | Euclidean MST β Delaunay triangulation (Preparata-Shamos 1985, Toussaint 1980); MST β relative-neighbourhood graph. |
π Full catalog: ACCELERATION_PLAYBOOK.md. The Acceleration Agent searches the playbook in a heuristic order; rejected rewrites are still logged for the per-port ITERATION_LOG.md.
Traditional evolutionary search plots iteration vs metric because the policy searches for better metric. That's the wrong model here β reconstruction's goal is identical output to the R reference, not "better" output.
So every port produces two plots against the same iteration axis:
wall-clock (s)
β
β βββ
β β βββ
β β ββββ
β baseline β iter 1 β iter 2 β iter 3 β iter 4
β
ββββββββββββββββββββββββββββββββββββββββββββββββββ iteration
parity metric (e.g. Pearson)
β ββββββββββββ
β \
β ββββ β annotated: "row truncation at Ξ΅=1e-12"
β β β β β β β β β β β threshold (red dashed line)
β
ββββββββββββββββββββββββββββββββββββββββββββββββββ iteration
- Plot 1 (top, log scale): wall-clock should monotonically decrease as rewrites land. Error bars = stddev over 3 warmup-excluded runs.
- Plot 2 (bottom): parity metric should stay flat at the ceiling. Every dip must be annotated with the math approximation that caused it.
Wall-clock measurement rules:
- Warmup: discard the first run (BLAS thread spin-up, Python imports, page cache).
- 3 measured runs in the same process; report mean Β± stddev.
- CV > 10% β auto-extend to 5 runs, report median + IQR.
- Fix BLAS threads via
OMP_NUM_THREADS=8etc. before any imports.
π Full spec + iteration-log schema: EVALUATION.md.
A finished port serves five audiences, each with a different need:
| Audience | What they need | Where they look |
|---|---|---|
| Reviewer / scientist evaluating whether to trust the port | Pipeline-level proof Python β‘ R numerically | compare_R_vs_Python.ipynb |
| End user new to the algorithm | A copy-pastable Python tour of every public function | tutorial_<dataset>.ipynb |
| R user porting their existing code line-by-line | A function-level dictionary β every R parameter β Python parameter, side-by-side calls on identical input | function_by_function_R_parity.ipynb |
| Auditor of the engineering process asking "did the agent really iterate, or did it skip the loop?" | A per-iteration narrative log with one named subplot per iteration | evolution.ipynb |
| CI / automation | The pre-registered parity gate as a pytest assertion | tests/test_exact_match.py |
All four notebooks ship pre-executed so GitHub renders them without re-running. Phase 4 of the protocol blocks the port from being released if any one is missing.
evolution.ipynb is a forcing function. It is structured as ## Iteration N β <title> headers, one per iteration, each with a markdown narrative of what was changed AND a code cell that produces a subplot for that iteration. If the agent performed 100 iterations, the notebook has 100 subplots; if it skipped the acceleration loop entirely, the notebook still has one block for the baseline (## Iteration 0 β Baseline translation) β but the protocol then audits whether obvious acceleration opportunities were missed.
The point is not to make the agent generate plots; the point is to make it impossible to ship without a written record of every iteration that touched the algorithm. The summary 2-panel examples/evolution.png (auto-generated from ITERATION_LOG.md by engine.plot_evolution) supplements but does not replace this notebook.
π Schemas + section-by-section requirements: NOTEBOOKS.md.
| File | What it does |
|---|---|
| SETUP.md | First-time install β prerequisites, two-env provisioning, env vars, gh auth, smoke test, troubleshooting. |
| PROTOCOL.md | The 6-step protocol + the two-agent inner loop. Read this in a session before starting a port. |
| DISCOVERY.md | Phase 0.5 β reuse before rebuild. Find existing org-mirror ports for the target and its R deps. |
| PARITY_TAXONOMY.md | 8-class algorithm taxonomy β which numerical-parity metric applies. |
| ACCELERATION_PLAYBOOK.md | Catalog of algebraic rewrites with the 3 admissibility proof types. |
| EVALUATION.md | Two-plot evaluation (time vs iter + accuracy vs iter), warmup excluded, accuracy dips annotated. |
| NOTEBOOKS.md | Three mandatory pre-executed notebooks per release. Non-skippable in Phase 4. |
| TEMPLATE.md | Standard py-<pkg> repo layout + naming conventions + license decision matrix. |
| CHECKLIST.md | Per-port checklist to tick through, Phase 0β5. |
| File | What it does | Typical invocation |
|---|---|---|
smoke_test.py |
30-second sanity check β verifies the kit installs and all 8 parity metrics + audit / plot / benchmark / loop helpers work. | python -m engine.smoke_test |
discover_omicverse_deps.py |
Lists existing org repos via gh repo list <org> (default omicverse, override with REBUILDR_ORG); parses R DESCRIPTION; reports which deps already have py-mirrors. Cached 24h. |
python -m engine.discover_omicverse_deps --check <RPkg> |
parity_metrics.py |
The 8 parity-class metric functions (Pearson, ARI, Procrustes, KS, top-K Jaccard, β¦) + class dispatcher. | from parity_metrics import compute_parity, is_pass |
benchmark.py |
Wall-clock timer with warmup-exclusion + 3-run averaging; auto-extends to 5 runs + median when CV > 10%. | from benchmark import time_callable |
r_function_audit.py |
Parses R NAMESPACE + R/*.R, audits Python coverage, produces AUDIT.md. |
python -m engine.r_function_audit --r-source <pkg>-ref --py-package <pkg> |
plot_evolution.py |
Renders the two-panel evolution PNG from ITERATION_LOG.md, annotates accuracy dips with their math reason. |
python -m engine.plot_evolution --port-dir <path> |
loop.py |
The Omicverse-RebuildR loop as runnable code β equivalence + acceleration phases as Python callables. | python -m engine.loop --port-dir <path> --phase equivalence |
manifest.template.yaml |
Pre-registered parity gate spec β copy into each new port's data/manifest.yaml. |
(file template) |
Every new port copies these as starting scaffolding; nothing is generated from scratch.
| Template | Becomes |
|---|---|
pyproject.template.toml |
The port's pyproject.toml (build + deps + metadata) |
README.template.md |
The port's user-facing README.md |
r_reference_driver.template.R |
tests/r_reference_driver.R β invokes the R package, dumps JSON |
_run_candidate.template.py |
tests/_run_candidate.py β invokes the Python port, dumps JSON |
test_exact_match.template.py |
tests/test_exact_match.py β pytest test that asserts the gate |
DISCOVERY.template.md |
The port's DISCOVERY.md artefact (Phase 0.5) |
ITERATION_LOG.template.md |
The port's ITERATION_LOG.md (Phase 3 acceleration log) |
RECONSTRUCTION_REPORT.template.md |
The port's RECONSTRUCTION_REPORT.md (8-section final report) |
compare_R_vs_Python.template.ipynb |
Notebook 1 β pipeline parity |
tutorial.template.ipynb |
Notebook 2 β Python tutorial |
function_by_function_R_parity.template.ipynb |
Notebook 3 β RβPython function dictionary |
r_per_function_dump.template.R |
R driver feeding Notebook 3 |
| File | What it does |
|---|---|
| ROADMAP_TRAJ.md | Ranked trajectory-inference R packages awaiting ports (TSCAN β , tradeSeq, destiny, URD, SCORPIUS, condiments, β¦) with citation counts + cites/year. |
| EXAMPLE_WALKTHROUGH.md | TSCAN end-to-end walkthrough β Phase 0 β Phase 5 narrative with concrete commands and intermediate outputs. |
A typical agent session opens with:
Port R package X. Follow omicverse-rebuildr/README.md.
The agent then executes:
- (Phase 0.5 β Discovery) Run
engine/discover_omicverse_deps.pyto check:- Is
omicverse/py-X(or<your-org>/py-X) already published? β if yes, STOP, report the existing repo. - Which of X's R deps already have py-mirrors? β record matches in
DISCOVERY.md, add topyproject.toml.
- Is
- (Phase 0) Look up X's algorithm class in
PARITY_TAXONOMY.md. Write and commitdata/manifest.yamlwith the algorithm class, threshold, canonical fixture path, seed, and per-output gate blocks. The gate is read-only after this. - (Phase 1) Copy the layout from
TEMPLATE.md(seed shape chosen by algorithm class β e.g.,py-monocle2for ordinal trajectories). - (Phase 2 β Equivalence Agent) Translate each R function in dependency order. After each function, run the per-function parity diff. Iterate until the top-level gate clears at the pre-registered threshold.
- (Phase 3 β Acceleration Agent) For each candidate rewrite from
ACCELERATION_PLAYBOOK.md:- Check precondition + produce admissibility proof (E / B / C).
- Apply on a working branch; re-run parity test (gate still clearing?); re-benchmark.
- Accept if speedup > 1.05Γ and gate clears; else roll back.
- Append one YAML block to
ITERATION_LOG.mdper attempt.
- (Phase 4 β release artefacts) Tick
CHECKLIST.mdend-to-end; produce all mandatory deliverables:RECONSTRUCTION_REPORT.md(8 sections, populated from per-phase artefacts)MATH.md(perturbation bounds for any (B) rewrites)AUDIT.md(R-function coverage, auto-generated byengine.r_function_audit)examples/evolution.png(two-panel time + accuracy plot, auto-generated byengine.plot_evolution)examples/compare_R_vs_Python.ipynbβ pipeline parityexamples/tutorial_<dataset>.ipynbβ Python-only function tutorialexamples/function_by_function_R_parity.ipynbβ RβPython function dictionaryexamples/evolution.ipynbβ per-iteration narrative + subplot (one block per iteration; forces the agent to record what each iteration did)
- (Phase 5 β release) Build wheel, push to PyPI; create GitHub repo + release; add the port as a seed template for future ports.
Always-first invariant: Phase 0.5 (Discovery) is non-skippable. If discovery is skipped, the protocol fails β we risk re-implementing upstream work that already exists. The TSCAN port saved ~3000 LOC of Mclust code by finding py-mclustR mid-port; the next port should hit that win at Step 1, not by accident.
No deferred items in Phase 4: every artefact above is mandatory. The TSCAN-v0.1 port deferred Notebooks 1 + 2 and shipped without; v0.2 added them retroactively; v0.3 added Notebook 3. The protocol now blocks all three from being skipped.
Use this kit when:
- β The target is an R / Bioconductor package with a clear numerical output (vector, matrix, table, cluster IDs, p-values).
- β You can construct a canonical input fixture small enough for fast iteration (< 1 minute end-to-end for the R reference).
- β The upstream R package is open-source under a permissive or copyleft license you can match.
- β You're prepared to commit time on the order of 1β5 working days for a clean port (less for class A, more for class C with acceleration).
Don't use it when:
- β The "R package" you want is closed-source or only described in a paper without runnable code β no executable spec means no parity oracle.
- β The algorithm depends critically on R-only C++ extensions or S4-heavy Bioconductor classes β the protocol works on functional algorithms, not framework-coupled ones.
- β You want a Python algorithm that's better than R, not identical. This kit refuses to widen the gate; if you want to improve the algorithm, fork after the port lands.
- β You're targeting GPU-only kernels with no CPU reference β the parity oracle won't have anything to compare against.
The acceleration loop is verifier-guided test-time search, not weight-update RL β and importantly not metric optimization:
| Component | Mapping |
|---|---|
| Policy | The LLM in-context (no fine-tune, no weight updates). |
| Action | One algebraic rewrite drawn from ACCELERATION_PLAYBOOK.md (Woodbury, Xβ€X memoisation, sparse-row truncation, MST β Delaunay, β¦). |
| Environment | The parity test + a 3-run-mean stopwatch on the canonical fixture (see EVALUATION.md). |
| Reward | r_t = Ο(a_t) Β· speedup(a_t) β gate must still clear (Ο = 1), then wall-clock speedup ranks admissible candidates. |
| Best-so-far register | The last commit on the in-progress port. Roll back if a later rewrite breaks parity. |
What we don't do: improve the algorithm's biological metric. Reconstruction's goal is identical outputs to the R reference, not "better" ones. Two evaluation plots come out of every port:
time vs iterationβ monotonically decreasing as rewrites land.accuracy vs iterationβ flat at the maximum; every dip annotated with the math approximation that caused it.
No model weights change. Search occurs inside one coding-agent session, with the parity test as oracle and the wall-clock as cost function.
After the parity gate clears and the Acceleration loop terminates, the agent fills out RECONSTRUCTION_REPORT.md. The 8 sections:
- Identity β package, upstream version, algorithm class, threshold, final parity value, audit class A/B/C, LOC, speedup vs R.
- R function coverage audit β every exported R function from
NAMESPACEis in the table (ported / skipped with reason). Auto-populated byengine.r_function_audit. Also lists dependencies reused from omicverse (ecosystem audit β how many LOC saved by reusing upstream py-mirrors). - Parity evidence β per-output metric values, per-fixture wall-clock + parity, reproducible reference command.
- Acceleration evidence β two-panel evolution figure embedded, accepted-vs-rejected rewrites with admissibility proofs.
- Code quality audit β
pip install+pytestgreen + four mandatory notebooks executed + license compatible + version pinned. All non-skippable. - Known limitations β honest list of what the port doesn't do; never used as an excuse to widen the gate.
- Integration into omicverse β vendor location, public-API exposure, tutorial slot.
- Sign-off β author, date, active time spent, final audit class.
This is what we present as "the port is done".
The protocol grew by patching anti-patterns surfaced during real ports. Each version maps to a real port's failure mode; the kit grows by closing them, not by speculation.
| Version | What changed | Why |
|---|---|---|
| v1 | Initial 5-step protocol + parity-class taxonomy + acceleration playbook | Reference-driven cross-language synthesis baseline. |
| v2 | Added EVALUATION.md (two-plot eval, warmup-excluded timing) + ITERATION_LOG.md + structured RECONSTRUCTION_REPORT.md |
User clarified that reconstruction is "preserve accuracy, search for speed" β not metric optimisation. |
| v3 | Added DISCOVERY.md (Phase 0.5) + engine/discover_omicverse_deps.py |
py-TSCAN discovered py-mclustR mid-port by luck; protocol now forces this check at Step 1. |
| v4 | Added NOTEBOOKS.md β two mandatory notebooks (compare_R_vs_Python, tutorial_<dataset>) |
py-TSCAN-v0.1 deferred them and shipped without; v0.2 added them retroactively. |
| v5 | Added Notebook 3 (function_by_function_R_parity) β RβPython parameter dictionary |
The first two notebooks didn't cover R users line-by-line porting their own code. |
| v6 | Genericised env names (PYTHON_TEST_ENV / R_TEST_ENV) + REBUILDR_ORG env var + SETUP.md + engine/smoke_test.py + requirements.txt + portable-paths sweep |
Portability audit surfaced that a second user couldn't clone-and-go without grepping the kit for hardcoded paths. |
| v7 (now) | Added Notebook 4 (evolution.ipynb) β per-iteration narrative + subplot, one block per iteration |
Audit of nine shipped ports surfaced that 8/9 had no evolution.png and no ITERATION_LOG.md. The summary plot was easy to skip silently; the per-iteration notebook makes skipping it visible (a missing notebook is louder than a missing PNG). The notebook is a forcing function: every iteration that touched the algorithm must have a named section. |
See examples/ROADMAP_TRAJ.md for the full ranked trajectory-inference list.
| Status | Port | Date | Audit | Speedup | Notes |
|---|---|---|---|---|---|
| β | py-monocle2 | 2026-04 | C | 102Γ | MST β Delaunay + Woodbury + Xβ€X cache + sparse R |
| β | py-mclustR v0.2.0 | 2026-05 | A | β | Fixed Fraley 1998 hcVVV bug surfaced by TSCAN |
| β | py-TSCAN | 2026-05 | A | ~28Γ | Class A + 3 notebooks + full discovery + reuse of py-mclustR |
| β¬ next | py-tradeSeq | β | TBD | TBD | Highest cite density (~152/yr); DE-along-trajectory companion to Slingshot |
| β¬ | py-destiny | β | TBD | TBD | Canonical DPT reference |
| β¬ | py-URD | β | TBD | TBD | Branching developmental trees |
| β¬ | py-SCORPIUS | β | TBD | TBD | dynbenchmark linear-trajectory winner |
| β¬ | py-condiments | β | TBD | TBD | Multi-condition trajectory comparison (Nat Commun 2024) |
Q: How long does a typical port take? A: Class A (translation-only): 1β3 days. Class B (minor optimisation): 2β5 days. Class C (major algorithmic restructuring with acceleration): 1β2 weeks. py-TSCAN was a class A done in ~6 hours; py-monocle2 was a class C done in ~2 weeks.
Q: What if my target R package has no Python equivalent in scipy / sklearn / pygam for its dependencies?
A: Either (a) port that dep first (and add it to the ecosystem) or (b) document it as "out of scope, deferred to a future minor release" in the reconstruction report. The TSCAN port did (a) for mclust (became py-mclustR) and (b) for ggplot2 (plotting deferred to v0.2).
Q: Can I publish to a different GitHub org?
A: Yes. Export REBUILDR_ORG=<your-org> before running engine.discover_omicverse_deps. The kit doesn't push anything anywhere automatically β Phase 5's gh repo create and twine upload are explicit and you control where they go.
Q: Does this work on Windows? A: Tested on Linux; macOS should work. Windows requires WSL2 because the kit shells out to bash for some pipe operations.
Q: What if R Mclust / R rand / R any-stochastic function gives different results on my machine? A: That's why the manifest pins a seed AND the class taxonomy degrades to distributional metrics (KS / Wasserstein) for stochastic outputs. If you're seeing platform-specific divergence beyond what KS allows, file an issue on the upstream R package β that's a non-determinism bug in R, not in your port.
Q: My port's difftest p-values don't match R because pygam β mgcv. What now?
A: Honest answer (see py-TSCAN Notebook 3): GAM implementations have meaningfully different fits at small df. Document it in MATH.md, switch to Spearman-on--log10(p) + top-K Jaccard as the inference-class metric, and call it out as a known limitation in the reconstruction report. Never widen the gate to make the p-values "pass" element-wise.
Q: What happens if my Acceleration Agent rewrite gets a 1.2Γ speedup but breaks Pearson from 1.0000 to 0.9970, still above the threshold? A: Reject. The accuracy is allowed to dip ONLY for (B) bounded-Ξ΅ rewrites where the perturbation bound is derived in closed form. A "small" empirical accuracy drop with no closed-form bound is a bug, not an optimisation.
The kit itself is MIT. Each individual port matches its upstream R package's license (GPL-3 if upstream is GPL β₯ 2; MIT if upstream is MIT / BSD / Apache; etc.). See TEMPLATE.md Β§License decision matrix.
This protocol distils experience from porting ~10 canonical bioinformatics R / Bioconductor packages to Python under reference-driven parity gates. The reference for the underlying methodology is the "PolyPort" recipe (reference-driven cross-language library synthesis via LLM agents). All case-study ports live under github.com/omicverse/py-*; this folder factors out the recipe so each subsequent port follows the same engineering loop without re-deriving it from scratch.