The single-cell TCR-Seq (VDJ) assay resolves the paired T-cell receptor sequence of individual T cells, and is a component of the CMI-Flu prediction challenge. It accompanies the scRNA/TCR-Seq data. An overview of all the data, including links to more detailed descriptions of the other data, may be found at CMI-x .

Experimental protocol

PBMCs were processed for single-cell immune profiling on the 10x Genomics Chromium platform, and TCR (VDJ) libraries were sequenced and assembled into contig annotations using Cell Ranger vdj against the GRCh38 V(D)J reference.

Data Standardization

  • Contigs were assembled and annotated with CellRanger vdj.
  • The published table is restricted to contigs called as cells (is_cell), assembled at high_confidence, and productive.

The Data

The VDJ data consists of 1 table : 2025LJI_vdj.tsv, containing paired single-cell TCR sequences for the 2025LJI cohort at the pre-vaccination (Day 0) timepoint. These data are not directly linked to a specific prediction task, but can be leveraged to build more robust models and improve predictions for other data types within the 2025LJI prediction challenge cohort.

Data tables

Single-cell TCR-Seq (VDJ) Assay
Data dictionary
Column Description
sample Sample / 10x library identifier.
barcode Cell barcode (10x GEM barcode); identifies the individual cell within a sample.
is_cell Whether the barcode was called as a cell (TRUE throughout the published table).
contig_id Unique identifier of the assembled contig.
high_confidence Whether the contig is a high-confidence VDJ assembly (TRUE throughout).
length Contig length (nucleotides).
chain Receptor chain: TRA (alpha), TRB (beta), or TRD (delta).
v_gene V gene assignment (e.g. TRBV20-1).
d_gene D gene assignment. NA for TRA and where no D segment was called.
j_gene J gene assignment.
c_gene Constant gene assignment (e.g. TRAC, TRBC1, TRBC2).
full_length Whether the contig spans a full-length V(D)J rearrangement.
productive Whether the contig is productive (in-frame, no stop codon). TRUE throughout.
fwr1 Framework region 1, amino acid sequence.
fwr1_nt Framework region 1, nucleotide sequence.
cdr1 CDR1, amino acid sequence.
cdr1_nt CDR1, nucleotide sequence.
fwr2 Framework region 2, amino acid sequence.
fwr2_nt Framework region 2, nucleotide sequence.
cdr2 CDR2, amino acid sequence.
cdr2_nt CDR2, nucleotide sequence.
fwr3 Framework region 3, amino acid sequence.
fwr3_nt Framework region 3, nucleotide sequence.
cdr3 CDR3, amino acid sequence (the principal antigen-contacting loop).
cdr3_nt CDR3, nucleotide sequence.
fwr4 Framework region 4, amino acid sequence.
fwr4_nt Framework region 4, nucleotide sequence.
reads Number of sequencing reads supporting the contig.
umis Number of UMIs (unique molecules) supporting the contig.
raw_clonotype_id Cell Ranger clonotype assignment (per sample). Cells sharing a clonotype have matching paired receptor sequences.
raw_consensus_id Identifier of the consensus sequence for this clonotype/chain.
exact_subclonotype_id Exact-subclonotype identifier within the clonotype.
experiment Experiment / GEM batch identifier (e.g. aim1_gem1).
participant_id Donor ID, in the format studyID.subjectID (links to participants.tsv).
timepoint Days relative to influenza vaccination (0).
study_accession Study identifier. Links to the investigations.tsv file.

Data exploration

Data preview:

library(tidyverse)

