Metadata-Version: 2.4
Name: epiquire
Version: 0.1.21
Summary: Low-N, acquisition-driven, epistasis-aware protein mutation recommendation engine
Author: gyuminlee-repo
Keywords: directed-evolution,protein-engineering,active-learning,bayesian-optimization,epistasis,mutation-recommendation
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: numpy
Requires-Dist: scipy
Requires-Dist: scikit-learn
Requires-Dist: pandas
Provides-Extra: plm
Requires-Dist: torch; extra == "plm"
Requires-Dist: esm; extra == "plm"
Provides-Extra: plm2
Requires-Dist: fair-esm; extra == "plm2"
Provides-Extra: dev
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pyright; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"

# epiquire

Low-N, acquisition-driven protein mutation recommendation. The spine is one measurement campaign:

```text
R0 seed to measure -> fit surrogate on all measured data -> acquire next plate -> measure -> repeat
```

`epiquire` is not a magic zero-shot "better protein" predictor. Zero-shot, MSA, inverse-folding,
structure, and ddG signals are used as priors, constraints, or features. The function-aligned signal
is still measurement. The tool's job is to spend a small measurement budget better.

## Install

```bash
pip install epiquire            # from PyPI (core deps: numpy/scipy/scikit-learn/pandas)
pip install "epiquire[plm]"     # optional: adds torch + ESM-C (PLM re-rank / naturalness)
```

Or run it in your browser with **no install** via the Colab notebook below.

## Easiest entry point: `epiquire round`

One command per round. It auto-resolves the active-site design region (the `resolve-site` evidence
ladder: UniProt -> linked PDB cocrystal -> AlphaFold) and then runs the campaign round, so there is
no position bookkeeping by hand.

