Workshop · NC_001802.1 · HIV-1

Mutations, diversity,
burden & the minority
you can't see

A hands-on session built on one real whole-genome HIV-1 deep-sequencing sample — 9,131 positions, median depth 4,002×.

Partway through, we will produce a confident, FDR-significant result. It will be wrong. Catching it is the point.

A · C · G · T  —  Dr. W. Choga

→ next   ← back   F fullscreen

The material

One file. Every question.

A per-position pileup: for every base of the HIV-1 genome, how many reads showed A, C, G and T.

That per-base count is the whole game. A consensus FASTA collapses each position to a single letter and throws the population away. These counts let us see underneath the consensus.

Everything today — types, diversity, burden, minority variants — is computed from these four columns.

What each row tells us

ColumnMeaning
Nucleotide posposition, 1–9181
refreference base
strainthis sample's consensus
depth (HQ)reads passing filter
A/C/G/T countthe population
indel countreads supporting indel
9,005
SNP-comparable sites
26
indel records
4,002×
median depth
31,797×
max depth
Definition

What is a mutation?

A change in sequence relative to a reference. Three things must be pinned down before the word means anything at all.

1 · Relative to what?

Reference genome? The patient's own baseline? Population consensus? "Mutation" is always a comparison — name the thing you compared to.

2 · In what fraction?

A virus is a population of genomes. A change in 100% of them and in 2% of them are both real — and mean completely different things.

3 · With what confidence?

Sequencers make errors. A 0.3% signal may be a mutation, or may be noise. This question will bite us later.

Our file offers two comparisons: ref vs strain → consensus mutations (Sanger sees these). strain vs base counts → minority variants (deep sequencing only).

Question 1 · relative to what

14% of this genome differs from the reference. Almost none of it is "mutation."

1,287
consensus differences
14.42%
divergence from HXB2

This sample is almost certainly a non-subtype-B virus measured against a subtype-B reference (HXB2 / NC_001802.1).

Those 1,287 differences are subtype differences — evolution that happened decades before this infection existed. They did not "arise" in this patient.

A difference from the reference is not a mutation that arose in your sample.

The reference is a historical accident — one man's virus, sequenced in 1983. It is not a wild-type ideal, and it is not "normal."

This single confusion produces more bad clinical genomics than any statistical error.

Types · axis 1

By structural change

TypeWhat happensIn this fileCount
Substitution (SNV/SNP)one base swapped for anotherref & strain both 1 base9,005
Insertionbases addedstrain longer than ref9
Deletionbases removedref longer than strain17

Why reading frame decides everything

An indel sized in multiples of 3 adds or removes whole codons — the protein is shorter or longer, but still readable.

Any other size shifts the reading frame: every downstream codon is garbled and the protein is usually destroyed. Same "one mutation" — wildly different consequence.

Our indels, by frame

Frame effectn
In-frame (×3)21
Frameshift5

Mostly in-frame — consistent with real viral variation. Random error has no reason to respect codon boundaries.

Types · axis 2 · your lie detector

Transitions vs transversions

Transition (Ti) — purine↔purine A↔G, or pyrimidine↔pyrimidine C↔T. Chemically similar bases; easy swaps.

Transversion (Tv) — purine↔pyrimidine. A bigger chemical change.

There are 8 possible transversions but only 4 transitions. So pure chance predicts Ti/Tv = 0.5.

Real data runs far higher — transitions are mechanistically favoured (deamination of methyl-C → T) and more often synonymous, so selection removes them less often.

815
transitions
472
transversions
1.73
consensus Ti/Tv — well above the 0.50 noise line

These consensus differences carry real evolutionary signal.

Remember 0.5. It is the cheapest QC metric you own, and in twenty minutes it will save us from publishing an artefact.

Types · axis 3

By functional consequence

Needs the reading frame — can't be read off a pileup alone. But it's what clinicians actually care about.

ClassEffect on proteinExample
Synonymous (silent)codon changes, amino acid does notGGA→GGG, both Gly
Missenseone amino acid replacedHIV RT K103N
Nonsensecodon → STOP, protein truncatedusually lethal to the virus
Frameshiftindel not ×3, everything downstream garbledusually knockout
Non-codingoutside genes; may affect expressionLTR promoter

