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/cmpVCEPClinVar506161.py src/hg/makeDb/scripts/cardiomyopathyVCEP/cmpVCEPClinVar506161.py index d41eaa2bed9..69bd7be592a 100644 --- src/hg/makeDb/scripts/cardiomyopathyVCEP/cmpVCEPClinVar506161.py +++ src/hg/makeDb/scripts/cardiomyopathyVCEP/cmpVCEPClinVar506161.py @@ -27,38 +27,32 @@ SUBMISSIONS_TSV = '/hive/users/lrnassar/claude/RM37446/cmp_downloads/clinvar/cardiomyopathyVCEP_submissions.tsv' VARIANT_SUMMARY = '/hive/data/outside/otto/clinvar/downloads/2026-05-30/variant_summary.txt.gz' # Standard 5-tier ACMG ramp (same as EvRepo / Walsh 2019); the "with codes vs no codes" # distinction is carried by the track name and mouseover, not by color. COLORS = { 'Pathogenic': '210,0,0', 'Likely pathogenic': '245,152,152', 'Uncertain significance': '0,0,136', 'Likely benign': '213,247,213', 'Benign': '0,210,0', } DEFAULT_COLOR = '136,136,136' # Per-gene EvRepo VariationIDs - built once at build-time from EvRepo JSON -EVREPO_VAR_IDS = set() +EVREPO_VAR_IDS = set() # populated in main() once EVREPO_JSON is resolved from --output-dir EVREPO_JSON = '/hive/users/lrnassar/claude/RM37446/cmp_downloads/erepo/cardiomyopathyVCEP_classifications.json' -try: - _erepo = json.load(open(EVREPO_JSON)) - EVREPO_VAR_IDS = set(v.get('variationId', '') for v in _erepo['variantInterpretations'] if v.get('variationId')) - print(f' loaded {len(EVREPO_VAR_IDS)} EvRepo VariationIDs (will tag overlapping rows)') -except Exception as e: - print(f' WARNING: could not load EvRepo JSON: {e}', file=sys.stderr) CHROM_SIZES = { 'hg38': '/cluster/data/hg38/chrom.sizes', 'hg19': '/cluster/data/hg19/chrom.sizes', } AUTOSQL = """table cmpVCEPClinVar506161 "ClinVar submitter 506161 (ClinGen Cardiomyopathy VCEP) - Final, no evidence codes attached" ( string chrom; "Chromosome" uint chromStart; "Start position (BED 0-based)" uint chromEnd; "End position (BED half-open)" string name; "Display name (gene + hgvsP + classification initial)" uint score; "Always 0" char[1] strand; "Always +" @@ -221,30 +215,41 @@ 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 SUBMISSIONS_TSV, EVREPO_JSON, EVREPO_VAR_IDS + SUBMISSIONS_TSV = f'{args.output_dir}/cmp_downloads/clinvar/cardiomyopathyVCEP_submissions.tsv' + EVREPO_JSON = f'{args.output_dir}/cmp_downloads/erepo/cardiomyopathyVCEP_classifications.json' + try: # load here, not at import, so the resolved EVREPO_JSON is used + _erepo = json.load(open(EVREPO_JSON)) + EVREPO_VAR_IDS = set(v.get('variationId', '') for v in _erepo['variantInterpretations'] if v.get('variationId')) + print(f' loaded {len(EVREPO_VAR_IDS)} EvRepo VariationIDs (will tag overlapping rows)') + except Exception as e: + print(f' WARNING: could not load EvRepo JSON: {e}', file=sys.stderr) + out_dir = os.path.join(args.output_dir, 'cmpVCEPClinVar506161') os.makedirs(out_dir, exist_ok=True) print(' [B.8 ClinVar submitter 506161]') submissions = load_submissions() coords = load_variant_summary_coords(submissions) # Distribution sanity from collections import Counter review = Counter(s['review_status'] for s in submissions.values()) print(f' review-status: {dict(review)} (expecting 199 expert-panel-reviewed)') classes = Counter(s['classification'] for s in submissions.values()) print(f' classifications: {dict(classes)}') n_in_erepo = sum(1 for v in submissions if v in EVREPO_VAR_IDS)