d121edc0bd2809f1d6de6185a497e6a288958479 braney Tue May 12 09:18:29 2026 -0700 hgConvert quickLift: skip pre-lifted tracks, append-and-merge hub file, per-track remove UI, refs #37535 In hgConvert / trackHubBuild: - Skip tracks that already came from a quickLift hub (quickLiftUrl / quickLifted setting) so they don't get re-lifted to a new destination. - Append new track stanzas to an existing per-source hub file instead of overwriting it; new stanzas get priorities after the existing max; duplicate track names are skipped. Also avoids re-emitting a parent supertrack that's already in the file. New public quickLiftHubRemoveTrack(cart, sourceDb, trackName) in trackHub.c rewrites the per-source hub file with the named stanza removed plus all descendant stanzas (parent reference cascade, transitive). hgTrackUi: adds a "Remove from QuickLift" link next to "Duplicate track" for any tdb carrying a quickLiftDb setting. The link hits hgTrackUi_op=quickLiftRemove which calls quickLiftHubRemoveTrack, hides the track in the cart, and 302s to hgTracks. The op argument cart var is qlSourceDb (renamed from quickLiftSourceDb to avoid colliding with the quickLift.* prefix used elsewhere; values cloned out of the cart hash before cartRemove so the helper doesn't see freed strings). hgTracks: adds a small "x" icon (printQuickLiftDelIcon) on tracks in a quickLift group, suppressed on the synthetic bigQuickLiftChain track. JS onQuickLiftDelIconClick fires the same hgTrackUi_op endpoint via synchronous XHR and removes every TD whose icon matches the deleted data-track, so the row goes away in both the QuickLift group and the Visible Tracks group. hubConnect cart handling fixes shaken out by the above: - hubConnectRemakeTrackHubVar's cart-var prefix is now "quickLift." (with the trailing dot) instead of "quickLift", so unrelated keys like qlSourceDb no longer get parsed as hubId/db and crash cart loading on every CGI. Also skips entries whose hubStatus lookup returned NULL. - hubConnectStatusListFromCart no longer calls removeQuickListReference when the current db isn't the lift's destination. A side trip to another assembly between two lifts to the same destination was deleting the earlier attachment's cart var; just skip attaching this load and leave the cart alone so the lift survives the round trip. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> diff --git src/hg/inc/quickLift.h src/hg/inc/quickLift.h index 3968cc1fb30..4c992fa3081 100644 --- src/hg/inc/quickLift.h +++ src/hg/inc/quickLift.h @@ -1,93 +1,97 @@ /* quickLift genome annotations on the fly between assemblies using chain files */ /* Copyright (C) 2023 The Regents of the University of California * See kent/LICENSE or http://genome.ucsc.edu/license/ for licensing information. */ #ifndef QUICKLIFT_H #define QUICKLIFT_H #define quickLiftCartName "hubQuickLift" #define quickLiftChainTableConfVariable "quickLiftChainName" #define defaultQuickLiftChainTableName "quickLiftChain" struct quickLiftRegions // store highlight information { struct quickLiftRegions *next; unsigned type; char *chrom; long chromStart; long chromEnd; char *bases; unsigned baseCount; char *oChrom; long oChromStart; long oChromEnd; char *otherBases; unsigned otherBaseCount; char * id; }; #define QUICKTYPE_INSERT 0 #define QUICKTYPE_DEL 1 #define QUICKTYPE_DOUBLE 2 #define QUICKTYPE_MISMATCH 3 extern char *quickTypeStrings[]; typedef struct slList *(*ItemLoader2)(char **row, int numFields); /* Load a bed file from an SQL query result. */ struct bigBedInterval *quickLiftGetIntervals(char *instaPortFile, struct bbiFile *bbi, char *chrom, int start, int end, struct hash **pChainHash); /* Return intervals from "other" species that will map to the current window. * These intervals are NOT YET MAPPED to the current assembly. */ struct bed *quickLiftIntervalsToBed(struct bbiFile *bbi, struct hash *chainHash, struct bigBedInterval *bb); /* Using chains stored in chainHash, port a bigBedInterval from another assembly to a bed * on the reference. */ struct slList *quickLiftSql(struct sqlConnection *conn, char *quickLiftFile, char *table, char *chromName, int winStart, int winEnd, char *query, char *extraWhere, ItemLoader2 loader, int numFields, struct hash *chainHash); /* Load a list of items (usually beds) from another database in a region that corresponds to chromName:winStart-winEnd in the reference database. * Fill a hash with the chains that were used to map the desired range. These chains will be used to map the query side items back to the reference. */ unsigned quickLiftGetChainId(struct cart *, char *fromDb, char *toDb); /* Return the id from the quickLiftChain table for given assemblies. */ char *quickLiftGetChainPath(struct cart *, char *fromDb, char *toDb); /* Return the path from the quickLiftChain table for given assemblies. */ struct bed *quickLiftBeds(struct bed *bedList, struct hash *chainHash, boolean blocked); // Map a list of bedd in query coordinates to our current reference boolean quickLiftEnabled(struct cart *cart); /* Return TRUE if feature is available */ struct quickLiftRegions *quickLiftGetRegions(char *ourDb, char *liftDb, char *quickLiftFile, char *chrom, int seqStart, int seqEnd); /* Figure out the highlight regions and cache them. */ char *quickLiftChainTable(); /* Return the name of the quickLiftChain table. */ void quickLiftResolveTable(struct trackDb *tdb, char *trackTable, char **retTable, char **retLiftDb); /* Resolve the table name and liftDb for a quickLift track. For custom tracks, * sets *retLiftDb to CUSTOM_TRASH and *retTable to the dbTableName setting; * otherwise sets *retTable to trackTable. Caller should have already set * *retLiftDb to trackDbSetting(tdb, "quickLiftDb"). */ struct bed *quickLiftSqlLoadBeds(struct trackDb *tdb, char *trackTable, char *liftDb, char *chrom, int start, int end, char *extraWhere, ItemLoader2 loader, int numFields, boolean blocked); /* Load items from another assembly via quickLift SQL, map them back to the reference, * and return the lifted beds. Handles custom track table resolution internally. * Caller provides liftDb from trackDbSetting(tdb, "quickLiftDb"). */ boolean quickLiftLiftPos(char *sourceDb, char *destDb, char *chrom, int start, int end, char **retChrom, int *retStart, int *retEnd); /* Map a position from source (sourceDb) coords to destination (destDb) coords * using the liftOver chain for sourceDb -> destDb. Used to remap hgFind * results from quickLifted bigBed tracks back to the destination assembly. */ + +boolean quickLiftHubRemoveTrack(struct cart *cart, char *sourceDb, char *trackName); +/* Remove a track stanza from the quickLift hub file for sourceDb. Returns + * TRUE if a stanza matching trackName was found and removed. */ #endif