dN/dS — the selection test

Ratio of nonsynonymous to synonymous change.
< 1 purifying · ≈ 1 neutral · > 1 positive (diversifying)

dN/dS > 1 is the signature of immune escape and drug pressure.

By origin

Germline (inherited) vs somatic (acquired — the basis of cancer genomics).

For a virus: transmitted vs acquired — which, for HIV resistance, decides whether a first-line regimen was ever going to work.

Calculation

Everything is built on one quantity

VAFb  =  nb  /  (nA + nC + nG + nT)
VARIANT ALLELE FREQUENCY — THE FOUNDATION OF EVERY METRIC TODAY

Minority calls, Shannon entropy, nucleotide diversity, burden — all of it is arithmetic on this ratio.

Sanity check: our computed majority base agrees with the file's own consensus call at 100.00% of sites. The arithmetic is sound.

Depth first, always. We keep only sites with ≥100× coverage: 8,924 of 9,005 (99.1%). You cannot call a variant you did not sequence deeply enough to see.

Calculation · a distinction that gets published wrong

Frequency ≠ rate

Mutation frequencyMutation rate
QuestionHow many mutants are here now?How fast do new ones appear?
Unitsa proportion (dimensionless)per base per replication
Needsone sample≥2 timepoints, or known generations
From this file?YesNo

Frequency is a snapshot — the product of mutation and selection and drift and elapsed time. A high-frequency variant may be common because it arose often, or because it was favoured. One timepoint cannot tell you which.

0.22
expected new mutations per genome, per replication cycle (rate 2.4 × 10⁻⁵)
240,000
times per day every possible point mutation is generated in an untreated infection

That second number is the whole ballgame. Resistance is not a question of whether it is generated — it is generated constantly. It is a question of whether the drug gives it a reason to expand.

Diversity

Divergence and diversity are different axes

Divergence asks: how far from the reference?

Diversity asks: how variable is the population within itself?

A sample can sit far from the reference yet be perfectly uniform, or sit right on it and be a seething swarm. This is the quasispecies concept: an infection is not a virus — it is a cloud of related genomes.

Shannon entropy

H = −Σ pb ln pb

0 = invariant · 1.386 = all four bases equally likely

Nucleotide diversity π

π̂ = [n/(n−1)] · (1 − Σ pb²)

The probability that two randomly drawn reads differ at a site.

The n/(n−1) correction matters. Without it, low-coverage sites look artificially less diverse — purely because you sampled fewer reads. That is a sampling artefact masquerading as biology.

Diversity · result

The swarm, measured

0.0262
mean Shannon entropy
0.0081
nucleotide diversity π
81
per 10,000 bases: how often two random reads differ
mean π per 200 bp window
0 0.006 0.012 0 GENOME POSITION 9,181
Diversity is not uniform, and it is not random — the peaks sit where selection is strongest.
Diversity · by gene

Mind the overlapping reading frames

HIV-1 is a masterclass in genomic compression: genes overlap, in different reading frames. vpu sits inside env; tat/rev exon 2 sit inside env.

A naive case_when() assigns each site to one gene and silently discards every overlap — 685 sites here. Use a long-format join so a site can belong to several genes.

env sits high — the surface protein, under relentless antibody pressure, and tolerant of change. pol — the drug target, structurally constrained — sits lower. Diversity maps onto selection.

mean π
Overlap-aware assignment: 685 sites belong to two reading frames at once.
Minority variants

Everything Sanger cannot see

Sanger sequencing sees ~20% and above. Anything rarer is invisible — buried in the chromatogram noise. Deep sequencing, at thousands of reads per site, can in principle reach 1% or lower.

Variants in that gap — present, real, sub-consensus — are minority variants. In HIV they matter enormously:

  • Minority drug-resistance mutations at 1–20% are associated with increased risk of virological failure — especially NNRTIs, which have a low genetic barrier.
  • They are archived from past treatment, or transmitted — and invisible to standard genotyping.
  • Under drug pressure, a 1% variant can sweep to fixation in weeks.
