Topiary predicts which peptides from an antigen source are presented by a patient's MHC molecules, then filters and ranks them. Inputs are protein sequences, peptides, somatic variants or another pipeline's report, plus a list of MHC alleles; the output is a DataFrame (or CSV/HTML file) with one row per peptide, allele and prediction. It is used for personalized cancer vaccine design, viral epitope mapping and characterizing T-cell responses. In the openvax stack, Topiary runs MHC predictors through mhctools, translates variants with varcode and pyensembl, reads RNA evidence from isovar, and supplies the predictions and ranking expressions that vaxrank uses.
Topiary requires Python 3.11 or newer and pandas 3.x (pandas>=3,<4).
pip install topiaryMHC predictors are installed separately and called through mhctools. MHCflurry installs with pip; its models are a separate download:
pip install mhcflurry
mhcflurry-downloads fetchNetMHCpan and the other DTU tools need a license from
DTU Health Tech. Variant annotation,
gene lookups and SelfProteome need a local Ensembl annotation database:
pyensembl install --release 115 --species humanIsovar, PirlyGenes, OncoRef and WEIRDO are installed with Topiary; there are no extras to choose. Installation details covers other Ensembl releases and compatible package versions.
Score two viral peptides against two HLA alleles with MHCflurry:
from mhctools import MHCflurry
from topiary import TopiaryPredictor
peptides = {"influenza_M1": "GILGFVFTL", "CMV_pp65": "TPRVTGGGAM"}
columns = ["peptide", "allele", "kind", "value", "score", "percentile_rank"]
predictor = TopiaryPredictor(
models=[MHCflurry],
alleles=["HLA-A*02:01", "HLA-B*07:02"],
)
df = predictor.predict_from_named_peptides(peptides)
print(df[columns].to_string(index=False)) peptide allele kind value score percentile_rank
GILGFVFTL HLA-A*02:01 pMHC_affinity 25.841361 0.699441 0.130863
GILGFVFTL HLA-B*07:02 pMHC_affinity 14185.201956 0.116437 8.844587
GILGFVFTL HLA-A*02:01 pMHC_presentation NaN 0.850049 0.193547
GILGFVFTL antigen_processing NaN 0.175628 NaN
TPRVTGGGAM HLA-A*02:01 pMHC_affinity 556.503394 0.415730 1.541447
TPRVTGGGAM HLA-B*07:02 pMHC_affinity 14.428557 0.753303 0.003906
TPRVTGGGAM HLA-B*07:02 pMHC_presentation NaN 0.941776 0.062445
TPRVTGGGAM antigen_processing NaN 0.300611 NaN
Each row is one peptide, allele and prediction kind. value is the raw
prediction (IC50 in nM for binding affinity), score is higher-is-better and
percentile_rank is lower-is-better. MHCflurry predicts affinity for each
allele, presentation for the genotype (reported under its best allele) and
antigen processing with no allele.
Pass filter_by=Affinity <= 500 (with from topiary import Affinity) to keep
only the pairs predicted to bind at 500 nM or tighter, and sort_by= to rank
them. Both take expressions that combine prediction fields, arithmetic,
normalizing transforms and any DataFrame column; see the
ranking DSL guide. To scan whole
proteins with a sliding window, use predict_from_named_sequences; for
varcode variants, use
predict_from_variants.
The topiary command runs the same pipeline from variants, sequence files or
gene names. This run translates KRAS G12D, scores the mutant peptides and keeps
the binders (Ensembl data for --genome grch38 must be installed as above):
topiary \
--variant 12 25245350 C T \
--genome grch38 \
--mhc-predictor mhcflurry \
--mhc-alleles 'HLA-A*11:01,HLA-C*08:02' \
--filter-by "affinity <= 500" \
--only-novel-epitopes peptide allele kind value score percentile_rank source_sequence_name
VVGADGVGK HLA-A*11:01 pMHC_affinity 126.927288 0.552337 0.505538 KRAS_p.G12D_chr12_g.25245350C_T__567b9678
VVGADGVGK HLA-A*11:01 pMHC_presentation NaN 0.727242 0.375163 KRAS_p.G12D_chr12_g.25245350C_T__567b9678
VVGADGVGK antigen_processing NaN 0.465049 NaN KRAS_p.G12D_chr12_g.25245350C_T__567b9678
GADGVGKSA HLA-C*08:02 pMHC_affinity 108.830353 0.566554 0.282237 KRAS_p.G12D_chr12_g.25245350C_T__567b9678
GADGVGKSA HLA-C*08:02 pMHC_presentation NaN 0.534686 0.686717 KRAS_p.G12D_chr12_g.25245350C_T__567b9678
GADGVGKSA antigen_processing NaN 0.215621 NaN KRAS_p.G12D_chr12_g.25245350C_T__567b9678
6 prediction rows (2 unique peptides, 2 named alleles)
--vcf, --maf, --fasta, --peptide-csv and --gene-names select other
inputs, and --output-csv results.csv saves every row instead of printing a
preview. The command-line guide
lists predictor names, input modes, output columns and exit status.
The full documentation is at openvax.github.io/topiary. In reading order:
- Quickstart: protein scans, input files, Ensembl and tissue lookups, multiple models.
- Command-line interface: predictor names, input modes, output columns, exit status.
- Ranking DSL: filter and ranking expressions in Python and as strings.
- Protein fragments: one antigen record for variants, fusions, ERVs, CTAs, viral and synthetic sources.
- Cached predictions: replay stored scores instead of calling a predictor.
- API reference: classes, functions and complete column lists.
Other guides cover RNA expression, peptide properties, cross-reactivity, structural-variant evidence reports, reading pVACseq, LENS and Exacto reports, and combining those sources with fresh predictions in one ranking.
./develop.sh # editable install (uses uv)
pip install -r requirements-dev.txt # lint, test and docs tools
./lint.sh
./test.sh # full suite: needs Ensembl data and predictors
python -m pytest tests --collect-only # collecting loads no Ensembl data or predictors
./test.sh -m isovar --strict-markers # synthetic Isovar tests, no Ensembl download
mkdocs build --strict # docs siteEvery pull request bumps __version__ in topiary/__init__.py and adds a
CHANGELOG entry;
RELEASING.md
describes the release steps.
Apache License 2.0. See LICENSE.