Skip to main content

Low-N, acquisition-driven, epistasis-aware protein mutation recommendation engine

Project description

epiquire

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

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

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 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:

%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).

# 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

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:

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

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:

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:

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.

Project details


Download files

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

Source Distribution

epiquire-0.1.21.tar.gz (153.5 kB view details)

Uploaded Source

Built Distribution

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

epiquire-0.1.21-py3-none-any.whl (124.7 kB view details)

Uploaded Python 3

File details

Details for the file epiquire-0.1.21.tar.gz.

File metadata

  • Download URL: epiquire-0.1.21.tar.gz
  • Upload date:
  • Size: 153.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for epiquire-0.1.21.tar.gz
Algorithm Hash digest
SHA256 54ed0798dafb9bd193c0d9aa76354de5832c641de38da7d67da22600b2a7b609
MD5 92bdec34676113106703f981e8e9228e
BLAKE2b-256 0c4d5e7b09c3340a2b44432115bc20f729cf96061c90bd2b4b8e16600e09cb72

See more details on using hashes here.

File details

Details for the file epiquire-0.1.21-py3-none-any.whl.

File metadata

  • Download URL: epiquire-0.1.21-py3-none-any.whl
  • Upload date:
  • Size: 124.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for epiquire-0.1.21-py3-none-any.whl
Algorithm Hash digest
SHA256 ab4c3599582967d26ab861c559ad8576beef93141bef23a4550531a7e68a49d1
MD5 22bece809d03da9a776d8630ac95bd84
BLAKE2b-256 f4cc3e67b7ae48997359d70c4e72ba4d420f00b330eb2414d207b1d0e1f205d9

See more details on using hashes here.

Supported by

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