HGVS Nomenclature02/11
Starting sandbox…
Beginner·4 graded tests

HGVS Nomenclature

HGVS Nomenclature

Core Principle: Human Genome Variation Society (HGVS) nomenclature specifies strict, unambiguous syntactic and semantic rules for describing sequence variants across genomic, transcript, and protein reference spaces.

Maintained by the Human Genome Variation Society in partnership with HUGO and the Human Variome Project. It is what clinical reports, ClinVar and LOVD all use.

The anatomy of a variant

NM_000546.6 : c . 215 C > G
─────┬───── ─┬─ ─┬─ ──┬──
     │       │   │    └── the edit: what changed
     │       │   └─────── the position
     │       └─────────── the reference type
     └─────────────────── the reference sequence, WITH VERSION

All four parts are required. c.215C>G alone is not a variant: it is meaningless without knowing which transcript. The accession version is part of the identity: NM_000546.5 and NM_000546.6 can number the same base differently.

The reference types

Prefix Reference Numbering starts at
g. linear genomic (a chromosome) position 1 of the sequence
m. mitochondrial position 1 of the mtDNA
c. coding DNA (a transcript) the A of the initiator ATG
n. non-coding RNA position 1 of the transcript
r. RNA as c., lowercase acgu
p. protein the initiator methionine
o. circular genomic

c. is the one clinicians use and the one with the complicated numbering.

Coding DNA (c.) Coordinate Rules

5'UTR          CDS                        3'UTR
──────────┬─────────────────────────┬───────────
  -3 -2 -1│ 1  2  3 ............ n  │*1 *2 *3
          A  T  G                 stop