vdj <- read_tsv("../datasets/260512/train/2025LJI_vdj.tsv", show_col_types = FALSE)
head(vdj)
## # A tibble: 6 × 36
##   sample    barcode is_cell contig_id high_confidence length chain v_gene d_gene
##   <chr>     <chr>   <lgl>   <chr>     <lgl>            <dbl> <chr> <chr>  <chr> 
## 1 5670-LI-2 AAACGA… TRUE    AAACGATC… TRUE               506 TRB   TRBV5… <NA>  
## 2 5670-LI-2 AAACGA… TRUE    AAACGATC… TRUE               472 TRA   TRAV10 <NA>  
## 3 5670-LI-2 AAACGG… TRUE    AAACGGCC… TRUE               519 TRA   TRAV39 <NA>  
## 4 5670-LI-2 AAAGCC… TRUE    AAAGCCTG… TRUE               495 TRB   TRBV27 <NA>  
## 5 5670-LI-2 AAAGCC… TRUE    AAAGCCTG… TRUE               484 TRA   TRAV21 <NA>  
## 6 5670-LI-2 AAAGGA… TRUE    AAAGGAAC… TRUE               492 TRA   TRAV9… <NA>  
## # ℹ 27 more variables: j_gene <chr>, c_gene <chr>, full_length <lgl>,
## #   productive <lgl>, fwr1 <chr>, fwr1_nt <chr>, cdr1 <chr>, cdr1_nt <chr>,
## #   fwr2 <chr>, fwr2_nt <chr>, cdr2 <chr>, cdr2_nt <chr>, fwr3 <chr>,
## #   fwr3_nt <chr>, cdr3 <chr>, cdr3_nt <chr>, fwr4 <chr>, fwr4_nt <chr>,
## #   reads <dbl>, umis <dbl>, raw_clonotype_id <chr>, raw_consensus_id <chr>,
## #   exact_subclonotype_id <dbl>, experiment <chr>, participant_id <chr>,
## #   timepoint <dbl>, study_accession <chr>
print("Contigs by chain:")
## [1] "Contigs by chain:"
table(vdj$chain)
## 
##   TRA   TRB   TRD 
## 43418 49615     2

TRB V-gene usage. The plot below shows the 20 most frequently used TRB (beta chain) V genes across all cells, as a percentage of TRB contigs.

trbv <- vdj %>%
  filter(chain == "TRB", !is.na(v_gene)) %>%
  count(v_gene, name = "n") %>%
  mutate(pct = 100 * n / sum(n)) %>%
  slice_max(pct, n = 20)

p1 <- ggplot(trbv, aes(x = reorder(v_gene, pct), y = pct)) +
  geom_col(fill = "#1b7837", alpha = 0.85, width = 0.7) +
  coord_flip() +
  labs(title = "Top 20 TRB V-gene usage (2025LJI, Day 0)",
       x = NULL, y = "% of TRB contigs") +
  theme_bw(base_size = 12)

p1

Clone size Each cell is assigned to a clonotype (cells with matching paired receptors). The plot below bins clonotypes by size (number of cells) and shows what fraction of the sampled T cells fall into each expansion class. Most cells sit in small clonotypes, with a tail of larger expanded clones.

clone_size <- vdj %>%
  filter(!is.na(raw_clonotype_id)) %>%
  distinct(participant_id, sample, raw_clonotype_id, barcode) %>%
  count(participant_id, sample, raw_clonotype_id, name = "clone_size")

cells_by_class <- clone_size %>%
  mutate(class = cut(clone_size, breaks = c(0, 1, 2, 5, 20, Inf),
                     labels = c("1", "2", "3-5", "6-20", ">20"))) %>%
  # weight by clone_size so the y-axis is the fraction of cells, not clonotypes
  group_by(class) %>%
  summarise(cells = sum(clone_size), .groups = "drop") %>%
  mutate(pct_cells = 100 * cells / sum(cells))

p2 <- ggplot(cells_by_class, aes(x = class, y = pct_cells)) +
  geom_col(fill = "#756BB1", alpha = 0.85, width = 0.7) +
  geom_text(aes(label = sprintf("%.1f%%", pct_cells)), vjust = -0.3, size = 3.5) +
  labs(title = "Clonal expansion (2025LJI, Day 0)",
       subtitle = "Share of sampled T cells by clonotype size",
       x = "Clone size (cells)", y = "% of cells") +
  expand_limits(y = max(cells_by_class$pct_cells) * 1.1) +
  theme_bw(base_size = 12)

p2