Skip to content

How many sequences will two samples share?

The question: if two samples are drawn from the same population, how many sequences will they have in common by chance alone?

Overlap between repertoires is often read as evidence of a shared response. Before reading it that way, it helps to know how much overlap independent samples of one population produce on their own. BEAM computes it directly from the model of the population, without simulation.

sharing(d1, d2) is the expected number of sequences found in both of two independent samples of depths d1 and d2.

sharing.py
import BEAM
from BEAM.analytics.exact_occupancy import ExactOccupancy
model = BEAM.load_pretrained("human_tcrb_cdr3_aa_foundation")
occupancy = ExactOccupancy(model)
print(" depth A depth B shared sequences share of A's distinct sequences")
for a, b in [(1e5, 1e5), (1e5, 1e6), (1e6, 1e6), (1e7, 1e7)]:
shared = occupancy.sharing(a, b).value
distinct_a = occupancy.richness(a).value
print(f"{a:9,.0f} {b:9,.0f} {shared:17,.0f} {shared / distinct_a:32.1%}")
Output
depth A depth B shared sequences share of A's distinct sequences
100,000 100,000 3,678 3.8%
100,000 1,000,000 14,633 15.1%
1,000,000 1,000,000 82,670 9.4%
10,000,000 10,000,000 1,090,052 15.1%
Full program, including the set-up hidden here
Share of one sample's sequences also found in a second sample of equal depth, rising with depth.Share of one sample's sequences also found in a second sample of equal depth, rising with depth.
Expected overlap between two independent samples of equal depth from the reference population.

Two samples of 100,000 cells share about 3,700 sequences by chance, 3.8% of either sample’s distinct sequences. The overlap grows with depth: at ten million cells each, 15% of one sample’s sequences are expected in the other. A deeper second sample also raises the overlap: 100,000 cells against a million share 15% of the smaller sample’s sequences.

private(depths) is the expected number of sequences found in exactly one sample of a cohort.

private.py
import BEAM
from BEAM.analytics.exact_occupancy import ExactOccupancy
model = BEAM.load_pretrained("human_tcrb_cdr3_aa_foundation")
occupancy = ExactOccupancy(model)
# A cohort of 10 people, each sampled to 100,000 cells
depths = [100_000] * 10
private = occupancy.private(depths).value
all_distinct = occupancy.richness(sum(depths)).value
print(f"distinct sequences across the cohort: {all_distinct:,.0f}")
print(f"seen in exactly one person: {private:,.0f} ({private / all_distinct:.1%})")
Output
distinct sequences across the cohort: 879,776
seen in exactly one person: 828,289 (94.1%)
Full program, including the set-up hidden here

Across ten people sampled to 100,000 cells each, 94% of all distinct sequences are expected to be private to one person. Shared sequences are the exception, even by chance.

The same calculation predicts how many distinct sequences a cohort accumulates as it is pooled. In the paper, without any adjustment, the reference model built without the 768 Emerson donors predicted 98.9% of their observed pooled distinct-sequence count.