**Run it in your browser, no install:** open [`notebooks/epiquire_round_colab.ipynb`](https://colab.research.google.com/github/gyuminlee-repo/epiquire/blob/master/notebooks/epiquire_round_colab.ipynb)
in Google Colab. The notebook is a 3-line bootstrap over `epiquire.colab.plate(...)` -- all logic
lives in the pip package, so `%pip install -q -U epiquire` always gets the latest and the notebook
file never needs re-uploading. In any notebook you can skip the form and call it directly:

```python
%pip install -q -U epiquire
from epiquire.colab import plate
df = plate("...WT sequence...", uniprot="Q50L36", auto_msa=True)   # R0 seed plate, MSA built for you
```

The core loop is numpy/scikit-learn (seconds); only the optional PLM path is heavy (Colab's free GPU).

```bash
# R0: no --measured -> the funclib seed plate to MEASURE. The seed needs a tolerance signal;
# supply --msa/--ddg/--if-logprobs, OR --auto-msa to build the MSA from the WT (ColabFold MMseqs2).
epiquire round WT.fasta --uniprot Q50L36 --auto-msa --plate 95 --outdir outputs/round

# Rk: add each round's measured results -> the next AL plate over the full saturation universe
epiquire round WT.fasta --uniprot Q50L36 --measured round0_measured.csv --plate 95 --outdir outputs/round
```

Point at the design region with whatever you have: `--uniprot ACC` (or `--uniprot auto` to find the accession by
an EXACT match of your WT sequence against UniProt), `--query`/`--pdb` (auto ladder), a local
`--holo` structure, or explicit `--positions`. Give more than one and the most-specific wins,
resolved by a fixed priority `positions > holo > pdb+uniprot > pdb > uniprot/query` -- so you can just
pass whatever you have. Two special combinations: giving **both** `--pdb` and `--uniprot` designs over
the PDB contact shell while flagging (QC) the UniProt catalytic core that falls inside it, and adding
`--exclude-catalytic` then designs only the tunable 2nd-shell ring (shell minus the usually-lethal
catalytic core). If the ladder cannot map evidence onto your WT it abstains (supply `--positions` or
`--holo`) rather than guessing. `round` is a thin wrapper: `resolve-site` and `campaign` below remain
the explicit, fully-configurable commands it calls.
No cocrystal at all? `--find-holo` (on `round`/`resolve-site`) Foldseek-searches for a ligand-bound
(holo) structural homolog of your WT and, if a SIGNIFICANT one exists (E-value + coverage gated), uses
its ligand pose to define the shell; it abstains when only distant homologs are found so a mismatched
pocket is never silently borrowed. When several evidence types are available (e.g. `--pdb` + `--uniprot`)
epiquire prints an evidence-consensus map: each position tagged with which independent lines support it
and a confidence tier (high = >=2 agree), so you can measure high-confidence positions first.

## The campaign engine (what `round` calls)

Use `campaign` when starting an active-site campaign. It combines the two validated pieces:

1. **R0 cold-start seed**: FuncLib-style active-site library construction. This proposes variants to
   measure; it does not predict winners.
2. **R1+ active learning**: after measurements arrive, the AL loop searches the full saturation space
   of the design positions, not just the R0 seed.

### R0: generate the seed plate

```bash
epiquire campaign WT.fasta \
  --holo holo_structure.pdb --ligand-resnames LIG \
  --msa alignment.a3m \
  --plate 95 \
  --outdir outputs/campaign
```

This writes `outputs/campaign/round0_plate.csv` with `variant,mutations,n_mut,seed_score`. Measure
those variants and save a `variant,fitness` CSV.

You can use explicit design positions instead of a holo structure:

```bash
epiquire campaign WT.fasta \
  --positions 183,184,227,228 \
  --msa alignment.a3m \
  --plate 95 \
  --outdir outputs/campaign
```

### R1+: propose the next plate from measured data

```bash
epiquire campaign WT.fasta \
  --positions 183,184,227,228 \
  --measured round0_measured.csv \
  --plate 95 \
  --outdir outputs/campaign
```

With multiple rounds, pass all accumulated CSVs:

```bash
epiquire campaign WT.fasta \
  --positions 183,184,227,228 \
  --measured round0_measured.csv round1_measured.csv \
  --plate 95 \
  --outdir outputs/campaign
```

On later rounds, add `--plm esmc` to rerank the plate with an ESM-C surrogate refit on YOUR measured
data (EVOLVEpro-style; opt-in, GPU-recommended). Every Rk round also auto-prints an `advise` line --
held-out Spearman + a recommendation (`gather_more` / `model_reliable` / `open_epistasis`) -- so you
know each round whether to trust the surrogate or keep measuring broadly.

### Simulate against a complete landscape

For validation or retrospective benchmarks:

```bash
epiquire campaign WT.fasta \
  --simulate data/trpb.csv \
  --positions 183,184,227,228 \
  --msa isps_run/msa_trpb.a3m \
  --strategies funclib singles random \
  --plate 95 --rounds 3 --seeds 20 --jobs 4 \
  --model-class ridge \
  --outdir artifacts/campaign_trpb
```

`--jobs` parallelizes independent seeds with spawn processes; serial output and parallel output are
byte-identical by test.

## Other commands

- `epiquire recommend measured.csv`: rank next candidates from accumulated measurements. This is the
  AL round engine exposed directly. If you pass `--if-logprobs`, epiquire CV-gates that signal by
  default and uses it only if it improves held-out performance on this protein. Use
  `--no-auto-signals` only as an expert override. `--recombine` also adds recombinations of your
  MEASURED beneficials (variants beating WT) to the candidate pool -- the strategy the real-data
  evidence supports (measure broadly, then recombine confirmed wins).
- `epiquire resolve-site WT.fasta --uniprot ACC` (or `--query`): resolve active-site/binding positions
  from UniProt experimental curation, sequence-aligned onto YOUR WT numbering (handles transit-peptide
  / species offsets), with provenance + confidence per position. If UniProt features do not map it
  falls back to a UniProt-linked PDB cocrystal (active-site shells); `--pdb ID` forces the structure
  path. If neither maps, it fetches the AlphaFold model (predicted, apo). Optional `--apo-pocket`
  (fpocket) guesses pocket positions but is LOW-confidence -- it missed the catalytic site on ispS,
  so it is warned, not default. `--find-holo` instead Foldseek-finds a ligand-bound homolog (gated on
  significance) to borrow a pose from; giving `--pdb` + `--uniprot` prints an evidence-consensus map
  (per-position support + confidence tier). Abstains on positions rather than guessing -- then provide
  `--holo`/`--positions`. Feed resolved positions to `campaign`.
- `epiquire hotspots scan.csv`: rank hotspot positions from a whole-protein single-mutant scan
  (`variant,activity`; CSV or Excel), then hand the top positions to `round --positions` for
  epistasis-aware combinatorial AL. Honest: scan-based position selection is a coarse pre-filter,
  reliable only on additive sites (see `artifacts/hotspots_backtest_evidence.md`).
- `epiquire funclib WT.fasta ...`: build only the active-site R0 measurement library. Useful when you
  want the seed plate without the campaign wrapper.
- `epiquire advise measured.csv`: readiness check on measured data (held-out Spearman + pairwise gate
  -> gather_more / model_reliable / open_epistasis). Also auto-printed at the end of every `round`/`campaign`
  Rk round, so you are told each round whether to trust the surrogate or keep measuring.
- `epiquire bench`: synthetic alpha-spectrum benchmark.
- `epiquire report`: summarize a JSON report.

## What the opt-ins mean

Most optional flags are not feature clutter. They are either:

- **resources you must provide**: MSA, PDB, inverse-folding table, ddG table, PLM cache; or
- **expert overrides** for known regimes.

The default stays conservative because low-N model selection overfits. When epiquire can decide from
this protein's measured data, it should decide itself: optional IF signals are now CV-gated by default;
pairwise epistasis has its own data gate (`--auto-gate-pairwise`). See `docs/OPTIN_AUDIT.md`.

## Honest scope

Evidence so far supports these claims:

- active-site FuncLib-style seeds enrich measurable libraries and improve low-budget discovery;
- the global activity winner can be outside the seed, so AL must search beyond the seed;
- stability/ddG signals are best used as constraints, while activity improvement is measurement-bound;
- high-order activity epistasis makes zero-shot winner prediction unreliable.

Evidence does **not** support: "epiquire predicts the best protein from sequence/structure alone." It
increases the probability and efficiency of finding a better variant per measured plate, conditional on
the design space and assay.

## When NOT to use epiquire

The focused active-site campaign helps only when the wins plausibly live in a region you can name
and measure combinatorially. Do NOT reach for it when:

- you do not know where beneficial mutations are (no mechanistic/structural prior on the target site);
- the wins are likely distal/distributed across the protein (use a broad whole-protein single-mutant
  scan instead -- that is a different tool class; epiquire's additive default cannot rank
  whole-protein singles because one-hot has no cross-position transfer);
- you cannot measure a focused combinatorial library (no assay throughput at the chosen site).

Real-data caution (PtIspS, `artifacts/ispS_wetlab_validation.md`): a campaign run as a broad
single-mutant scan with the active site barely sampled and the global winner distal is exactly the
regime epiquire is NOT for. Pick broad-vs-focused from your biology; epiquire does not decide it.

More detail: `ARCHITECTURE.md`, `artifacts/DECISION_EVIDENCE.md`, and the Obsidian decision log named
there.
