Wet-lab feedback loop
Architecture for Waves 2-4 — how wet-lab measurements flow into the platform, calibrate predictions, and close the dry/wet loop.
Wet-lab bench Platform
──────────── ────────
SPR / BLI Kd ─────────────┐
Flow cytometry % │
Cytotoxicity E:T │ ┌──────────────────────────┐
Yield mg/L ├───▶ │ POST /api/v1/wet-lab/ │
Tonic readouts │ │ measurements │
Stability Tm │ │ (single or /batch) │
───────────── ┘ └──────────┬───────────────┘
│
▼
┌──────────────────────────────┐
│ wet_lab_measurements (DB) │
│ - antibody_id │
│ - measurement_type │
│ - value / unit / assay │
│ - batch_id / measured_at │
└──────────┬───────────────────┘
│
▼
┌──────────────────────────────┐
│ Wave 2 calibration runner │
│ (pipeline.tools.calibration) │
│ Fits per (score × wet-lab │
│ type) corrector — linear, │
│ isotonic, or Platt scaling │
└──────────┬───────────────────┘
│
▼
┌──────────────────────────────┐
│ score_calibrations (DB) │
│ - score_id, wet_lab_type │
│ - method + parameters_json │
│ - n_samples + ρ + RMSE │
└──────────┬───────────────────┘
│
▼
┌──────────────────────────────┐
│ Calibrated score surface │
│ - /candidates shows │
│ corrected values + raw │
│ - /docs/scoring-audit V4 │
│ reports per-score ρ to │
│ measurement │
│ - Wave 3 internal models │
│ train on (raw, wet-lab) │
│ pairs │
└──────────────────────────────┘
Every observation at the bench has exactly one place it lands: the wet_lab_measurements table. Calibration runs read from there, fit per-score correctors, and store parameters in score_calibrations. The platform then surfaces both the raw prediction and the calibrated correction so researchers can see the delta.
| Field | Required | Example | Why |
|---|---|---|---|
| antibody_id | yes | 37 | Pairs measurement to a platform candidate. |
| measurement_type | yes | Kd_SPR_nM | Standardized type string — used as the join key for calibration. |
| value | yes | 12.4 | The measurement itself. |
| unit | yes | nM | Required for unit-aware comparison across batches. |
| assay_method | recommended | SPR / Biacore 8K | Different assays correlate differently; calibration can stratify by method. |
| batch_id | recommended | BCMA-batch-2026-06-14 | Tracks the wet-lab campaign for traceability + re-fit triggers. |
| measured_at | recommended | 2026-06-14T09:30:00Z | ISO timestamp — needed to detect drift over time. |
| notes | optional | outlier — possible aggregation | Anything that helps future-you re-interpret the row. |
Keep types as `name_method_unit` so the platform can auto-match wet-lab columns to in-silico scores at calibration time.
| measurement_type | Maps to in-silico score |
|---|---|
| Kd_SPR_nM | ipTM / ensemble_iptm (rank against) |
| Kd_BLI_nM | ipTM / ensemble_iptm |
| expression_yield_mg_per_L | ablang_avg / TAP composite |
| tm_DSF_celsius | tm_prediction / ddg_thermompnn |
| aggregation_SEC_pct_HMW | aggregation_score / tap_psh |
| tonic_signal_flow_pct | tonic_clustering_risk |
| cytotoxicity_E_T_5_1_pct_killing | car_score + composite |
| surface_expression_MFI | car_score component (expression) |
| cross_reactivity_TACI_BLI_nM | selectivity |
| cyno_binding_BLI_nM | xspecies_cyno_iptm |
| fcrn_binding_SPR_pH6_nM | fcrn_binding |
Wave 2 — Linear / isotonic correction
Once 10-20 (in-silico, wet-lab) pairs exist per type, the calibration runner fits a per-score linear corrector and an isotonic regression backup. Outputs: corrected score column + Spearman ρ + RMSE diagnostic. Storage: score_calibrations table.
Wave 3 — Internal predictor training
Once 50+ pairs exist, train an internal model that beats the corrected public-tool score on this specific assay. Stored as a versioned model alongside its training cohort id. Architecture: ESM-2 embeddings → small MLP head, or whatever rank-correlates best. Triggers automatic re-evaluation against the latest wet-lab batch.
Wave 4 — Foundation-model fine-tune
Once 200+ pairs cover the full design space, fine-tune ProteinMPNN / RFantibody on internal sequence + wet-lab label pairs. Gated on Modal self-host (Spec 3 S.1) — these models need GPU. Output: a fine-tuned design model that proposes candidates already shifted toward the wet-lab-validated subspace.
| Endpoint | Purpose |
|---|---|
| POST /api/v1/wet-lab/measurements | Single measurement ingest |
| POST /api/v1/wet-lab/measurements/batch | Batch ingest from a CSV / pipeline export |
| GET /api/v1/wet-lab/measurements | List recent measurements, optional type filter |
| GET /api/v1/wet-lab/measurements/candidate/{id} | All measurements for one candidate |
| GET /api/v1/wet-lab/coverage | How many candidates have which measurement types |
| GET /api/v1/wet-lab/calibrations | Latest fitted correctors per (score, wet-lab type) |
| GET /api/v1/wet-lab/health | Pipe sanity check — confirms tables exist |
✅ Tables created (wet_lab_measurements + score_calibrations)
✅ Ingest + retrieval API live (7 endpoints above)
✅ Wave 2 calibration runner shipped (pipeline.tools.calibration.refit_all)
⏳ Awaiting first wet-lab batch — coverage is 0 measurements / 0 candidates today
🔒 Wave 4 (foundation-model fine-tune) is gated on Modal self-host