615721361f4baf75c0715bb931c5fc1015101622
lrnassar
  Tue Aug 11 18:21:56 2026 -0700
Address code-review findings on the Cardiomyopathy VCEP scripts. refs #37446

- Gate PM1 to missense variants per the CSpec ("applicable to missense variants");
a positional-only test wrongly gave synonymous/truncating/splice variants PM1 and
let it collide with BA1/BP7. PM1 firing 1,293 -> 700.
- Transcript-gate the Walsh-2019 ClinVar coordinate lookup so a classic-vs-MANE
c.notation collision no longer mis-places TNNT2 R92Q (was drawn ~331 nt off with a
different variant's VariationID); the gate applies only to the WALSH_TX genes.
- Show the amino-acid change in the REVEL mouseover (computed from the MANE CDS) so
the per-alt genomic-forward-strand score is not misread on minus-strand genes.
- Resolve every build input relative to --output-dir (sibling track outputs and
cmp_downloads sources) for otto portability; canonical build byte-identical.
- Also key the diseaseTag off the counted PM1 code, and makedoc corrections
(worked example REVEL/gnomAD values, PM1 count, universe and EvRepo notes).

diff --git src/hg/makeDb/doc/Cardiomyopathy.txt src/hg/makeDb/doc/Cardiomyopathy.txt
index 0cc4661be64..400fcc1550b 100644
--- src/hg/makeDb/doc/Cardiomyopathy.txt
+++ src/hg/makeDb/doc/Cardiomyopathy.txt
@@ -252,30 +252,34 @@
 # cross-assembly parity at the end.
 #
 # Build order matters: B.3 defines the variant universe that B.6 annotates;
 # B.11 (Computable codes) consumes B.6 (annotation), B.3 (AF), B.4 (REVEL), and the
 # B.7 EvRepo P/LP set (PS1/PM5 reference). Suggested order:
 #
 #   for s in cmpVCEPClinDomains cmpVCEPPVS1 cmpVCEPAFfrequencies cmpVCEPAnnotate \
 #            cmpVCEPRevel cmpVCEPCardioBoost cmpVCEPEvRepo cmpVCEPWalsh2019 \
 #            cmpVCEPClinVar506161 cmpVCEPWalshOR cmpVCEPAtlasEF \
 #            cmpVCEPProvisionalClass; do
 #     python3 ~/kent/src/hg/makeDb/scripts/cardiomyopathyVCEP/${s}.py \
 #       --db hg38 --db hg19 \
 #       --output-dir /hive/users/lrnassar/claude/RM37446 || break
 #   done
 #   # (cmpVCEPAnnotate.py takes only --output-dir.)
+#   # cmpVCEPWalshOR + cmpVCEPAtlasEF are the RETIRED PS4 tracks (Q5): they still run
+#   # here and emit .bb files, but no trackDb references them, so those .bb are dormant
+#   # orphans. Left in the loop only so the scripts stay runnable; drop them once the
+#   # retirement is permanent.
 #
 #
 # B.1  cmpVCEPClinDomains.py — PM1 Hotspot Regions
 #      Output: 28 features (4 genes x CDS-exon-spanning AA range; MYH7, MYBPC3,
 #      TNNT2, TNNI3 only). Codon ranges per A.1. Color 230,3,131 (magenta-rose,
 #      the InSiGHT/TP53 clinical-domains convention). Built-in unit tests check
 #      codon-to-genomic conversion across all 8 genes.
 #
 # B.2  cmpVCEPPVS1.py — MYBPC3 PVS1 Evidence (MYBPC3 only)
 #      Output: 16 features (2 NMD-escape genomic segments + 14 in-frame exon
 #      caveats; 3 also tagged micro-exon in the mouseover).
 #
 # B.3  cmpVCEPAFfrequencies.py — gnomAD v4.1 BA1/BS1/PM2_supporting
 #      Variant universe: all gnomAD v4.1 PASS variants in the 8 gene CDS regions
 #      +/- 20 nt splice padding. fetch_gene_variants() is the canonical universe,
@@ -308,40 +312,47 @@
 # B.5  cmpVCEPCardioBoost.py — CardioBoost missense predictor (informational)
 #      Loads cm_prediction.RData via /usr/bin/Rscript; 31,236 missense predictions
 #      across the 8 genes. GRCh37 native -> add chr prefix -> liftOver to hg38
 #      (0 unmapped). Rendered as a default-OFF subtrack under the Bioinformatic
 #      composite (sibling to REVEL). Colored by CardioBoost's own published class
 #      (probability >= 0.9 Pathogenic, <= 0.1 Benign, else Indeterminate). NOT a
 #      CSpec-specified predictor and fires no ACMG code — informational only.
 #      name field includes ref/alt so same-aa variants via different nt are unique.
 #
 # B.7  cmpVCEPEvRepo.py — VCEP Curated Variants from EvRepo (Final, with codes)
 #      Output: 25 features (all MYH7). The complex repeat-notation p.Glu931del
 #      (c.2785GAG[2]) is recovered via a coords_via_hgvstovcf() fallback.
 #      Mouseover prefix "Final — VCEP EvRepo submission"; codesMet filtered to
 #      status="Met"; codesAll = Met + NotMet where enumerated. Standard 5-tier
 #      ACMG ramp.
+#      NOTE: EvRepo has 14 P/LP entries but only 13 are missense (p.Glu931del is an
+#      in-frame deletion). B.11's PS1/PM5 reference uses the 13 missense (it gates on
+#      is_missense + single-codon + aaAlt), so the deletion is correctly not a seed.
 #
 # B.7c cmpVCEPWalsh2019.py — Walsh 2019 Pre-EvRepo curations (Table S6)
 #      Output: 155 features (3 rows outside our 8 genes filtered out). All 155
 #      are rendered: the 32 previously unmatched-to-ClinVar entries (complex
 #      indels + 4 TNNT2 SNVs incl. R92W) are placed via walsh_coords_via_tool()
 #      = hgvsToVcf on each gene's Walsh-paper transcript, gated on FILTER==PASS.
 #      TNNT2 uses NM_001001430.2 (MANE gives HgvsRefAssertedMismatch); TNNT2 hg19
 #      coords via liftOver from hg38. 27 variants tagged "Walsh-upgraded" (the new
 #      PM1 EF rule, asterisked in Table S6). Classification strings normalized to
 #      "Uncertain Significance" (not "VUS"). Standard ACMG ramp.
+#      The ClinVar coordinate lookup is gated on transcript for the WALSH_TX genes:
+#      a Walsh classic-transcript c.notation can collide with a different MANE variant
+#      of the same c.notation (TNNT2 classic c.275G>A [R92Q] vs MANE c.275G>A [G92E]),
+#      so TNNT2 entries fall to the hgvsToVcf-on-classic path (VariationID shown as —).
 #
 # B.8  cmpVCEPClinVar506161.py — VCEP ClinVar submissions (Final, no codes)
 #      Output: 199 features. Joined to variant_summary for hg38 + hg19 coords.
 #      All carry review status "reviewed by expert panel". 25 of 199 overlap
 #      EvRepo (flagged inline in the mouseover). Standard 5-tier ACMG ramp (the
 #      earlier desaturated palette was dropped). Carries no per-code evidence.
 #
 # B.9  cmpVCEPWalshOR.py — Walsh 2017 gene-level case-control OR (PS4)
 #      [RETIRED from the hub 2026-07 per the VCEP (Q5: do not display Walsh 2017/2019
 #       PS4; ORs use current cohorts). Script + data retained in the tree for reference.]
 #      Source: Walsh 2017 Supplementary_Tables_resubmit.xlsx, Tables S5A (HCM) /
 #      S5B (DCM). Output: 48 features = 8 genes x {HCM, DCM} x {All protein-
 #      altering, Truncating, Non-truncating}, each spanning the gene CDS (MANE),
 #      filterable by gene / cohortDisease / variantClass / ps4Strength.
 #      PS4 strength by OR 95%-CI lower bound (Strong >=20, Moderate >=10,
@@ -372,31 +383,36 @@
 #      P/LP reference, leave-one-out; a variant cannot earn the code from its
 #      own entry; PS1 reference excludes established splice-impact variants e.g.
 #      MYBPC3 c.2308G>A), PM4 (NMD-escaping truncating, non-MYBPC3: last exon or
 #      within 50 nt of the final exon-exon junction), BP7 (synonymous +
 #      SpliceAI < 0.1, per Walker 2023 PMID 37352859; conservation requirement
 #      removed per the VCEP). PM1<->PM5 mutual exclusion enforced per CSpec (keep
 #      PM5, the variant-specific code; drop PM1; PM1+PS1 co-occurrence flagged).
 #      HCM/DCM diseaseTag populated. A SpliceAI score >= 0.20 is recorded as an
 #      informational splice flag.
 #      Mouseover is evidence-first ("evidence -> supports CODE"); NO overall
 #      classification is calculated. The GN002 combining logic remains in the
 #      script as classify() but is retired/uncalled. Clinical/functional codes
 #      (PS2/PS3/PS4/PP1/PP4/BS3/BS4) are not computed. Single neutral display
 #      color 91,107,122; no classification encoded.
 #      Output: 10,974 features. Evidence firing: BA1 210, BS1 367, PM2_Supporting
-#      9,893, PP3 1,436, BP4 1,647, BP7 2,334, PM1 1,293, PM4 27, PM5 11, PS1 0.
+#      9,893, PP3 1,436, BP4 1,647, BP7 2,334, PM1 700, PM4 27, PM5 11, PS1 0.
+#      PM1 is gated to MISSENSE variants (per the CSpec "applicable to missense
+#      variants"); a positional-only test wrongly gave synonymous/truncating/splice
+#      variants PM1 and let it collide with BA1/BP7.
+#      NOTE on the variant universe: it is the gnomAD-PASS set (B.3), so a variant
+#      with no evidence row is simply not in gnomAD-PASS, NOT necessarily "not rare".
 
 
 ##############################################################################
 # Phase C: Hub assembly
 ##############################################################################
 #
 # Files written/maintained by hand (NOT generated by the build scripts):
 #   hub.txt, genomes.txt
 #   cardiomyopathy.html        (shared description page; hub descriptionUrl)
 #   hg38/trackDb.txt
 #   hg19/trackDb.txt           (mirrors hg38; differs in bigDataUrl + an hg19
 #                              provenance header noting liftOver-derived coords)
 #
 # trackDb structure: 6 top-level groups -> 9 tracks. Two are composites:
 #   Bioinformatic (REVEL on + CardioBoost off) and VCEP Curated Variants (EvRepo on
@@ -418,32 +434,33 @@
 # Phase D: Verification
 ##############################################################################
 #
 # (Build verification only. QA history, audit findings, and review/release
 #  readiness are tracked in Redmine #37446, not here.)
 #
 #   - hubCheck: silent pass (exit 0) on hg38 + hg19.
 #   - Cross-assembly parity (hg38 == hg19 feature counts):
 #       PM1 28 | PVS1 16 | AF 10,974 | REVEL 22,466 | EvRepo 25 | Walsh2019 155 |
 #       ClinVar 199 | Variant evidence 10,974 | CardioBoost 31,236
 #   - Worked example, MYH7 p.Arg870His (NM_000257.4:c.2609G>A, chr14:23424839 hg38):
 #       EvRepo:       Pathogenic, codes PM1;PM2;PP1_Strong;PS4
 #       EvRepo R870C: Likely Pathogenic at the adjacent codon-870 position
 #                     (the PS1/PM5 partner)
 #       PM1:          within MYH7 167-931
-#       REVEL:        0.853 -> PP3_supporting
-#       gnomAD AF:    absent from v4.1 exomes -> PM2_supporting
+#       REVEL:        0.807 -> PP3_supporting  (0.853 is the R870L alt=A allele at the
+#                     same position; R870H is the alt=T allele, REVEL 0.807)
+#       gnomAD AF:    present but rare in v4.1 exomes (FAF95 5.75e-06) -> PM2_supporting
 #       Variant evidence: PM1 hotspot, PM2 rarity, PP3/REVEL shown (each tagged with
 #                     the criterion it supports); no overall classification (the VCEP
 #                     Pathogenic call rests on PS4+PP1, manual)
 
 
 ##############################################################################
 # Phase E: Otto cron (TODO — gated on VCEP sign-off; do AFTER deployment)
 ##############################################################################
 #
 # DO NOT enable until the VCEP signs off (Phase F gate). The weekly refresh
 # touches EvRepo + ClinVar 506161 only; premature activation could surface
 # unreviewed VCEP curations on the public hub.
 #
 # Mirror the TP53 pattern at /hive/data/outside/otto/cardiomyopathyVCEP/
 # (doUpdate.sh + checkCMPVCEPClinVar.sh). Crontab (NOT activated until sign-off):