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/scripts/cardiomyopathyVCEP/cmpVCEPEvRepo.py src/hg/makeDb/scripts/cardiomyopathyVCEP/cmpVCEPEvRepo.py index dbc55b81dd7..cd73a3122cc 100644 --- src/hg/makeDb/scripts/cardiomyopathyVCEP/cmpVCEPEvRepo.py +++ src/hg/makeDb/scripts/cardiomyopathyVCEP/cmpVCEPEvRepo.py @@ -56,31 +56,31 @@ # MANE Select RefSeq accession per gene (for HGVS transcript-version normalization, item F). MANE_TSV = '/hive/users/lrnassar/claude/RM37446/cmp_downloads/mane_8genes.tsv' HGVSTOVCF = '/cluster/bin/x86_64/hgvsToVcf' def load_mane_acc(): acc = {} for line in open(MANE_TSV): f = line.rstrip('\n').split('\t') if len(f) < 7 or f[0] == 'geneSym': continue acc[f[0]] = f[6] # geneSym -> refSeqAcc (e.g. NM_000257.4) return acc -MANE_ACC = load_mane_acc() +MANE_ACC = {} # populated in main() once MANE_TSV is resolved from --output-dir def normalize_hgvs_version(hgvs, gene): """Item F: rewrite the displayed transcript version to the gene's MANE Select version (e.g. NM_000257.3(...) -> NM_000257.4(...)). Coordinate-neutral display fix.""" mane = MANE_ACC.get(gene) if not mane or '.' not in mane or not hgvs: return hgvs base = mane.rsplit('.', 1)[0] return re.sub(re.escape(base) + r'\.\d+', mane, hgvs) def coords_via_hgvstovcf(hgvs_list): """Item K fallback: when an entry has NO parseable NC_ genomic HGVS (e.g. repeat-notation deletions like c.2785_2787GAG[2]), derive coords from the NM_ c.HGVS via hgvsToVcf. @@ -325,30 +325,36 @@ def make_bigbed(bed_path, db, as_path, bb_path): cmd = ['bedToBigBed', '-tab', '-type=bed9+11', '-as=' + as_path, bed_path, CHROM_SIZES[db], bb_path] print(f' $ {" ".join(cmd)}') subprocess.run(cmd, check=True) def main(): ap = argparse.ArgumentParser() ap.add_argument('--db', action='append', required=True, choices=['hg38', 'hg19']) ap.add_argument('--output-dir', required=True) args = ap.parse_args() + # Source files live under --output-dir/cmp_downloads (see cmpVCEPProvisionalClass). + global EVREPO_JSON, MANE_TSV, MANE_ACC + EVREPO_JSON = f'{args.output_dir}/cmp_downloads/erepo/cardiomyopathyVCEP_classifications.json' + MANE_TSV = f'{args.output_dir}/cmp_downloads/mane_8genes.tsv' + MANE_ACC = load_mane_acc() # load here, not at import, so the resolved MANE_TSV is used + out_dir = os.path.join(args.output_dir, 'cmpVCEPEvRepo') os.makedirs(out_dir, exist_ok=True) print(' [B.7 EvRepo curated variants]') # Load JSON data = json.load(open(EVREPO_JSON)) interpretations = data['variantInterpretations'] print(f' loaded {len(interpretations)} interpretations from {EVREPO_JSON}') # Parse all records records = [extract_record(v) for v in interpretations] print(f' parsed {len(records)} records') # Sanity: count classifications