Getting started#
Installation#
From PyPI (binary wheels ship the C++ extensions and pull in the TCR-annotation backend):
$ pip install tcren
For development — a repo-local .venv via uv, an editable
install, and the reference data fetched into data/ (no conda; needs only uv and a C++
compiler):
$ bash setup.sh
$ source .venv/bin/activate
The TCR-annotation backend arda (mmseqs2-based) is a normal dependency, published to PyPI as
arda-mapper (it imports as arda); uv/setup.sh
pull it in automatically. From arda-mapper >= 2.5.7 it auto-fetches its own reference and a
static mmseqs2 binary on first use — no conda/bioconda and no ARDA_HOME to set. tcren also
builds five small pybind11/C++ kernels on install:
tcren._align (MHC-pseudosequence alignment), tcren._refine (DOPE Monte-Carlo refinement),
tcren._relax (DOPE interface energy), tcren._fold (CCD loop closure) and tcren._geom
(binder interface geometry).
Command line#
End-to-end candidate-epitope scoring from a structure:
$ tcren score -s complex.pdb -c candidates.txt -o ranked.csv
Scoring structures#
tcren scoring reads structures and writes numbers: the three interface contact energies
(TCRen for TCR↔peptide, Miyazawa–Jernigan for TCR↔MHC and peptide↔MHC) and their total
\(\Phi\), one row per structure. It is scoring only — the preparation steps
(canonicalisation, region mapping, Cα / contact / atom-distance matrices) are the separate
tcren annotate, tcren superimpose and tcren contacts commands. In the library it is
tcren.run_pipeline(structure).
$ tcren scoring -s complex.pdb.gz -o scores.csv
-s takes a file, a directory, a .tar.gz, a quoted glob, a .txt manifest with one path
per line, a comma-separated list, or a repeated flag — mix them freely:
$ tcren scoring -s a.pdb.gz -s b.pdb.gz -o scores.csv
$ tcren scoring -s 'models/*.pdb.gz' -o scores.csv
$ tcren scoring -s models.txt -o scores.csv
Two options change what is reported:
--deltaadds the poly-alanine reference \(\Delta\Phi_I=\Phi_I(\text{peptide})-\Phi_I(\text{poly-Ala})\) per interface, plus
dF_total. \(\Delta\Phi_{\mathrm{TCR:MHC}}\) is identically zero — the peptide is not in that interface. On a fixed contact map \(\Delta\Phi\) is \(\Phi\) minus a constant and reorders nothing; use it when each candidate carries its own generated pose, where raw \(\Phi\) partly reads the pose the predictor chose.--geometryadds the interface descriptors (
burial,n_pep_contacted,chain_balance,n_hbond,pitch,crossing) andQ, the directional decorrelated interface-quality score (tcren.q_score()), standardised against the native-crystal reference so it is defined for a single structure. For the complete 35-descriptor catalogue plusP(real), usetcren recognize.
Columns are named as in tcren recognize (F_tcr_pep, dF_pep_mhc, …), so the two tables
join on pdb.id.
Inputs accept .pdb/.cif/.pdb.gz/.cif.gz, a directory, or a .tar.gz batch;
identifiers are resolved from the file names:
$ tcren contacts -s batch.tar.gz -o contacts.csv --interface tcr_peptide
$ tcren annotate -s complex.cif.gz -o markup.csv --regions mhc --pseudo
tcren annotate emits one per-residue markup table covering TCR (CDR/FR), MHC groove
(helices/floor) and peptide; --regions all|tcr|mhc|peptide filters it to one chain class and
--pseudo additionally marks the NetMHCpan MHC pseudosequence residues (region MPS). It
replaces the old separate tcren mhc command.
There are two orientation commands (chains are renamed A=Vα, B=Vβ, C=peptide,
D=MHCα, E=MHCβ/β2m):
tcren superimposebrings a new structure into the canonical frame by superposing its conserved MHC groove Cα onto a canonical database. It detects the input’s MHC class and species, selects every database structure of the same class and species, superposes against each (sequence alignment fixes the residue correspondence), and averages the rigid transforms — translations by mean, rotations by the chordal (SVD-orthonormalised) mean — into one consensus placement. The database defaults todata/Canonical2026(populated at install).tcren orientbuilds a canonical database from native complexes by deriving the per-class canonical frame (this is howCanonical2026itself is produced). Annotation runs as a single batched mmseqs2 call;-tthreads only the structural alignment and write.
$ tcren superimpose -s complex.pdb -o oriented/
$ tcren orient -s data/Native2026 -o data/Canonical2026 -t 8
Both need the reference sets in data/; setup.sh runs tcren fetch-data at install to
populate them. Structure outputs are plain .pdb by default — add --mmCIF for .cif and
--compress for a trailing .gz (these flags apply to every command that writes a structure).
Fetch recent TCR-pMHC structures from the RCSB into data/pdb_recent (mmCIF .cif.gz,
validated to have all five required chains):
$ tcren fetch-recent --discover --after 2024-01-01
What tcren can answer#
From a single TCR–peptide–MHC structure (crystal or model), each task is one command:
question |
command |
|---|---|
Which candidate epitopes does this TCR recognise? |
|
Is this peptide a strong binder for this TCR? |
|
How does a mutation change recognition (ΔΔG)? |
|
Is this modelled TCR a binder or a non-binder? |
|
Three-interface energy Φ (and ΔΦ, and Q)? |
|
Substitute a peptide and relax its pose? |
|
Case studies#
Screen candidate epitopes.
tcren scoreranks a candidate list by TCRen energy on the native contact map (no re-docking) — the drop-in for the originalrun_TCRen.R. Addtcren rankto place the top hit’s energy in a random-background percentile.Neoantigen / alanine ΔΔG.
tcren ddgre-scores mutants on the native contacts:--alanine-scanfor a per-position sensitivity profile, or--mutant(repeatable) for specific neoantigen substitutions. Positive ΔΔG = stabilising (the mutant scores lower).Rank candidate TCRs against a fixed pMHC.
tcren binderscores AlphaFold/TCRmodel2 models from interface geometry (size, dual-chain balance, H-bonds, buried ΔSASA) plus a CDR1/2-vs-CDR3α TCRen term — AlphaFold-orthogonal signal that ranks binders above non-binders using no external tool. Seetcren.binder.binder_score().Substitute + refine a pose.
tcren refine --substitutethreads a new equal-length peptide onto the backbone and runs a knowledge-based Monte-Carlo refinement scored by the DOPE atom-level potential — deliberately independent of the TCRen/MJ scoring potentials so the pose is not optimised against the quantity it is later scored with. This is not physics relaxation; use Rosetta FlexPepDock for that.Graft a TCR onto another pMHC (build a chimera).
tcren substitute-tcrtakes a host and a donor TCR:pMHC complex and returns a new complex with the host peptide + MHC and the donor TCR.--by mhcsuperposes the two MHC grooves, so the donor TCR keeps its native docking geometry;--by tcrsuperposes the two TCRs, so the donor TCR inherits the host’s docking pose. Useful for cross-docking and for building TCR:pMHC models to score. As a library call:from tcren import substitute_tcr from tcren.annotation import classify_chains from tcren.mhc import annotate_mhc from tcren.structure import import_structure host = import_structure("hostA.pdb"); classify_chains(host); annotate_mhc(host) donor = import_structure("donorB.pdb"); classify_chains(donor); annotate_mhc(donor) chimera = substitute_tcr(host, donor, by="mhc") # host pMHC + donor TCR
Interface energy and koff mechanics.
tcren energyreports the DOPE interaction energy across the peptide↔partner interface (e_native; add--relaxfor the post-refinement energy and the gap — the ΔΔG scorer).tcren mechanicstreats the contact map as a network of breakable springs and reports the stiffness tensor (K_tens/K_shear), a steered-rupture force/work, and coupling residues. On ATLAS these mechanical measures track the dissociation off-rate (koff, a Bell–Evans rupture quantity) better than the equilibrium ΔG/Kd — the physically apt axis for the TCR mechanosensor. Both are also library calls:from tcren import interface_energy, stiffness_tensor, rupture e = interface_energy(structure) # DOPE interface energy (lower = more favourable) k = stiffness_tensor(structure) # {"K_tens": ..., "K_shear": ..., "n_spring": ...} r = rupture(structure, direction="tensile") # {"rupture_force": ..., "rupture_work": ...}
Library#
Score candidate epitopes against a structure:
from tcren import parse_structure, ContactMap, score_peptides
from tcren.annotation import classify_chains
from tcren.potential import tcren
structure = parse_structure("complex.pdb.gz") # .pdb/.cif/.pdb.gz/.cif.gz
classify_chains(structure, organism="human") # TRA/TRB via arda, peptide, MHC
contact_map = ContactMap.from_structure(structure)
ranked = score_peptides(contact_map, ["KQWLVWLFL", "RLLHPHHPL"], tcren())
Iterate over a batch (file, directory, or .tar.gz):
from tcren.structure import iter_structures
for pdb_id, structure in iter_structures("batch.tar.gz"):
classify_chains(structure, organism="human")
...
Orient into the canonical frame, layer contacts, and read the docking geometry:
from tcren.mhc import annotate_mhc
from tcren.orient import canonicalize_structure, superimpose, docking_angles
from tcren.contacts import multi_contacts, ContactDefinition
annotate_mhc(structure)
oriented, info = canonicalize_structure(structure) # z=MHC->TCR, y=peptide, x=thin
oriented, info = superimpose(structure) # onto data/Canonical2026 (class+species ensemble)
layers = multi_contacts(structure, ContactDefinition(d1=5, d2=8, d3=12))
angles = docking_angles(structure) # crossing + incident angle
Build a 2D complementarity map and summarise contacts by region pair:
from tcren.project2d import (project_structure, residue_markup_table,
contacts_table, region_pair_summary)
from tcren.viz import render_complementarity_map
proj = project_structure(structure)
svg = render_complementarity_map(residue_markup_table(structure, proj),
contacts=contacts_table(structure, threshold=5.0))
summary = region_pair_summary(structure, kind="closest") # also "cb" (8 A) / "ca" (12 A)
Data#
Structures come from the Hugging Face dataset
isalgo/tcren_structures (all gzipped):
Native2022 (the 2022 paper set), Native2026 (the 2026 set the current potential is derived
from), and Canonical2026 (Native2026 re-oriented). When orienting a new complex an installed
library lazily fetches the canonical reference structures (1ao7/1fyt) from the Hub, so no local
dataset is required.