Self-contained pipeline for downloading, curating, and extracting binding grooves from MHC protein sequences.
pip install mhcseqs
For development:
git clone https://github.com/openvax/mhcseqs.git
cd mhcseqs
./develop.sh # pip install -e ".[dev]"
./test.sh # pytest
./lint.sh # ruff
Requirements: Python 3.10+, mhcgnomes (installed automatically).
mhcseqs buildDownloads FASTA sources (IMGT/HLA + IPD-MHC), parses alleles, selects two-field representatives, extracts binding grooves, and runs validation.
mhcseqs build [--output-dir DIR] [--data-dir DIR]
| Option | Description |
|---|---|
--output-dir | Directory for output CSVs (default: ~/.cache/mhcseqs) |
--data-dir | Directory for downloaded FASTA files (default: ~/.cache/mhcseqs/fasta) |
Produces four files:
| File | Description |
|---|---|
mhc-seqs-raw.csv | Every parsed protein entry from all sources |
mhc-full-seqs.csv | One representative per two-field allele: full sequence, groove decomposition, and metadata |
mhc-merge-report.txt | Details on allele group merging decisions |
mhc-validation-report.txt | Sanity check results |
mhcseqs lookupQuery built CSVs by allele name.
mhcseqs lookup "HLA-A*02:01"
mhcseqs lookup "Mamu-A1*001:01"
mhcseqs --versionPrint the installed version.
import mhcseqs
# Build the database (downloads FASTA sources, only needed once)
paths = mhcseqs.build()
# Look up any allele → AlleleRecord with everything
r = mhcseqs.lookup("HLA-A*02:01")
r.allele # "HLA-A*02:01" (two-field)
r.full_allele # "HLA-A*02:01:01:100" (full resolution)
r.sequence # full protein (with signal peptide)
r.mature_sequence # signal peptide removed (computed property)
r.mature_start # signal peptide length (24)
r.groove1 # α1 domain (90 aa)
r.groove2 # α2 domain (93 aa)
r.ig_domain # α3 Ig-fold (95 aa)
r.tail # TM + cytoplasmic
r.species_category # "human"
# Apply mutations (IEDB-style, e.g. "K66A")
m = mhcseqs.lookup("HLA-A*02:01", mutations=["K66A", "D77S"])
import mhcseqs
# As a DataFrame (full sequence + groove decomposition + metadata)
df = mhcseqs.load_sequences_dataframe()
# Or as a list of dicts (no pandas dependency)
rows = mhcseqs.load_sequences_dict()
mhcseqs.normalize_species("Macaca mulatta") # "macaque"
mhcseqs.normalize_mhc_species("macaque") # "nhp"
mhcseqs.get_latin_name("macaque") # "Macaca mulatta"
mhcseqs.get_canonical_prefix("macaque") # "Mamu"
mhcseqs.normalize_allele_name("A0201") # "HLA-A*02:01"
mhcseqs.infer_gene("HLA-A*02:01") # "A"
mhcseqs.infer_mhc_class("HLA-A*02:01") # "I"
| Column | Description |
|---|---|
allele_raw | Original allele token from FASTA header |
allele_normalized | Full-resolution name from mhcgnomes |
two_field_allele | Truncated to two-field / "4-digit" resolution |
gene | Gene name (e.g. A, DRB1, DQA1) |
mhc_class | I or II |
chain | alpha, beta, or B2M |
species | Species name (usually Latin) |
species_category | One of: human, nhp, murine, other_mammal, bird, fish, other_vertebrate |
species_prefix | MHC naming prefix (HLA, Mamu, SLA, etc.) |
source | imgt, ipd_mhc, uniprot_curated, or uniprot_reference |
source_id | Database accession (HLA00001, NHP00001, P01901, etc.) |
sequence | Full protein sequence |
has_signal_peptide | Whether a signal peptide was detected |
signal_peptide_len | Inferred signal peptide length |
is_null, is_questionable, is_pseudogene | Allele status flags |
Shares columns with the raw CSV: two_field_allele, gene, mhc_class,
chain, species, species_category, species_prefix,
source, seq_len, sequence, is_null,
is_questionable, is_pseudogene. Additional columns:
| Column | Description |
|---|---|
representative_allele | Specific full-resolution allele chosen |
protein_seq_selection | Selection method (unique, nested_longest, etc.) |
mature_start | Offset where mature protein begins |
mature_sequence | Protein with signal peptide removed |
groove1 | N-terminal groove half: α1 domain (class I & II alpha chains) |
groove2 | C-terminal groove half: α2 domain (class I) or β1 domain (class II beta) |
groove_seq | Concatenation of groove1 + groove2 |
ig_domain | Ig support domain: α3 (class I), α2 (class II α), β2 (class II β) |
tail | Transmembrane + cytoplasmic region |
domain_architecture | Typed domain grammar, e.g. signal_peptide>g_alpha1>g_alpha2>c1_alpha3>transmembrane |
domain_spans | Human-readable domain coordinates in the raw sequence |
groove_status | Groove parse outcome (ok, missing_groove, fragment_fallback, etc.) |
anchor_type | Which Cys pair anchored the parse |
is_functional | Groove parseable AND not null/pseudogene |
The parser is alignment-free and holistic. It scores signal peptide, groove, support-domain, and TM evidence together instead of anchoring the parse on one fixed mature-position constant.
Class I alpha: signal_peptide? -> g_alpha1 -> g_alpha2 -> c1_alpha3 -> TM? -> tail?
Class II alpha: signal_peptide? -> g_alpha1 -> c1_alpha2 -> TM? -> tail?
Class II beta: signal_peptide? -> g_beta1 -> c1_beta2 -> TM? -> tail?
The main evidence sources are:
-3/-1 compatibility, and impossible-pair exclusions.c1+14.| Status | Meaning |
|---|---|
ok | Full decomposition from the main structural grammar |
inferred_from_alpha3 | Class I salvage parse using only a downstream α3 C-like anchor |
beta1_only_fallback | Class II β salvage parse using only the β1 groove pair |
alpha1_only | Class-I fragment consistent with α1 / exon 2 only |
alpha2_only | Class-I fragment consistent with α2 / exon 3 only |
fragment_fallback | Short fragment retained as the observable groove half |
missing_groove | No recoverable groove architecture from the available evidence |
non_classical | Non-classical class-I lineage flagged post-parse |
short | Groove half too short to look functionally peptide-binding |
not_applicable | Pipeline-level non-groove row, mainly B2M in build outputs |
-2/+1 cleavage effects.+1 Pro.Every entry is assigned a species_category from a 10-class taxonomy:
| Category | Fine-grained species included |
|---|---|
human | Homo sapiens |
nhp | macaque, chimpanzee, gorilla, orangutan, baboon, other NHP |
murine | mouse, rat |
ungulate | cattle, pig, horse, sheep, goat |
carnivore | dog, cat |
cetacean | whale, dolphin |
other_mammal | rabbit, other mammals |
bird | chicken, other birds |
fish | salmon, zebrafish, other fish |
other_vertebrate | reptiles, amphibians |
Core groove extraction. Key functions:
extract_groove(seq, mhc_class, ...) — main dispatcherparse_class_i(seq, ...) — class I alpha chain parserparse_class_ii_alpha(seq, ...) — class II alpha chain parserparse_class_ii_beta(seq, ...) — class II beta chain parserfind_cys_pairs(seq) — locate Ig-fold Cys-Cys pairsAlleleRecord — dataclass with all parsed fieldsAllele name parsing via mhcgnomes:
parse_allele_name(name) — parse with mhcgnomesnormalize_allele_name(name) — canonical two-field forminfer_gene(allele) — extract gene (e.g. "A", "DRB1")infer_mhc_class(allele) — "I" or "II"Species normalization:
normalize_species(raw) — 29-class fine-grainednormalize_mhc_species(raw) — 7-class categoryget_latin_name(raw) — canonical Latin nameget_canonical_prefix(raw) — MHC naming prefixLATIN_NAMES, CANONICAL_MHC_PREFIXES — lookup dictsTwo-step build pipeline:
build_raw_index(fasta_paths, out_csv) — Step 1: parse FASTA → raw CSVbuild_full_seqs(raw_csv, out_csv) — Step 2: select representatives + extract groovesPost-build sanity checks:
validate_build(raw_csv, full_csv) — run all checksformat_validation_report(warnings, stats) — human-readable reportFASTA source downloading:
download_all(dest_dir) — download IMGT/HLA + IPD-MHCSOURCES — dict of source URLs and metadataGenerated by mhcseqs. Apache License 2.0.