53ab3f1e293a91ddf71ec7568f4a6ff827bcd278 lrnassar Fri Oct 2 13:52:36 2026 -0700 Native GPN-Star track (Ye, Benegas et al., Nature 2026) on hg38, mm39, galGal6, dm6 and ce11, from the authors' Hugging Face hub. Each model is a multiWig sequence logo plus a four-allele -LLR composite using negateValues. The three hg38 models (V/M/P) sit in predictionScoresSuper via human/gpnStar.ra with /gbdb/$D bigDataUrls so -strict drops them on other human assemblies; the other four get a standalone gpnStar superTrack. The authors' bigWigs come from pyBigWig, whose bwAddIntervalSpanSteps writes the last section of each run 6 bases too long (pyBigWig #166) and makes bigWigAverageOverBed and bigWigCorrelate abort, so gpnStarRebuild.sh re-encodes them with wigToBigWig and gpnStarVerify.sh checks every per-base value is unchanged. Entropy scores and the GenArk-only Arabidopsis set are left out, and pennantIcon still has #TBD placeholders for the newsarch anchor and date. refs #38451 diff --git src/hg/makeDb/scripts/gpnStar/gpnStarCheckSections.py src/hg/makeDb/scripts/gpnStar/gpnStarCheckSections.py new file mode 100755 index 00000000000..ffc1b61b24b --- /dev/null +++ src/hg/makeDb/scripts/gpnStar/gpnStarCheckSections.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +"""Report bigWig fixedStep sections whose header end-start disagrees with itemCount. + +The GPN-Star bigWigs from Hugging Face have such sections (end overshoots by 6 before +each coverage gap), which makes kent bigWigAverageOverBed and bigWigCorrelate abort. + +usage: gpnStarCheckSections.py file.bw nShow +""" +import struct, sys, zlib +f = open(sys.argv[1], "rb"); nShow = int(sys.argv[2]) +h = f.read(64) +magic, ver, zl, chromTree, dataOff, indexOff = struct.unpack("<IHHQQQ", h[:32]) +uncompBuf = struct.unpack("<I", h[52:56])[0] +f.seek(indexOff); rh = f.read(48) +def leaves(off): + f.seek(off); isLeaf, _, cnt = struct.unpack("<BBH", f.read(4)) + if isLeaf: + items = [struct.unpack("<IIIIQQ", f.read(32))[4:] for _ in range(cnt)] + for it in items: yield it + else: + kids = [struct.unpack("<IIIIQ", f.read(24))[4] for _ in range(cnt)] + for k in kids: yield from list(leaves(k)) +shown = bad = total = 0 +for off, size in list(leaves(indexOff + 48)): + f.seek(off); raw = f.read(size) + buf = zlib.decompress(raw) if uncompBuf else raw + chromId, start, end, step, span, typ, _, cnt = struct.unpack("<IIIIIBBH", buf[:24]) + payload = len(buf) - 24 + total += 1 + mismatch = (typ == 3 and step == 1 and span == 1 and end - start != cnt) + bad += mismatch + if shown < nShow or (mismatch and bad <= 3): + print(f"type={typ} start={start} end={end} end-start={end-start} itemCount={cnt} payloadFloats={payload//4} {'MISMATCH' if mismatch else ''}") + shown += 1 +print(f"sections={total} fixedStep step1 sections with end-start != itemCount: {bad}")