d0ddd717713f275dc2f567c9b6d733fd3f55bd90 markd Fri Oct 2 21:27:25 2026 -0700 Put PRO-cap and ProCapNet inside a Transcription Initiation folder. refs #35528 The two data sources were top-level superTracks because a superTrack could not be a member of another one. #38460 fixes that, so they now sit inside a transcriptionStart superTrack, which is what the collection was meant to be. The container is written before either of its children, and both children before any of their members: tdbQuery -strict rejects a file in which another track comes between a superTrack and one of its children. This depends on the #38460 build. A plain make here with the installed binaries produces a half-built state, since hgTrackDb drops the container from the table and trackDbToTxt then writes an hs1 curated hub whose member names a parent stanza that is not there. Both makedocs say so. diff --git src/hg/makeDb/outside/proCapNet/proCapNetTrackDb src/hg/makeDb/outside/proCapNet/proCapNetTrackDb index 676b91f9052..d48cc95a8b2 100755 --- src/hg/makeDb/outside/proCapNet/proCapNetTrackDb +++ src/hg/makeDb/outside/proCapNet/proCapNetTrackDb @@ -28,40 +28,52 @@ GBDB = "/gbdb/{db}/{track}" def parseArgs(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument("db") parser.add_argument("experimentsTsv") parser.add_argument("outRa") return cli.parseOptsArgsWithLogging(parser) def stanza(indent, lines): pad = " " * indent return "".join(pad + line + "\n" for line in lines) + "\n" -def sourceSuperStanza(track, shortLabel, longLabel): - """One top-level superTrack per data source. - - These were briefly nested under a transcriptionStart superTrack, which looks - legal and passes tdbQuery -check -strict but silently loses the outer level: - trackDbSuperMarkup() refuses to give a superTrack a parent, so hgTrackDb never - writes the outer one. See #38460.""" +def superStanza(): + "the container both data sources sit in" return stanza(0, [ + "track transcriptionStart", + "superTrack on show", + "group rna", + "shortLabel Transcription Initiation (TSS)", + "longLabel Transcription initiation (TSS)", + ]) + +def sourceSuperStanza(track, shortLabel, longLabel): + """One superTrack per data source, inside the transcriptionStart container. + + A superTrack inside a superTrack needs the fix in #38460; before it the outer + container passed tdbQuery -check -strict and was then silently dropped at + load. Every child of the container is written before any of their members, + because tdbQuery -strict rejects a file in which another track comes between + a superTrack and one of its children.""" + return stanza(4, [ f"track {track}", "superTrack on show", + "parent transcriptionStart", "group rna", f"shortLabel {shortLabel}", f"longLabel {longLabel}", ]) def strandOverlay(db, composite, exp, dataType, subDir, fileTag, shortLabel, longLabel, childLabel, priority, vis): """One cell line's two strands as an overlay, plus strand drawn up and minus strand drawn down. Both sources store the minus strand negated, so neither needs the trackDb negateValues setting. That setting used to be on the ProCapNet minus tracks, and it broke the composite's own negate control: that control sets one shared value for the composite, which replaced the per-track setting and sent both strands the same way, with no route back to the default short of a cart reset. @@ -156,30 +168,31 @@ out += strandOverlay(db, "encode4ProCap", exp, "procap", "", exp.procapAcc, f"{exp.cell} PRO-cap", f"{exp.cell} ({exp.procapAcc}) PRO-cap transcription start" f" sites, plus up minus down", f"{exp.cell} ({exp.procapAcc}) PRO-cap transcription start sites", priority, "full") return out def proCapNetTrackDb(opts, args): experiments = list(TsvReader(args.experimentsTsv)) fileOps.ensureFileDir(args.outRa) with fileOps.AtomicFileOpen(args.outRa) as fh: print(f"# Generated by hg/makeDb/outside/proCapNet/proCapNetTrackDb for {args.db}.", file=fh) print("# Do not edit by hand, edit the script and regenerate.\n", file=fh) + fh.write(superStanza()) if args.db == "hg38": fh.write(sourceSuperStanza( "encode4ProCap", "PRO-cap", "PRO-cap nascent RNA transcription start sites from ENCODE 4")) fh.write(sourceSuperStanza("proCapNet", "ProCapNet", "ProCapNet predicted PRO-cap")) if args.db == "hg38": fh.write(encode4ProCapTracks(args.db, experiments)) fh.write(proCapNetTracks(args.db, experiments)) def main(): opts, args = parseArgs() with cli.ErrorHandler(noStackExcepts=(OSError, cli.PycbioException)): proCapNetTrackDb(opts, args)