Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 156 additions & 0 deletions docs/WET_LAB_HANDOFF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
# Wet-Lab Handoff Guide

**Version:** 0.1.0
**Status:** Working draft for expert review before synthesis ordering.

---

## Purpose

This document translates pipeline output scores into synthesis and assay decisions for wet-lab
scientists. Every nominated candidate has a JSON evidence certificate and a pre-synthesis QC
report. This guide explains what each number means, what action it recommends, and what to do
when fewer candidates pass the filters than expected.

---

## Score Reference Table

All scores are on a **[0, 1] scale**. Higher is better (except `disagreement`, which is lower is better).

| Score key | What it measures | Low (< 0.4) | Medium (0.4–0.7) | High (> 0.7) |
|-----------|-----------------|------------|-----------------|-------------|
| `activity` | Physicochemical similarity to known AMPs (charge, hydrophobicity, amphipathicity) | Unlikely AMP-like | Possible candidate | Strong AMP signature |
| `safety` | Absence of hemolysis risk, toxic motif similarity, mammalian membrane affinity | High host-cell risk — exclude | Monitor carefully | Safe to proceed |
| `synthesis` | SPPS synthesis feasibility (length, Cys content, repeat runs) | Difficult / high failure risk | Moderate; check QC report | Straightforward synthesis |
| `novelty` | Sequence distance from known AMP references | Near-duplicate of known AMP | Moderate novelty | New structural territory |
| `ensemble` | Weighted combination of above four scores | Below priority threshold | Borderline | Priority candidate |
| `disagreement` | |activity_likeness − boman_activity| — scorer consensus | High consensus (good) | Some divergence | Low consensus — treat cautiously |

### Recommended Action by Ensemble Score

| Ensemble range | Recommendation |
|---------------|---------------|
| ≥ 0.70 | **Synthesise** — priority candidate |
| 0.55–0.69 | **Conditional synthesis** — review QC flags first |
| 0.40–0.54 | **Expert review required** — only if budget allows |
| < 0.40 | **Do not synthesise** — fails pipeline threshold |

---

## Selection Thresholds

The pipeline uses four gates before a candidate is marked `selected: true`.

| Gate | `pipeline.yaml` | `phase3.yaml` | Why |
|------|----------------|--------------|-----|
| `min_novelty` | ≥ 0.20 | ≥ 0.05 | Near-duplicates waste budget on already-known peptides |
| `max_safety_risk` → min safety | ≤ 0.70 → safety ≥ 0.30 | ≤ 0.40 → safety ≥ 0.60 | Phase 3 is the final synthesis batch — only clean candidates |
| `max_disagreement` | ≤ 0.40 | ≤ 0.30 | When physchem and Boman scoring diverge > threshold, both models are guessing |
| Sequence validity | canonical AA only | same | Non-canonical residues are disqualified |

A candidate must pass **all four gates** to be nominated. Failing any single gate → `selected: false`.

---

## Pre-Synthesis QC Report Interpretation

Run `make presynth-qc` (or `openamp-foundry presynth-qc --panel-csv <file>`) on the final panel
before ordering. The report flags:

| Flag | Risk | Action |
|------|------|--------|
| `CYSTEINE×N` | Disulfide formation, oxidation during storage | Order under inert atmosphere; store in N₂; check purity pre-assay |
| `MET×N` | Met oxidation to sulfoxide in air | Order with >95% purity; store at −80°C; re-check purity on thaw |
| `HYDROPHOBIC_RUN (XXXX)` | Aggregation; poor aqueous solubility | Test solubility at 1 mM in PBS before assay; add 0.1% DMSO if needed |
| `TRYPSIN_SITES×N` (N > 2) | Serum degradation < 2h | Use serum-free media for initial MIC; add protease inhibitors if needed |
| `DEAMIDATION_RISK` | N→D conversion at pH > 7.5 | Use pH 7.0 buffer; avoid long storage at room temp |
| `LOW_CHARGE` | Reduced membrane affinity | Lower expected potency; may need higher test concentrations |
| `LONG_PEPTIDE (>30aa)` | SPPS yield risk | Expect lower crude purity; order extra crude for purification |

### Synthesis Difficulty Rating

| Rating | Meaning | Action |
|--------|---------|--------|
| LOW | ≤ 0 flags | Standard SPPS protocol; Fmoc chemistry |
| MODERATE | 1–2 flags | Standard protocol + address specific flags above |
| HIGH | ≥ 3 flags | Discuss with peptide synthesis vendor; consider Boc chemistry or ligation |

---

## Assay Recommendations

### Initial Screen (MIC Assay)

- **Organism priority:** *E. coli* ATCC 25922 (Gram-negative standard), *S. aureus* ATCC 29213 (Gram-positive standard)
- **Growth medium:** MHB (Mueller-Hinton Broth), cation-adjusted
- **Inoculum:** ~5×10⁵ CFU/mL (CLSI standard)
- **Concentration range:** 1–128 μg/mL (2-fold serial dilutions)
- **Replicates:** ≥ 3 biological replicates per candidate
- **Positive control:** Colistin (Gram-negative), Oxacillin (Gram-positive)
- **Negative control:** Solvent blank matching highest solvent concentration

### Hemolysis Assay (Safety Gate)

