f665d4cc3b02924a8507b2f910eaf85eab54d433
braney
  Sat Jul 18 14:12:24 2026 -0700
hprc2X: left-shifted HPRC r2 deletion analysis and external-catalog cross-reference scripts

Deletion-only re-derivation of the HPRC Release 2 rearrangement track used to
test left-shifting indel placement and to measure how the deletions correspond
to dbSNP, DGV, ClinVar, and the previous (rel1) release. Includes the unbounded
left-normalizer, the aggregation and subsampling drivers, the stability and
cross-release carryover analyses, and the dbSNP rs cross-reference prototype.
See README.txt for the manifest; full results and cached data live in
/hive/data/genomes/hg38/bed/hprc2X.

refs #37891

diff --git src/hg/makeDb/scripts/hprc2X/dumpAbsentFixed.py src/hg/makeDb/scripts/hprc2X/dumpAbsentFixed.py
new file mode 100644
index 00000000000..c6fa3612ed3
--- /dev/null
+++ src/hg/makeDb/scripts/hprc2X/dumpAbsentFixed.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python3
+# Dump rel1 fixed (recurrence==88) deletions split by whether they are present in rel2 full
+# (any-length within +/-20bp). Writes two BEDs: absent (the ~90) and present (control).
+import bisect
+D="/hive/data/genomes/hg38/bed/hprc2X"
+byC={}
+with open(D+"/hprc2X.canon.tsv") as f:
+    for line in f:
+        k=line.split("\t",1)[0]; c,s,l=k.split(":"); byC.setdefault(c,[]).append(int(s))
+for c in byC: byC[c].sort()
+def near(lst,x,w=20):
+    if not lst: return False
+    i=bisect.bisect_left(lst,x)
+    return (i<len(lst) and abs(lst[i]-x)<=w) or (i>0 and abs(lst[i-1]-x)<=w)
+ab=open(D+"/fixedAbsent.bed","w"); pr=open(D+"/fixedPresent.bed","w")
+na=npr=0
+for line in open(D+"/hprc1.canon.tsv"):
+    k,r=line.rstrip("\n").split("\t")
+    if int(r)!=88: continue
+    c,s,l=k.split(":"); s=int(s); e=s+int(l)
+    if near(byC.get(c),s):
+        pr.write("%s\t%d\t%d\t%s\n"%(c,s,e,k)); npr+=1
+    else:
+        ab.write("%s\t%d\t%d\t%s\n"%(c,s,e,k)); na+=1
+ab.close(); pr.close()
+print("fixed rel1 events: absent-from-rel2=%d  present=%d"%(na,npr))