d0ed51d077718213c0b843a89fd6f36ac32f1804 braney Fri Sep 4 11:39:28 2026 -0700 quickLift: lift alignments, and let psl and bigPsl tracks into the hub Every type quickLift handled so far is one set of coordinates on one genome, so the lift is a call to remapBlockedBed. An alignment carries coordinates on both sides at once, with a block start on each, so moving the genome side means splitting and trimming blocks while keeping the other side lined up with them. quickLiftPsl does that with pieces that were already in the tree: pick the chain with liftOverChainForRange, the same one the bed path picks, turn it into a mapping alignment with chainToPsl plus pslSwap, then pslTransMap. The mapping alignment is kept per chain, since rebuilding it for every item costs nothing at gene zoom and a great deal zoomed out. Two things pslTransMap does had to be undone. It recounts match and mismatch off the blocks, which would read every lifted alignment as a perfect match and draw every item at full shade, so quickLiftPslCounts puts the original counts back, scaled by how much of the alignment survived. And it leaves a protein alignment in nucleotide space, which the base alignment view rejects, so quickLiftPslBackToProtein returns the query side to protein units when the lift did not split a codon. quickLiftChainHash hands out the chains for a reference range for callers that collected their items some other way. validateOneTdb now accepts psl and bigPsl, and bigPsl joins bigBed and bigWig in the bigDataUrl fill-in. refs #38249 diff --git src/hg/lib/trackHub.c src/hg/lib/trackHub.c index ca08288f003..264bbb41fa4 100644 --- src/hg/lib/trackHub.c +++ src/hg/lib/trackHub.c @@ -1939,40 +1939,44 @@ /* 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("bigPsl", tdb->type) || \ + sameWord("psl", tdb->type) || + startsWithNoCase("psl ", 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("bigPsl", 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; }