Gene list matching: single alias hop, and a resync that deletes #1669 - #1846
Open
davmlaw wants to merge 2 commits into
Open
Gene list matching: single alias hop, and a resync that deletes #1669#1846davmlaw wants to merge 2 commits into
davmlaw wants to merge 2 commits into
Conversation
ReleaseGeneMatcher walked the GeneSymbolAlias graph transitively and in both directions, so an alias string shared by two unrelated approved symbols acted as a bridge. A hypogonadotropic hypogonadism panel returned a PDCD2 variant via MT-TS2 -> RP8 -> PDCD2, and since MT-TS2 has no RefSeq gene in the release, PDCD2 was its only match - a false positive and a false negative from one row. aliases_dict now takes exactly one GeneSymbolAlias hop, in either direction: the queried symbol is the alias of a symbol the release has, or a symbol the release has is an alias of it. Both directions earn their keep - HGNC is refreshed far more often than gene annotation releases, so a current-symbol gene list against an older release relies on the backward hop constantly. One hop is enough for renames: HGNC lists every previous symbol of a gene. Matching only ever inserted, so a rematch left the chained rows in place. fix_rematch_release_symbols_to_genes becomes a full resync per release - insert, update match_info, delete what the current rules no longer make - with --dry-run, and a ManualOperation migration so deployments run it.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements #1669.
Problem
ReleaseGeneMatchertraversed theGeneSymbolAliasgraph transitively and in both directions, so an alias string shared by two unrelated approved symbols bridged their genes. Reported from prod (SACGF/variantgrid_sapath#426): a hypogonadotropic hypogonadism panel returned a PDCD2 variant, because HGNC recordsRP8as an alias for bothMT-TS2(on the list) andPDCD2. The walk wentMT-TS2 → RP8 → PDCD2and wrote:MT-TS2 is a mitochondrial tRNA with no RefSeq gene in the release, so PDCD2 was its only matched gene — a false positive and a false negative from the same row.
Fix
aliases_dictnow takes exactly oneGeneSymbolAliashop, in either direction, for symbols the release doesn't have itself:KAL1 → ANOS1: gene list uses an old name)ANOS1 → KAL1: HGNC is refreshed far more often than gene annotation releases, so a current-symbol gene list against an older release hits this constantly — over 1,100 rows in the T2T Ensembl 2022 release alone)One hop is enough for renames: HGNC's
prev_symbollists every previous symbol of a gene, so a gene renamed twice has direct alias rows from both old names. Chaining is what let a shared alias string bridge unrelated genes._aliases(the recursive walk) is gone.Precedence is unchanged: a symbol in the release matches its own genes with
match_info=Noneand aliases are never consulted; otherwise gene-version matches (Gene v0/GRCh38) win over alias matches for the same gene.Cleanup
Matching only ever inserts
ReleaseGeneSymbolGenerows, so a rematch leaves the chained rows in place — and rows derived from alias rows since deleted by a re-import survive too.fix_rematch_release_symbols_to_genesbecomes a full resync per release (insert / updatematch_info/ delete what the current rules no longer make), with--dry-run, andgenes/migrations/0089_one_off_resync_release_gene_symbol_genes.pyregisters it as aManualOperationso deployments pick it up.--dry-runagainst this box's 175 GB database:Against
RS_2025_08_GRCh38, the known bridges are all gone and the legitimate hop is kept:Testing
genes/tests/test_gene_matching.pygetsTestReleaseGeneMatcher(direct hit, forward hop, backward hop, shared alias doesn't bridge, alias matches only the release target) andTestFixRematchReleaseSymbolsToGenes(plants theMT-TS2 → 5134chained row, asserts the resync deletes it, keeps the direct match and inserts the missing one; and that--dry-runwrites nothing).Full suite: 3112 tests, OK.
scripts/vg map --checkandscripts/vg docs checkpass.Not in scope
Item 3 of the issue (surfacing an alias substitution on the gene list page) stays with #1668, which is where the shared resolver and its provenance live. Once that exists, the backward hop should accept
prev_symbolrows only.🤖 Generated with Claude Code
https://claude.ai/code/session_01XeLN2A486UE31zfdk9SrRG