Run in parallel with MIC. The `hemolysis_start_conc` field in the presynth QC report gives the
recommended starting concentration based on the computed hydrophobic moment (μH):

| μH range | Starting concentration |
|---------|----------------------|
| ≤ 0.55 | Start at MIC (low risk) |
| > 0.55 and ≤ 0.80 | Start at MIC/3 (moderate risk) |
| > 0.80 | Start at MIC/10 (high risk — very cautious) |

Use human red blood cells (hRBCs) at 0.5% in PBS. Incubate 1h at 37°C. Read at A540.
Hemolysis > 10% at MIC is a fail.

---

## Troubleshooting

### Too Few Candidates Pass the Gates

If fewer than 10 candidates are nominated from a batch:

1. Check `disagreement` scores — if many candidates cluster near the configured `max_disagreement`
threshold (0.30 for phase3.yaml, 0.40 for pipeline.yaml), the two scorers may systematically
disagree for this peptide series. Consider whether to relax `max_disagreement` in a custom
config (document the change and the scientific justification).
2. Check `novelty` scores — if the reference set covers your template region well, novelty will
be low. Consider reducing `min_novelty` for that generation run only.
3. Check `safety` scores — if a hydrophobic template is used, many variants may have low safety.
Review the safety score components (`scoring/safety.py`) for the specific risk flag.
4. Run `openamp-foundry bench leakage` to confirm candidates are not near-duplicates of each other.

### Synthesis Failure (No Product / Low Purity)

1. Check the presynth QC report for HYDROPHOBIC_RUN or LONG_PEPTIDE flags.
2. Consider pseudoproline (Ψ-Pro) dipeptides for Ser/Thr-containing sequences.
3. Consider microwave-assisted SPPS for sequences with aggregation propensity.
4. For Cys-containing peptides: use Acm protection if disulfide formation is not desired.

### All Candidates Fail Hemolysis

1. Check μH values — a high hydrophobic moment across all candidates suggests the template
itself is hemolytic.
2. Consider substituting hydrophobic residues (L→A, F→Y) to reduce membrane disruption.
3. Re-score the modified variants through the pipeline before ordering.

---

## Confidence Statement

All scores are **heuristic proxies** derived from physicochemical features. They have not been
calibrated against wet-lab activity data for this specific peptide series. The pipeline is a
**nomination tool**, not a predictor of MIC values. Expect a hit rate of 20–40% in initial
screens (consistent with the AMP field literature for computationally nominated candidates).

No antimicrobial activity claim is made until wet-lab confirmation.

---

## References

- CLSI M07-A10: Methods for Dilution Antimicrobial Susceptibility Tests for Bacteria That Grow Aerobically
- Boman HG (2003) Peptide antibiotics and their role in innate immunity. Annu Rev Immunol 13:61–92
- Fjell CD et al. (2011) Designing antimicrobial peptides. Nat Rev Drug Discov 11:37–51
25 changes: 25 additions & 0 deletions tests/test_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,31 @@ def test_default_config_selection_present(self):
assert "max_disagreement" in sel
assert 0.0 <= sel["max_disagreement"] <= 1.0

def test_phase3_config_selection_present(self):
phase3 = Path(__file__).parents[1] / "configs" / "phase3.yaml"
result = load_config(phase3)
sel = result["selection"]
assert "top_n" in sel
assert "min_novelty" in sel
assert "max_safety_risk" in sel
assert 0.0 < sel["max_safety_risk"] <= 1.0
assert "max_disagreement" in sel
assert 0.0 <= sel["max_disagreement"] <= 1.0

def test_phase3_config_weights_are_positive(self):
phase3 = Path(__file__).parents[1] / "configs" / "phase3.yaml"
result = load_config(phase3)
for name, w in result["weights"].items():
assert w > 0, f"phase3.yaml weight '{name}' must be positive, got {w}"

def test_phase3_config_filters_present(self):
phase3 = Path(__file__).parents[1] / "configs" / "phase3.yaml"
result = load_config(phase3)
filters = result["filters"]
assert "min_length" in filters
assert "max_length" in filters
assert filters["min_length"] < filters["max_length"]

def test_string_path_accepted(self):
with tempfile.TemporaryDirectory() as d:
cfg_path = Path(d) / "config.yaml"
Expand Down
13 changes: 13 additions & 0 deletions tests/test_physchem.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,16 @@ def test_all_canonical_aa_no_crash(self):
seq = "ACDEFGHIKLMNPQRSTVWY"
feat = compute_features(seq)
assert feat["length"] == 20

def test_compute_features_supplies_synthesis_feasibility_keys(self):
# synthesis_feasibility_score() does direct dict access (no .get()) on three keys.
# This test pins the contract so a refactor that removes any key fails loudly here
# rather than crashing mid-pipeline during candidate scoring.
from openamp_foundry.scoring.synthesis import synthesis_feasibility_score
feat = compute_features("KWKLFKKIGAVLKVL")
assert "length" in feat
assert "longest_repeat_run" in feat
assert "cysteine_fraction" in feat
# Also verify the function runs without KeyError — the real integration check.
score = synthesis_feasibility_score(feat, valid_sequence=True)
assert 0.0 <= score <= 1.0
Loading