Patch release on top of v2.2.1. No cache invalidation: existing v2.2.1 caches remain current on upgrade and allelix db update signal-skips every annotator. The one new gnomAD position index lands as a transparent lazy migration inside the annotator — one-time ~30s build cost on first analyze against a pre-v2.2.2 cache, never again.
Highlights
- rsID-less VCF coverage on
analyze --filter-fileandextract. VCFs that don't stamp dbSNP identifiers in the ID column — DeepVariant gVCFs, Sequencing.com / DRAGEN output, GIAB GRCh38 benchmarks — now resolve rsIDs against gnomAD's full dbSNP coordinate map after the ClinVar position resolver runs. Pharmacogenomic, GWAS-only, and SNPedia-only panel rsIDs that were previously classified as "not in file" now surface correctly.extractwas rewritten symmetrically — both the tabix fast-path and the sequential fallback match by(chrom, pos, ref, alt)instead of an rsID equality check that always failed on rsID-less inputs. Real-world measurement on a DeepVariant HG002 gVCF with a 22-rsID wellness panel: panel coverage went from 3/20 found to 8/22 found, with the rest reading honestly as "reference at this position or no variant call" instead of the misleading "not on chip" framing. - VCF parser tolerance for UTF-8 BOM and leading preamble lines. Defensive hardening for a reported Sequencing.com 30x WGS VCF rejection.
_open_vcfnow opens files with theutf-8-sigcodec, which strips a leading UTF-8 BOM transparently and behaves identically toutf-8on BOM-less input.can_parseand the header reader scan the first 10 non-blank lines for##fileformat=VCFrather than insisting it appears on line 1 — robust against tool banners, comment-line preambles, and other upstream pipeline quirks that previously caused silent format-detection failures. - Format-aware HTML panel-coverage wording on VCF / gVCF inputs. State-3 panel rsIDs no longer render as "not genotyped on this chip/platform" for VCF / gVCF inputs (there is no chip). Array inputs keep the historical label; VCF / gVCF inputs surface "reference at this position or no variant call" — honest framing on the genuine ref/ref case where the sample carries the reference allele and the caller emits no variant row.
- Stats Build column: em dash + chr-prefix hint instead of a blank cell. Caller-output VCFs (DeepVariant, DRAGEN, GIAB GRCh38 benchmark) don't write
##reference=in their headers, so the parser returned an empty build string and the stats summary rendered a blank cell — reading as broken even thoughstatsdeliberately does not run build detection (that's ananalyzejob). The cell now renders an em dash, plus a short hint pointing the user toanalyzewhen chr-prefixed contigs suggest a likely build. - gnomAD position-index lookup ~5x faster on WGS analyze. The new rsID-less position resolver hit a missing covering index —
gnomad_frequenciescarried only anrsidindex, so every position-keyed query was a full scan against 57 million rows. Addedidx_gnomad_positionover(chrom, pos)to the canonical schema, with a lazy migration inGnomadAnnotator._connectionso existing 2.7 GB caches don't need re-download. The per-batch SQL was also collapsed from one statement per chromosome to one combined row-valueINper batch. Real-world measurement on a 5.2 M-variant DeepVariant HG002 gVCF: ~165s → ~133s.
Known limitations
- GRCh38 rsID-less files still fall back to ClinVar / gnomAD position resolution for rsID-keyed lookups. Full dbSNP resolution is targeted for v2.3+.
- Three call sites that compare a variant's rsID against a curated set bypass the analyze pipeline's resolver phase —
statshigh-value match, PLINK export ref/alt lookup, and build-detection known-SNP positions. None user-blocking. Tracked for v2.3 as a single centralize-resolution change rather than three scattered patches.
Calibration
- Array carrier counts unchanged. The v2.1.0 strand-aware carrier-matching pathway is untouched; per the v2.1.0 calibration this release does not move array-side results.
- JSON report schema stays at 6. No new fields, no semantic changes.
- VCF data-line fidelity preserved. The BOM strip and preamble scan touch only the header block; VCF data lines are pure ASCII tab-separated values and never reach either path. Genotype calls are unaffected.
- Annotation count drift on rsID-less files is expected. The new resolver surfaces pharmacogenomic / GWAS-only / SNPedia-only rsIDs that v2.2.1 silently missed. The §19 ground-truth harness floor invariants accommodate this drift by design; the spot-checks at MTHFR / APOE / VEGFA / Factor V still hold.
Fixed
- Panel coverage and extract on rsID-less VCFs now recover rsIDs via gnomAD after ClinVar's existing pass; downstream annotators see the recovered rsIDs and produce the annotations that were silently missing pre-v2.2.2.
- VCF parser no longer rejects files with a leading UTF-8 BOM or a banner / comment line before
##fileformat=VCF. - HTML panel-coverage section uses format-aware wording on VCF / gVCF inputs.
- Stats Build column renders an honest em dash (with chr-prefix hint when applicable) instead of a misleading blank cell on caller-output VCFs.
Performance
- gnomAD
(chrom, pos)covering index closes a full-scan path the v2.2.2 rsID resolver fix had exposed. Lazy migration runs once per existing cache; new caches built from v2.2.2 onward have the index from the install step. Per-chromosome SQL collapsed to a single row-valueINper batch.
Added
tests/fixtures/mock_vcf_bom.vcf/.vcf.gz,mock_vcf_preamble.vcf,mock_vcf_bom_preamble.vcf— four committed fixtures exercising the full BOM × preamble matrix.Variant.original_rsiddebug-only audit field, stashed by every rsID-less resolver before mutatingVariant.rsid. Gated by a serialization-guard test that fails any PR letting the field reach JSON, HTML,--diff, terminal, or extract-table output.GnomadAnnotator.bulk_resolve_rsids_from_positions— reverse coord-to-rsid lookup that backs the new pipeline second-pass resolver.
Verification
-
Tests. 1731 passed, 0 skipped, 5 deselected.
-
Coverage. CI 3.11 / 3.12 matrix clears the 92.5 floor. Local 3.12 measures 93.12; CI runs ~0.1–0.2pp lower per the calibration note in
pyproject.toml. -
Lint.
ruff check/ruff format --check/mypyall clean. -
Ground-truth harness on the three bundled WGS battery files, all invariants hold:
File Annotations Notes GIAB GRCh38 benchmark 2,191 Resolver lift vs v2.2.1's 773 GIAB GRCh37 benchmark 3,063 Stable (rsIDs present in ID column) HG00187 GATK-HC gVCF 17 Resolver lift vs v2.2.1's 6 -
Wrong-allele safety invariant. Every alt-set annotation with a stamped CADD score has its alt directly in gnomAD's alts at that rsID; zero via-complement hits.