f29b65452a1cca8a5bc62f007100b313e589d036 braney Sun Sep 6 15:11:36 2026 -0700 quickLift: lift a bigNet track, refs #20824 A net is not an ordinary track to lift. It is an alignment of two assemblies, so only its target side moves to the new reference; the query side names a third assembly and is carried across untouched. And the browser draws a net by recursion, so what really has to survive the lift is the tree: a row's level only means anything relative to the row above it. chainNetLoadRangeQuickLift() maps each row's target range with quickLiftIntervalsToBedClip, which is the same code every other quickLift track uses, so a net row lands where a bed of the same span would. The surviving rows then go to the same helpToNet() the unlifted path uses, so there is one tree builder and not two. The row collection either path does is now cnlHelperNew and cnlHelperAddBigNet. validateOneTdb lets bigNet into a quickLift hub. Its chain track is not offered, so a lifted net's details page has no chain to follow and says so rather than looking for a track this assembly does not have. bigNetLoadOne lifts the same way for that page, unclipped, so it reports the item's whole extent. bigNetFromInterval passes -1 as the cached chromId. bbiCachedChromLookup leaves the buffer alone when the id matches the one before it, so a cache that outlives the buffer hands back stale bytes. Measured against the standalone liftOver tool, on hg19 chr22's mouse net lifted to hg38: 36 of 36 source rows in the sampled window land on the same coordinates, counting the one liftOver will not take whole, whose two ends it does place exactly where the browser puts them. Against hg38's own mouse net, computed independently, 1.02% of the drawn pixels differ. diff --git src/hg/lib/trackHub.c src/hg/lib/trackHub.c index 1949b8458dc..599b19d8e0b 100644 --- src/hg/lib/trackHub.c +++ src/hg/lib/trackHub.c @@ -1940,40 +1940,42 @@ /* Make sure the tdb is a track type we grok. badList may be NULL to validate * silently (no user-facing complaint about non-liftable types). */ { // trackDb types are matched without regard to case since that's how the rest of the // browser reads them (some trackDb stanzas say "bigbed" rather than "bigBed"). if (sameString("cytoBandIdeo", trackHubSkipHubName(tdb->track)) || !( startsWithNoCase("bigBed", tdb->type) || \ startsWithNoCase("bigWig", tdb->type) || \ startsWithNoCase("bigDbSnp", tdb->type) || \ startsWithNoCase("bigGenePred", tdb->type) || \ startsWithNoCase("gvf", tdb->type) || \ startsWithNoCase("genePred", tdb->type) || \ startsWithNoCase("narrowPeak", tdb->type) || \ startsWithNoCase("broadPeak", tdb->type) || \ startsWithNoCase("bigLolly", tdb->type) || \ + startsWithNoCase("bigNet", tdb->type) || \ sameWord("bed", tdb->type) || startsWithNoCase("bed ", tdb->type))) { if (badList != NULL) slAddHead(badList, tdb); return FALSE; } // make sure we have a bigDataUrl if (startsWithNoCase("bigBed", tdb->type) || \ + startsWithNoCase("bigNet", tdb->type) || \ startsWithNoCase("bigWig", tdb->type)) { char *fileName = cloneString(trackDbSetting(tdb, "bigDataUrl")); if (fileName == NULL) { struct sqlConnection *conn = hAllocConnTrack(db, tdb); fileName = bbiNameFromSettingOrTable(tdb, conn, tdb->table); hashAdd(tdb->settingsHash, "bigDataUrl", fileName); hFreeConn(&conn); } } return TRUE; }