vdjtools#

TCR/BCR immune-repertoire analysis — v2, a clean-room rewrite in Python + C++.

Standardised on the AIRR schema and polars DataFrames with minimal object-orientation, built on the antigenomics ecosystem (seqtree, vdjmatch, arda).

Note

v3.0.0 — the native V(D)J model engine plus the full analytics suite (diversity, overlap/TCRnet, preprocessing, biomarkers, single-cell), longitudinal clonotype dynamics (paired expansion testing + the VDJtrack recapture model), CDR features, and legacy-format ingestion (MiXcr, MiGec, immunoSEQ, IMGT/HighV-QUEST, Vidjil, RTCR, TRUST4, arda). Clonotype columns follow the AIRR junction convention (junction_nt / junction_aa). The legacy Groovy/Java vdjtools (v1.x) lives on the legacy-1.x branch and its releases remain available under the repository’s tags.

New here? The User guide has runnable examples for every module — loading data, diversity, overlap/TCRnet, preprocessing, biomarkers, single-cell, and the model engine.

Quickstart — recombination model engine#

Precomputed models for all 7 human loci ship in the wheel (no OLGA or download needed):

from vdjtools.model import load_bundled, native
from vdjtools.model.generate import generate

model = load_bundled("TRB", source="olga")        # or source="learned" (fit to real repertoires)
native.pgen_nt(model, "TGTGCCAGCAGC...")           # nucleotide generation probability (native C++)
native.pgen_aa(model, "CASSLAPGATNEKLFF")          # amino-acid Pgen (codon-marginalised)
native.pgen_aa(model, "CASSLAPGATNEKLFF", mismatches=1)  # + the whole Hamming-1 ball
native.pgen_aa_batch(model, seqs, mismatches=1, threads=0)  # many CDR3s, thread-parallel (~11x)
generate(model, 1000)                              # sample a repertoire -> polars DataFrame

Matches OLGA’s Pgen to machine precision across all 7 loci, adds tandem-D (D-D) support, and learns models from your own reads (vdjtools.model.infer.infer_native()). Explore any model’s recombination Bayes net interactively with marimo edit examples/model_explorer.py.

Command line#

pip install vdjtools installs the vdjtools command — the model engine (OLGA/IGoR-style) and the repertoire analytics (sample files or a metadata table, like the legacy tool):

vdjtools models                                # list the bundled models
vdjtools generate -m TRB -n 1000 -o gen.tsv    # sample sequences   (cf. olga-generate_sequences)
vdjtools pgen seqs.tsv -m TRB -o pgen.tsv      # Pgen per CDR3       (cf. olga-compute_pgen)

vdjtools convert mixcr.txt.gz -o clones.parquet   # any format → canonical TSV / Parquet
vdjtools filter clones.parquet --coding --min-freq 1e-4 -o coding.tsv
vdjtools downsample clones.parquet 100000 -o ds.tsv

vdjtools diversity     sampleA.tsv sampleB.tsv -o diversity.tsv
vdjtools overlap       *.tsv -o overlap.tsv
vdjtools segment-usage *.tsv --segment v -o usage.tsv
vdjtools spectratype   --cohort cohort_parquet/ -o spectra.tsv     # one streamed pass
vdjtools dynamics      day0.tsv day15.tsv -o tracked.tsv           # paired expansion test

Native vdjtools, AIRR, Parquet, and third-party inputs are auto-detected; every command writes to -o — TSV, or Parquet when the path ends in .parquet / .pq — or to stdout. Cohort commands parallelise over samples with -t/--threads or stream a Parquet cohort with --cohort. Run vdjtools <command> --help for options.

Performance#

The Pgen / generation / EM / diversity hot paths are a native C++ (pybind11) core; everything else is polars. On an Apple M3 (single thread, bundled human TRB model): nucleotide Pgen ~0.5 ms/seq (9× OLGA, single-D VDJ), amino-acid Pgen ~0.6–0.9 ms/seq (8.6× OLGA, exact to 1e-15), the Hamming-1 ball ~15 ms/seq (8.7×), sequence generation ~32 000 seq/s. Both nt and aa Pgen use the same transfer-matrix DP (an in-frame CDR3 is an aa query with one codon fixed per position); nt is exact vs OLGA on all 7 loci. Batched Pgen / 1-mismatch over many CDR3s parallelises over sequences (vdjtools.model.native.pgen_aa_batch(), ~11× on 16 cores, bitwise-identical to serial); the EM E-step parallelises over reads (~6.7× on 8 threads), and diversity / rarefaction run on a native iNEXT kernel (bootstrap + parallel batch). Memory stays light — ~63 MB resident for import vdjtools plus one model, ~123 MB with all seven bundled models.

Capabilities (see the API reference):

  • IO — canonical AIRR junction clonotype frame (junction_nt / junction_aa); readers for native vdjtools, AIRR TSV, Parquet, and converters for MiXcr (incl. C-gene / isotype), MiGec, immunoSEQ (v1/v2), IMGT/HighV-QUEST, Vidjil, RTCR, TRUST4, and arda AIRR output (vdjtools.io.convert); metadata-driven batch + cohorts.

  • Model — native V(D)J recombination model: Pgen (nt / aa / 1-mismatch / V/J-agnostic / thread-parallel batch), sequence generation, EM inference, and tandem-D (D-D) support — a native pybind11 core that supersedes OLGA and IGoR. Concordant with OLGA on all 7 loci; bundled models.

  • Stats — diversity, spectratype, V/J/VJ usage.

  • Features — CDR physicochemical profiles, k-mer / V+k-mer summaries.

  • Overlap — sample overlap and TCRnet (via vdjmatch/seqtree), similarity-aware overlap, clustering.

  • Preprocess — downsampling, error-correction, batch-effect correction, pooling/joining.

  • Biomarker — incidence-based association (Fisher) and metaclonotype grouping.

  • Dynamics — longitudinal clonotype tracking: paired within-donor expansion testing, the VDJtrack size-bucket recapture model, metaclonotype-grouped testing, and an edgeR NB-exact caller.

  • Single-cell — AIRR Cell / 10x interoperability, chain pairing + QC, paired α/β Pgen, and an AnnData / scverse bridge (.h5ad / .zarr).