detected minor allele Sanger limit
Every variant we found sits below the Sanger line — max 16.0%. Standard genotyping would have reported this sample as having none of them.
The result · take a good look

451 minority variants. Every one significant at FDR < 1%.

We did it properly. If the per-base error rate is ε, then under the null "this is just error" the alt count is Binomial(n, ε). So we tested every site against ε = 0.2%, and corrected for multiple testing with Benjamini–Hochberg.

451
minority variants ≥ 1%
100%
of them pass FDR < 1%

A clean, defensible, fully corrected result. We could write this up this afternoon.

So let us try to destroy it.

The next slide is the most important one in this workshop.

The reversal

Ti/Tv collapses at low frequency

minority Ti/Tv pure chance = 0.50 consensus Ti/Tv = 1.73
Point size ∝ number of sites. At a 0.1% threshold, 6,798 "variants" have Ti/Tv = 0.09.

This is damning. At 0.1% the ratio is 0.09 — not merely random (0.5), but far below it. Random error would give 0.5. Something worse than random is happening: a systematic, direction-specific artefact.

At our 1% threshold, Ti/Tv sits at exactly 0.50. Roughly half of those 451 "significant" variants are noise.

Diagnosis

Read the spectrum, name the culprit

artefact signature plausible biology

Look at what dominates low VAF: A>C, T>G, G>T, C>A — all transversions.

And notice they form reverse-complement pairs (A>C ≡ T>G; G>T ≡ C>A). That strand symmetry is the fingerprint of a chemical/technical artefact — not biology.

  • G>T / C>A — the classic 8-oxoguanine (OxoG) oxidative damage signature, introduced during library prep.
  • A>C / T>G — a well-documented context-specific sequencing artefact.

Above 2% the spectrum flips to G>A, A>G, C>T — transitions. Real biology.

Why the statistics didn't save us

The test wasn't wrong. Its assumption was.

At ~4,000× depth, a 1% variant means ~40 supporting reads. Against a null of ε = 0.2%, forty reads is overwhelmingly significant — p is astronomically small.

So the test passes every single call. It never had a chance to reject anything.

The binomial test assumes error is uniform at 0.2% everywhere. Real error is context- and site-specific — at some sites it runs at 2%. The model cannot see that, so it confidently certifies artefacts.

Statistical significance is not biological reality.

A p-value only ever tests the model you handed it. With enough depth you can get vanishingly small p-values for pure garbage.

Deep sequencing does not protect you from this — it guarantees it. Depth makes everything significant.

The fix

Throw most of it away

Filter out the artefact signature (A>C, T>G, G>T, C>A) and raise the threshold to 2% — justified empirically, from Ti/Tv and the spectrum, not by convention.

Ti/Tv jumps from 0.50 to 5.25. We discarded 83% of our variants, and what remains finally looks like biology.

451
naive calls · 1%
0.50
their Ti/Tv — the noise line
75
clean calls · 2% + filter
5.25
their Ti/Tv — biology
VAF thresholdn (naive)Ti/Tv (naive)n (filtered)Ti/Tv (filtered)
≥ 1%4510.501775.81
≥ 2%1290.95755.25
≥ 5%200.82114.50
Independent validation

The virus signs its own work

If our surviving calls are real, they should carry biological signal. HIV has a famous one.

Host APOBEC3G deaminates cytosine during reverse transcription, producing G>A hypermutation. The virus's vif gene exists precisely to destroy APOBEC3G — that is its whole job.

G>A climbs from 1.6% to 20% as VAF rises. Sequencing error has no reason whatsoever to do that. A specific, known, host-driven biological process does.

This is independent confirmation that the surviving calls are real — and that the low-VAF tier is not.

% of variants that are G>A
The APOBEC3G hypermutation signature, concentrated exactly where the real variants are.
Burden testing

Trade resolution for power

Single-variant tests work for common variants. For rare ones they fail — and the reason is purely statistical. If a variant appears in 3 people out of 5,000, nothing on Earth has power to associate it with anything.

The burden test's move is collapsing: stop testing variants, start testing units — a gene, a region, a domain.

Instead of "does variant X associate with disease?", ask "do carriers of any rare variant in gene G differ from non-carriers?"

You no longer know which variant matters — but you can now detect that the gene matters at all.

