Extract TCR:pMHC specificity data from raw source files (papers, supplementary tables, XLS, PDF, 10X output, AIRR-format) and produce a VDJdb-formatted TSV chunk ready for /format and /proofread.
Scanned 8/30/2026
Install to Claude Code
npx -y skills add antigenomics/vdjdb-db --skill vdjdb-extract --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Vdjdb Extract?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/antigenomics-vdjdb-extract)More formats (shields.io, HTML) on the badges page.
---
name: vdjdb-extract
description: Extract TCR:pMHC specificity data from raw source files (papers, supplementary tables, XLS, PDF, 10X output, AIRR-format) and produce a VDJdb-formatted TSV chunk ready for /format and /proofread.
---
# /extract — VDJdb Data Extraction Skill
## Purpose
Extract T-cell receptor antigen-specificity records from arbitrary source files and write a single TSV in VDJdb chunk format. Every value written to the output **must be verified back against the original source** to prevent hallucinations. This skill feeds directly into `/format` and `/proofread`.
## Invocation
```
/extract [path-to-folder-or-file]
```
The input may be a folder or individual file(s) containing any mix of:
- Supplementary Excel/CSV/TSV tables
- PDF manuscripts or supplementary PDFs
- Plain-text files (FASTA, exported tables)
- 10X Genomics `filtered_contig_annotations.csv` / clonotype files
- AIRR-format TSV files (`productive`, `v_call`, `j_call`, `cdr3_aa` columns)
- **Adaptive Biotech ImmunoSEQ** exports (TSV; gene columns use `TCRB`/`TCRA` prefix with zero-padded numbers like `TCRBV06-05*01` — flag all gene names for conversion in `/format`)
- Jupyter notebooks or scripts used by the authors
If the user limits scope (e.g., "only beta chains", "skip MHC data"), respect that limit and note it in the extraction log.
### Excel-specific pitfalls (apply when source is .xlsx/.xls)
1. **Embedded sub-header rows**: Submitters often repeat column headers mid-table to mark new donors or groups. These appear as rows where gene columns contain `TCRα`, `TCRβ`, `TRAV`, `TRBV`, `CDR3α`, `CDR3β`, `CDR3` (literal text). **Filter by checking both CDR3 and gene columns** — some sub-header rows have blank CDR3 cells and `TCRα`/`TCRβ` only in gene columns; the simpler "check CDR3 column for header text" filter will miss them.
2. **Allele suffix with functionality code**: Some cells contain the gene name formatted as `TRAV16*01 F` (allele + space + IMGT functionality code). Standard regex `\*\d+\s*$` fails because `F` follows the space. Use `re.sub(r'\*.*$', '', v).strip()` to strip everything from `*` onwards.
3. **Excel formula artifacts**: Cell merging or formula errors can produce values like `TRAJ3+D107:D1082` (gene name + cell reference). Strip everything after `+` to recover the gene: `val.split('+')[0].strip()`.
4. **TRBJ/TRBD column swap**: Submitters sometimes place TRBJ before TRBD in their table despite the column header saying the opposite. **Always verify by gene name prefix** (e.g., `TRBJ2-7*01` starting with `TRBJ` → it is a J gene regardless of which column it's in). Apply swap correction when prefix contradicts column header.
5. **Non-standard characters in CDR3**: Excel auto-correct, copy-paste artefacts, or annotation notations can introduce characters like `#`, `X`, `*` in CDR3 fields. Exclude rows containing non-20-AA characters; log the exclusion.
6. **Frequency as Excel formula**: Cells like `=I4/26*100` appear as literal strings if the workbook is loaded without `data_only=True`. Always use `data_only=True` in openpyxl to get cached computed values.
---
## ⚠️ Absolute Requirements (Non-Negotiable)
### CDR3 sequences
- Must contain **only standard amino acids**: `ARNDCQEGHILKMFPSTWYV`
- Canonical form: starts with `C`, ends with `F` or `W`
- Minimum length: **4 residues**
**Handling non-standard CDR3s:**
| Case | Action |
|---|---|
| Contains non-20-AA character (`X`, `B`, `#`, `*`, etc.) | **Exclude the row** — log it; likely a data artefact |
| Does not start with `C` | **Keep in `chunks/`** — flag in extraction log; VDJdb build marks it non-canonical automatically |
| Ends with residue other than `F`/`W` | **Keep in `chunks/`** — flag in extraction log |
| Contains genuine modified/non-natural residues | **Move to `chunks_with_unconventional_aa/`** after confirming with user |
> `chunks_with_unconventional_aa/` is **only** for non-standard amino acids (beyond the 20 canonical). Non-canonical start/end residues stay in `chunks/`.
### Epitope sequences
- Must be **standard amino acids only**
- If authors describe a chemical modification, a non-peptide antigen, or a long peptide pool: **flag prominently** in the log and ask before including
### References — strict enforcement
Only these formats are acceptable in `reference.id`:
| Format | Example | Notes |
|---|---|---|
| `PMID:XXXXXXX` | `PMID:28975614` | Strongly preferred; numeric only after colon |
| `doi:10.XXXX/...` | `doi:10.1016/j.immuni.2023.01.001` | Lowercase `doi:`, no URL prefix |
| Preprint URL | `https://www.biorxiv.org/content/10.1101/2024.01.01.123456` | Full URL |
| Unpublished | `unpublished: Submitter Name YYYY-MM-DD` | For submissions without a publication |
**NEVER invent or guess a PMID.** If uncertain, leave blank and ask the user. DOI and preprint URLs must be quoted exactly from the source.
### Hallucination prevention (mandatory for every extracted value)
After extracting any amino acid sequence, gene name, species name, MHC allele, or reference ID:
1. Run a grep or direct text search in the **original source file** to confirm the exact string is present
2. Log the verification result (found / not found / found with minor variant)
3. If the value **cannot be confirmed** in the source: mark as `[UNVERIFIED]` and do **not** include it without explicit user approval
---
## Step-by-Step Workflow
### Step 1 — Survey the source folder
1. List all files and identify types (PDF, XLS, TSV, CSV, FASTQ, etc.)
2. Note which files are likely to contain: TCR sequences, antigen/epitope data, MHC/HLA data, methods, references
3. Share the inventory with the user before proceeding if the folder contains more than 3 files or has an unclear structure
### Step 2 — Build a cross-reference graph
Source data is often spread across multiple files. Build an explicit graph:
1. Identify all **ID columns** in each file: barcode, clone ID, sample ID, donor ID, clonotype ID, barcode, well ID, etc.
2. Determine which IDs appear in multiple files and can be used to join records
3. Perform the join; log the join keys used
**Ambiguities** (one-to-many links, missing join keys, contradictory values between files) must be logged **immediately**. Do not silently pick one option.
### Step 3 — Extract TCR complex fields
For each record, extract the following. Leave blank if absent — **never use a placeholder string** (`NA`, `N/A`, `null`, `nan`, `-`, `.`).
| VDJdb field | What to look for | Verification |
|---|---|---|
| `cdr3.alpha` | Alpha chain CDR3 amino acid sequence | grep in source |
| `v.alpha` | TRAV gene (IMGT style preferred; note if not IMGT) | grep in source |
| `j.alpha` | TRAJ gene | grep in source |
| `cdr3.beta` | Beta chain CDR3 amino acid sequence | grep in source |
| `v.beta` | TRBV gene | grep in source |
| `d.beta` | TRBD gene (often missing; leave blank) | grep if present |
| `j.beta` | TRBJ gene | grep in source |
| `species` | Organism (`HomoSapiens`, `MusMusculus`, `RattusNorvegicus`, `MacacaMulatta`) | confirm from text |
| `mhc.a` | First MHC chain (e.g., `HLA-A*02:01`, `H-2Db`) | grep in source |
| `mhc.b` | Second MHC chain (`B2M` for MHC-I; β-chain allele for MHC-II) | grep in source |
| `mhc.class` | `MHCI` or `MHCII` | confirm from context |
| `antigen.epitope` | Epitope amino acid sequence | grep in source |
| `antigen.gene` | Antigen gene name (e.g., `pp65`, `NP`, `MART-1`) | grep in source |
| `antigen.species` | Antigen origin (e.g., `CMV`, `InfluenzaA`, `HomoSapiens`) | confirm from text |
| `reference.id` | PMID, DOI, or preprint URL | strict format check + grep |
**At least one of `cdr3.alpha` or `cdr3.beta` must be non-blank per row.**
**Both `mhc.a` and `mhc.b` must be filled if MHC data exists.**
Cross-reference epitopes against `patches/antigen_epitope_species_gene.dict` — if the epitope is already known, use the dict's gene and species values.
### Step 4 — Extract method fields
These fields directly affect the VDJdb confidence score (0–3) computed by `py_src/ScoreFactory.py`. Extract them carefully from the methods section.
| Field | Recognised values | Notes |
|---|---|---|
| `method.identification` | `tetramer-sort`, `dextramer-sort`, `pelimer-sort`, `pentamer-sort`, `antigen-loaded-targets`, `antigen-expressing-targets`, `beads`, `cultured-T-cells`, `limiting-dilution-cloning`, `tetramer-umi`, `cd8null-tetramer` | Multiple values comma-separated, no spaces |
| `method.frequency` | `X/X` (e.g., `7/30`), `X%`, or decimal fraction | Fraction format preferred |
| `method.singlecell` | `yes` if single-cell sequencing was used; blank otherwise | |
| `method.sequencing` | `sanger`, `rna-seq`, `amplicon-seq` | |
| `method.verification` | `tetramer-stain`, `dextramer-stain`, `direct`, `restimulation`, `co-culture`, `antigen-loaded-targets`, `antigen-expressing-targets`, `beads` | |
If the paper uses a method not in the above lists, **do not force it into an existing category**. Log it as a "Novel method" candidate for extending the VDJdb specification.
> **Score shortcut:** If a PDB structure ID is available, record it in `meta.structure.id` — this grants score 3 automatically, bypassing all other scoring logic.
### Step 5 — Extract metadata fields
Fill as many of the 12 meta columns as the source supports. Leave others blank.
| Field | Description |
|---|---|
| `meta.study.id` | Internal study identifier used in the paper |
| `meta.cell.subset` | T cell subset (`CD8+`, `CD4+CD25+`, etc.) |
| `meta.subset.frequency` | Clone frequency within the cell subset |
| `meta.subject.cohort` | Donor cohort (`healthy`, `HIV+`, `CMV-seroneg`, etc.) |
| `meta.subject.id` | Donor/patient identifier |
| `meta.replica.id` | Replicate or timepoint identifier |
| `meta.clone.id` | T cell clone identifier or barcode |
| `meta.epitope.id` | Short epitope label from the paper (e.g., `FL10`) |
| `meta.tissue` | `PBMC`, `spleen`, `TIL`, `TCL`, etc. |
| `meta.donor.MHC` | Donor HLA typing if reported |
| `meta.donor.MHC.method` | HLA typing method if reported |
| `meta.structure.id` | PDB ID if a structure was solved for this complex |
| `comment` | Any important note not captured elsewhere (max 140 characters) |
### Step 6 — Assemble the output TSV
**Canonical column order** (must match exactly):
```
chunk.id
cdr3.alpha v.alpha j.alpha cdr3.beta v.beta d.beta j.beta
species mhc.a mhc.b mhc.class antigen.epitope antigen.gene antigen.species
reference.id
method.identification method.frequency method.singlecell method.sequencing method.verification
meta.study.id meta.cell.subset meta.subset.frequency meta.subject.cohort meta.subject.id
meta.replica.id meta.clone.id meta.epitope.id meta.tissue
meta.donor.MHC meta.donor.MHC.method meta.structure.id
comment
```
**Formatting rules:**
- Tab-separated, UTF-8, Unix line endings (LF)
- `chunk.id`: sequential integers starting from 1
- Blank fields: truly empty (no quotes, no `NA`, no `-`)
- No trailing whitespace; no quoted fields (TSV, not CSV)
- `comment` is optional — include column only if at least one row has a comment
### Step 7 — Write the extraction log
Write `<output_basename>_extraction_log.txt` containing:
1. **Source inventory**: all files found, their types, and assigned roles
2. **Cross-reference graph**: which ID columns were used to link which files, and join cardinality
3. **Ambiguities**: every unclear/ambiguous case and the decision made (or flagged for user)
4. **Verification results**: for each field, confirm or report failure to verify in source
5. **Unverified values**: any value included at user direction despite not being directly verifiable
6. **Novel methods**: identification/verification methods not in the current VDJdb vocabulary
7. **Excluded records**: rows dropped and the reason (failed canonical check, missing required fields, etc.)
8. **Scope restrictions**: any user-imposed limits on what was extracted
---
## Validation Reference Files
| File | Purpose |
|---|---|
| `proofreading/imgt_alleles.tsv.gz` | **Primary** V/D/J gene ID authority — check all extracted gene names here first |
| `proofreading/imgt.md` | IMGT nomenclature rules and gene structure explanation |
| `proofreading/mhc_alleles.tsv.gz` | **Primary** HLA allele authority — check all extracted human MHC alleles here |
| `proofreading/mhc.md` | MHC/HLA naming rules, class I vs II, non-human conventions |
| `patches/IGM_nomenclature_table.tsv` | Secondary V/D/J fallback (existing repo file) |
| `patches/nomenclature.conversions` | Old-style → IMGT gene name conversions |
| `patches/antigen_epitope_species_gene.dict` | Known epitope → antigen.gene/antigen.species mappings |
| `py_src/ScoreFactory.py` | Confidence score logic and method vocabulary |
| `README.md` | VDJdb column specification |
---
## Output
- **Primary output**: `<PMID_xxxxxxx>_unformatted.txt` — raw VDJdb TSV (gene names not yet IMGT-normalised)
- **Log**: `<PMID_xxxxxxx>_extraction_log.txt` — full provenance and ambiguity record
Suggest the output filename based on PMID if available (e.g., `PMID_40713946_unformatted.txt`), otherwise use the folder name or ask the user.
---
## Next Steps
1. Run `/format` on the output to normalise gene names, species, and MHC alleles to IMGT standard
2. Run `/proofread` to validate against QC scripts in `py_src/`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!