Skip to main content

engin-core

Open toolkit for fermentation scale-up: a mechanistic fed-batch simulator, a Gaussian-process titer model with conformally calibrated uncertainty, an active-learning next-batch recommender, and reproducible benchmarks. Built on mature libraries — scipy (integration), scikit-learn (GP), MAPIE (conformal) — with only the domain models hand-written.

Part of the engin-suite strain-to-scale monorepo.

Why

Most bioprocess optimizers give point predictions or intervals that quietly lie. The trap is easy to fall into: form a 90% interval from the model's uncertainty alone and assume normality, and it covers only ~55% of held-out runs — badly overconfident. engin-core forecasts titer with honest coverage and recommends the runs worth doing next.

Calibrated uncertainty is the whole point of the wedge: a scale-up decision needs P(hit $/kg target), not a number with no error bar.

Install

Not published to PyPI yetpip install engin-core will not find anything. Install from a checkout of the monorepo:

git clone https://github.com/enginbio/engin-suite
cd engin-suite
pip install -e "packages/engin-core[dev]"

Quickstart

import numpy as np
from engin_core import (
    simulate_unit, fit_gp, split_conformal_multiplier,
    recommend_batch, ard_importance, unit_to_physical,
)

rng = np.random.default_rng(0)
U = rng.random((120, 5))                       # unit-cube DoE (5 design knobs)
y = simulate_unit(U)                            # titer (g/L) from the simulator

tr, ca, te = slice(0, 70), slice(70, 100), slice(100, 120)
gp = fit_gp(U[tr], y[tr])                        # fit the GP titer model

# Calibrate a 90% interval on a held-out set (split conformal):
mc, sdc = gp.predict(U[ca])
q90 = split_conformal_multiplier(y[ca], mc, sdc, level=0.90)

mean, sd = gp.predict(U[te])                     # forecast: mean ± q90*sd is a 90% PI
X_next, m_next, sd_next, ei = recommend_batch(gp, float(y[tr].max()), k=8)
print("recommended next runs (physical units):\n", unit_to_physical(X_next))
print("titer drivers (ARD):", np.round(ard_importance(gp), 2))

Running this in a loop? recommend_batch draws a fresh candidate pool on each call, because seed defaults to None (ADR 0011). Pass seed=<int> when you want a bit-reproducible recommendation — but pass a different one each round, not a fixed one, or every round searches the same fixed set of candidate points and the campaign converges to the best point in that set rather than the best design.

Full end-to-end demo (writes plots, a DoE CSV, and a DoE round-reduction memo):

python examples/run_demo.py

What's in the box

Module What it does
engin_core.simulator Fed-batch Monod/Luedeking-Piret bioreactor with product inhibition — a non-monotonic titer landscape with a real interior optimum. Bespoke equations, integrated by scipy solve_ivp (piecewise across the feed/induction switches). 5 knobs: feed_rate, feed_start, Sf, induction_time, S0.
engin_core.gp scikit-learn ARD-RBF Gaussian Process + split-conformal (heteroscedastic, sd-scaled) and MAPIE-backed interval calibration + prob_at_least.
engin_core.recommend Expected-Improvement next-batch recommender with a diversity filter.
engin_core.sensitivity ARD inverse-lengthscale sensitivity — which knobs actually move titer.

The calibration story (why conformal)

A raw GP interval is overconfident here because a space-filling DoE is "easier" than the future query points the model is asked about (covariate shift), and the epistemic sd ignores observation noise entirely. Split-conformal calibrates the interval multiplier on a same-distribution held-out set using the finite-sample conformal quantile — distribution-free, no normality assumption. The score is the classical normalized nonconformity measure of Papadopoulos, Gammerman and Vovk — |y − ŷ| / σ, with σ taken from the model's own predictive sd — and the multiplier form keeps intervals riding the GP's per-point sd.

This is related to, but not the same as, MAPIE's ResidualNormalisedScore, which estimates σ with a separate learned model fitted to log-residuals. Normalizing by the GP's own sd needs no second model, which matters at the sample sizes this targets.

Reproduce (python benchmarks/benchmark.py, mean over 20 seeds):

90% interval built from… Coverage (target 0.90)
epistemic-only, Gaussian ×1.645 0.59 — naive, overconfident (seed-dependent; read as ~0.55–0.62)
total (model + noise), Gaussian ×1.645 0.86 — assumes normality, drifts per seed
total, split-conformal ×q90 0.96 — honest

Benchmarks

python benchmarks/benchmark.py (mean over 20 seeds, held-out):

  • Forecast: RMSE ≈ 3.8 g/L, R² ≈ 0.96.
  • Calibration: see table above.
  • Active-learning lift (best true titer of an 8-run batch vs the best true titer in the initial DoE): EI ≈ +18% vs random ≈ −23% — one recommended batch moves the frontier; a random batch does not.

The single-seed examples/run_demo.py slice: R² 0.97, RMSE ~4 g/L, feed_rate the dominant driver, and one active-learning round lifting best titer +28% (86→110 g/L).

Development

pip install -e ".[dev]"
pytest            # tests
ruff check .      # lint

License

Apache-2.0. Patent grant included, matching the BayBE/BioSTEAM ecosystem.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

engin_core-0.1.1.tar.gz (126.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

engin_core-0.1.1-py3-none-any.whl (88.9 kB view details)

Uploaded Python 3

File details

Details for the file engin_core-0.1.1.tar.gz.

File metadata

  • Download URL: engin_core-0.1.1.tar.gz
  • Upload date:
  • Size: 126.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for engin_core-0.1.1.tar.gz
Algorithm Hash digest
SHA256 354734760ee056759a397a7afc3f5ee09740c9f88213ffe2767b64b6e3c132b0
MD5 afea25e505627ba7dd11c7ff25fd3179
BLAKE2b-256 5a1d8856963963d2df8fe7a726e3c0f866ba63bd80d28dbb0794c2e1ffa21c8e

See more details on using hashes here.

Provenance

The following attestation bundles were made for engin_core-0.1.1.tar.gz:

Publisher: release.yml on enginbio/engin-suite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file engin_core-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: engin_core-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 88.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for engin_core-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 eaaef8bc90976105daa62c2132338c71854cbaa0f8e67ff42d075bb28a2c6930
MD5 4b11e72e90506b26be9b7a8362b9f3ad
BLAKE2b-256 377ff818f04e3fa489c9d9178d535002618f475f120cb551e2fd482424bd443d

See more details on using hashes here.

Provenance

The following attestation bundles were made for engin_core-0.1.1-py3-none-any.whl:

Publisher: release.yml on enginbio/engin-suite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page