TestCollapsing ruleBest when
CASTbinary: carries ≥1 rare variantrare variants, same direction
Burden / MBcount, weighted by rarityeffects same direction
SKATvariance-componentmixed directions
SKAT-Odata-driven blendyou don't know — the safe default

The plain burden test's fatal flaw: it assumes every variant in the unit pushes the same way. If half are harmful and half protective, they cancel — and it sees nothing. That is why SKAT exists.

Burden · an honest note

We have one sample. So let's be precise about what we can claim.

What we cannot do

A classical burden test compares cases vs controls across many individuals. We have one sample. We cannot run one — and you should be suspicious of anyone who claims otherwise.

What we can do

The same machinery, in its within-sample form: collapse variants into genes, test each against a background rate. This is exactly how regional mutation-enrichment scans work in cancer genomics — and it drills the identical logic.

THE NULL

Minority variants fall uniformly across the genome, at the genome-wide rate. Under that null, the count in a gene is Binomial(gene length, background rate). Test it. Correct it. Report the q-value.

Nine genes = nine tests. At α = 0.05 you expect ~0.45 false positives by chance. Always report the q-value.

Burden · the payoff

The same test, before and after

FDR < 0.05 not significant

vif — a false positive

fold 1.78 → 1.44 · q 0.0005 → 0.65

Its "enrichment" was driven by artefact-signature calls — 77% of vif's 1% calls were A>C/T>G/G>T/C>A. A confident, FDR-corrected, entirely false result.

env — real signal

fold 1.33 → 1.74 · q 0.0007 → 0.011

It got stronger when the noise was removed — the hallmark of real signal, and exactly what HIV biology predicts for the antibody-facing envelope protein.

The lesson

FDR controls chance. It is blind to bias.

Our q-value was 0.0005 and the result was still garbage.

Multiple-testing correction did not save us. It was never designed to. FDR controls for chance — it has nothing at all to say about systematic bias.

No amount of statistics rescues contaminated input. Only the biology told us the truth:

  • Ti/Tv sitting on the 0.5 noise line
  • The OxoG strand-symmetric spectrum
  • The APOBEC3G G>A gradient

Every one of those checks is a domain check, not a statistical one. They work because we know what HIV does — and what a sequencer does when it is wrong.

Know your data's failure modes, or your p-values will lie to you with perfect confidence.

Takeaways

Six things to leave with

1 · "Mutation" is a comparison

State: relative to what, at what frequency, with what confidence. 14% of this genome differs from HXB2 because it is a different subtype — not because the patient mutated.

2 · Frequency ≠ rate

One timepoint gives a snapshot, never a speed.

3 · Diversity ≠ divergence

Independent axes — and diversity maps onto selection (env high, pol constrained).

4 · Threshold + depth define your count

451 variants at 1%; 75 at 2% with filtering. Neither is "the truth." Report both numbers, or report nothing.

5 · Ti/Tv is your lie detector

0.5 = noise. If your minority calls sit at 0.5, they are noise — no matter how small the p-value.

6 · Statistics cannot rescue contaminated data

We got q = 0.0005 for vif and it was pure artefact. Only the biology told us the truth.

Your turn

Exercises

1 · Predict the spectrum

Consensus Ti/Tv was 1.73. Before running the minority analysis, predict whether minority Ti/Tv will be higher or lower — and why. Then check.

2 · Find the variable loops

Compute diversity in 100 bp windows across env only. Can you locate V1–V5 as peaks? What does it mean clinically if a patient's env diversity is very low?

3 · Defend your threshold

We justified 2% empirically. Now defend it to a clinician. What must you state alongside "we found N minority variants" for the claim to be reproducible?

4 · Break the burden test

In run_burden(), make half the variants protective. Re-run. Watch power collapse. Then explain in one sentence why SKAT exists.

Everything on these slides is reproduced in mutations_workshop.Rmd — every number is computed from the CSV, not typed in. Change params at the top and the whole document re-derives itself.

Close

The sequencer will always
give you an answer.

Your job is to know when it's lying.

451
variants we found
75
variants that were real
1
gene that survived scrutiny

A · C · G · T

1 / 26