Three rules:

  1. There is no position 0. The base before c.1 is c.-1.
  2. * marks the 3'UTR. The first base after the stop codon is c.*1.
  3. Intronic positions use offsets from the nearest exonic base:
    • c.87+3: 3 bases into the intron after coding position 87
    • c.88-3: 3 bases before coding position 88 (i.e. near the 3' end of that intron)
    • c.-24+5: intronic, within the 5'UTR
    • c.*12-8: intronic, within the 3'UTR

The +/- offset is measured from the nearest exon boundary on each side, so a long intron is numbered from both ends and the middle is unreachable by either convention. That is deliberate: introns are numbered relative to the splice sites that matter.

Never do arithmetic on the base number and ignore the offset. c.87+3 and c.90 are unrelated positions. See SequenceVariant.

Edit types

Type Example Meaning
Substitution c.215C>G one base replaced
Deletion c.76_78del bases removed
Duplication c.76_78dup copy inserted immediately 3' of the original
Insertion c.76_77insT inserted between the two named bases
Delins c.76_78delinsAC delete then insert
Inversion c.76_78inv reverse-complemented in place
Repeat c.76TG[8] a short tandem repeat with a count
No change c.76= reference confirmed

Insertions name the flanking bases, not an insertion point: c.76_77insT means "insert T between 76 and 77". The two positions must be consecutive. This is why insertion coordinates cannot be converted to or from VCF by simple arithmetic.

Duplication vs insertion. If the inserted sequence is a copy of the immediately preceding sequence, HGVS requires dup, not ins. c.76dup and c.76_77insG (where base 76 is G) describe the same event; only the first is correct HGVS.

Protein notation

p.Arg175His        three-letter (preferred)
p.R175H            one-letter (accepted)
p.(Arg175His)      PREDICTED, not observed: note the parentheses
p.Arg175*          nonsense (stop gained); p.Arg175Ter is equivalent
p.Arg175fs         frameshift
p.Arg175ProfsTer13 frameshift with the new reading frame's stop 13 residues later
p.Met1?            the start codon is affected; consequence unknown
p.=                protein unchanged (synonymous)
p.0                no protein produced

The parentheses matter. p.(Arg175His) means the protein change was inferred from the DNA, not observed at the protein level. Anything produced by projecting a c. variant is a prediction and should carry them: which is exactly what AssemblyMapper does.

Multiple variants

NM_000546.6:c.[215C>G];[847C>T]      two variants in trans (different alleles)
NM_000546.6:c.[215C>G;847C>T]        two variants in cis (same allele)
NM_000546.6:c.215C>G(;)847C>T        phase unknown

Phase: whether two variants are on the same chromosome copy: is clinically decisive. Two loss-of-function variants in trans in a recessive gene is a diagnosis; the same two in cis is a carrier. The bracket notation encodes it, and most pipelines throw it away.

Common conventions and pitfalls

The 3'-most rule. Where a variant could be described at several positions (an indel in a homopolymer or repeat), HGVS requires the most 3' position on the reference sequence. This is the opposite of VCF's left-alignment convention. See hgvs Normalizer.

Reference-sequence-relative, not strand-relative. "3'-most" means 3' on the reference sequence being used. For a c. variant on a minus-strand gene, that is the opposite genomic direction from a g. variant at the same locus. Getting this backwards is a real and common error.

Legacy notation you will still meet: IVS3+2T>C (intron numbering) and c.215C>G written without an accession. Both are ambiguous and both are still in clinical records. Convert them to proper HGVS before doing anything with them, and record what you assumed.

Worked examples

NC_000017.11:g.7676154G>C          genomic, GRCh38, chr17
NM_000546.6:c.215C>G               TP53 transcript, coding
NP_000537.3:p.(Pro72Arg)           the predicted protein consequence
NM_000546.6:c.-28-2A>G             intronic, in the 5'UTR
NM_000546.6:c.*1175A>C             3'UTR
NM_004006.2:c.4375_4379del         a DMD deletion
NM_000492.4:c.1521_1523delCTT      CFTR F508del at the DNA level
NP_000483.3:p.(Phe508del)          the same event at the protein level
NC_012920.1:m.3243A>G              MELAS, mitochondrial

Note that CFTR ΔF508 is c.1521_1523delCTT in HGVS but universally called "F508del" clinically: the legacy protein-level name persists. This gap between clinical shorthand and formal nomenclature is why parsing free-text variant names is hard.

Where to check

  • Specification: https://hgvs-nomenclature.org/
  • Validators: VariantValidator, Mutalyzer: useful for cross-checking your library output
  • The library: biocommons hgvs

Common mistakes

  • Omitting the accession, or omitting its version.
  • ins where dup is required.
  • Forgetting there is no c.0.
  • Arithmetic on intronic base numbers, ignoring offsets.
  • Assuming left-alignment. HGVS is 3'-most; VCF is leftmost.
  • Treating a predicted p. as observed: the parentheses are meaningful.
  • Losing phase information.
  • Hand-writing HGVS strings rather than generating them with a library. A string you constructed by concatenation is unvalidated.
  • Regex-parsing HGVS. It has a formal grammar for a reason. See hgvs Parser.

See also

biocommons hgvs · hgvs Parser · SequenceVariant · hgvs Normalizer · Coordinate Systems · hgvs Pitfalls

Exercise

The hgvs package is not available in this sandbox, so you will encode the nomenclature rules yourself rather than letting the grammar reject the string for you. Writing the rules out is what makes them memorable, and it forces you to notice which of them a parser can check without sequence data and which it cannot.

Write check_variants(lines), taking the input lines and returning a list of output lines. Ignore blank lines. For each remaining line emit <variant> <rule>, where <rule> is the first rule below that the string breaks, or ok if it breaks none. Check the rules strictly in this order:

  • missing_accession: there is no : separating a reference sequence from the description
  • missing_version: the accession is not two letters, an underscore, digits, a dot and a version number
  • unknown_type: the reference type is not one of g, m, c, n, r, o
  • malformed: the description is not a position or start_end range followed by one of X>Y, del, dup, ins, inv, delins or =
  • position_zero: a position numbers zero; there is no c.0
  • interval_reversed: the end of the range precedes the start, ordering -n before n before *n
  • insertion_not_flanking: an ins does not name two consecutive plain positions
  • substitution_no_change: a substitution states the same base twice, which HGVS writes =

Finish with a line ok=<n> invalid=<m> counting the two outcomes; that line is the only output when the input is empty.

exerciseEvery submission runs independently in a fresh namespace.

Test cases · 4

#viainputexpected stdout
1stdinNM_000546.6:c.215C>G c.215C>G NM_000546:c.215C>G NM_000546.6:x.215C>G NM_000546.6:c.215Q>G NM_000546.6:c.0C>G NM_000546.6:c.218_215del NM_000546.6:c.76_78insT NM_000546.6:c.215C>C NM_000546.6:c.76_77insT NM_000546.6:c.215C>G ok c.215C>G missing_accession NM_000546:c.215C>G missing_version NM_000546.6:x.215C>G unknown_type NM_000546.6:c.215Q>G malformed NM_000546.6:c.0C>G position_zero NM_000546.6:c.218_215del interval_reversed NM_000546.6:c.76_78insT insertion_not_flanking NM_000546.6:c.215C>C substitution_no_change NM_000546.6:c.76_77insT ok ok=2 invalid=8
2stdinNC_000017.11:g.7676154G>C NM_000546.6:c.-28-2A>G NM_000546.6:c.*1175A>C NM_000492.4:c.1521_1523delCTT NC_012920.1:m.3243A>G NM_000546.6:c.76= NM_000546.6:c.*12_-24del NM_000546.6:c.76insG NC_000017.11:g.7676154G>C ok NM_000546.6:c.-28-2A>G malformed NM_000546.6:c.*1175A>C ok NM_000492.4:c.1521_1523delCTT ok NC_012920.1:m.3243A>G ok NM_000546.6:c.76= ok NM_000546.6:c.*12_-24del interval_reversed NM_000546.6:c.76insG insertion_not_flanking ok=5 invalid=3
3stdinNM_000546.6:c.215C>G NM_000546.6:c.215C>G ok ok=1 invalid=0
4stdin ok=0 invalid=0

Hints · 3

01Hint

Split once on ':' with str.partition, then check the accession and the two-character type prefix separately.

02Hint

Sort positions with a key of (1 if it starts with '*' else 0, int(value)) so -24 < 215 < *12 falls out.

03Hint

An insertion is only well-formed when both positions are plain integers and int(end) == int(start) + 1.