7f7a9a5579d7acec698c51dbf93f5030ce1a0439
braney
  Tue Apr 8 15:43:17 2025 -0700
support genePred in quickLift

diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c
index cf1d8af99af..a009f821d1b 100644
--- src/hg/hgTracks/simpleTracks.c
+++ src/hg/hgTracks/simpleTracks.c
@@ -135,30 +135,32 @@
 #ifdef LOWELAB
 #include "loweLabTracks.h"
 #include "rnaPLFoldTrack.h"
 #endif /* LOWELAB */
 #ifdef LOWELAB_WIKI
 #include "wiki.h"
 #endif /* LOWELAB_WIKI */
 
 #include "trackVersion.h"
 #include "genbank.h"
 #include "bedTabix.h"
 #include "knetUdc.h"
 #include "trackHub.h"
 #include "hubConnect.h"
 #include "bigWarn.h"
+#include "quickLift.h"
+#include "liftOver.h"
 
 #define CHROM_COLORS 26
 
 /* Declare our color gradients and the the number of colors in them */
 Color shadesOfGreen[EXPR_DATA_SHADES];
 Color shadesOfRed[EXPR_DATA_SHADES];
 Color shadesOfBlue[EXPR_DATA_SHADES];
 Color shadesOfYellow[EXPR_DATA_SHADES];
 Color shadesOfGreenOnWhite[EXPR_DATA_SHADES];
 Color shadesOfRedOnWhite[EXPR_DATA_SHADES];
 Color shadesOfBlueOnWhite[EXPR_DATA_SHADES];
 Color shadesOfYellowOnWhite[EXPR_DATA_SHADES];
 Color shadesOfRedOnYellow[EXPR_DATA_SHADES];
 Color shadesOfBlueOnYellow[EXPR_DATA_SHADES];
 Color orangeColor = 0;
@@ -6247,39 +6249,79 @@
 if (tg->visibility != tvDense)
     slSort(&lfList, linkedFeaturesCmpStart);
 
 return lfList;
 }
 
 struct linkedFeatures *connectedLfFromGenePredInRange(struct track *tg, struct sqlConnection *conn,
                                                       char *table, char *chrom, int start, int end)
 /* Return linked features from range of a gene prediction table after
  * we have already connected to database. */
 {
 return connectedLfFromGenePredInRangeExtra(tg, conn, table, chrom,
                                                 start, end, FALSE);
 }
 
-struct linkedFeatures *lfFromGenePredInRange(struct track *tg, char *table,
-                                             char *chrom, int start, int end)
-/* Return linked features from range of a gene prediction table. */
+static void maybeLiftGenePred(struct track *tg, char *table, char *chrom, int start, int end, boolean extra)
+/* Load a bunch of genePreds, perhaps quickLifting them. */
+{
+char *liftDb = cloneString(trackDbSetting(tg->tdb, "quickLiftDb"));
+
+if (liftDb != NULL)
     {
+    char *table;
+    if (isCustomTrack(tg->table))
+        {
+        liftDb = CUSTOM_TRASH;
+        table = trackDbSetting(tg->tdb, "dbTableName");
+        }
+    else
+        table = tg->table;
+    struct hash *chainHash = newHash(8);
+    struct sqlConnection *conn = hAllocConn(liftDb);
+    char *quickLiftFile = cloneString(trackDbSetting(tg->tdb, "quickLiftUrl"));
+
+// using this loader on genePred tables with less than 15 fields may be a problem.
+extern struct genePred *genePredExtLoad15(char **row);
+
+    struct genePred *gpList = (struct genePred *)quickLiftSql(conn, quickLiftFile, table, chromName, winStart, winEnd,  NULL, NULL, (ItemLoader2)genePredExtLoad15, 0, chainHash);
+    hFreeConn(&conn);
+
+    calcLiftOverGenePreds( gpList, chainHash, 0.0, 1.0, TRUE, NULL, NULL,  TRUE, FALSE);
+    struct genePred *gp = gpList;
+
     struct linkedFeatures *lfList = NULL;
+    for(;gp; gp = gp->next)
+        slAddHead(&lfList, linkedFeaturesFromGenePred(tg, gp, TRUE));
+    slReverse(&lfList);
+    tg->items = lfList;
+    }
+else
+    {
     struct sqlConnection *conn = hAllocConn(database);
-lfList = connectedLfFromGenePredInRange(tg, conn, table, chrom, start, end);
+    tg->items = connectedLfFromGenePredInRangeExtra(tg, conn, tg->table,
+                                            chromName, winStart, winEnd, extra);
     hFreeConn(&conn);
-return lfList;
+    }
+}
+
+struct linkedFeatures *lfFromGenePredInRange(struct track *tg, char *table,
+                                             char *chrom, int start, int end)
+/* Return linked features from range of a gene prediction table. */
+{
+maybeLiftGenePred(tg, tg->tdb->table, chrom, start, end, FALSE);
+return tg->items;
 }
 
 void abbr(char *s, char *fluff)
 /* Cut out fluff from s. */
 {
 int len;
 s = strstr(s, fluff);
 if (s != NULL)
    {
    len = strlen(fluff);
    strcpy(s, s+len);
    }
 }
 
 char *genieName(struct track *tg, void *item)
@@ -6452,38 +6494,37 @@
 
 /* filter items on selected criteria if filter is available */
 if (!showComprehensive)
     filterItems(tg, knownGencodeClassFilter, "include");
 
 if (!showPseudo)
     filterItems(tg, knownGencodePseudoFilter, "exclude");
 
 /* if we're close enough to see the codon frames, we better load them! */
 if (zoomedToCdsColorLevel)
     loadFrames(conn, tg->items);
 
 hFreeConn(&conn);
 }
 
+
 void loadGenePredWithName2(struct track *tg)
 /* Convert gene pred in window to linked feature. Include alternate name
  * in "extra" field (usually gene name) */
 {
-struct sqlConnection *conn = hAllocConn(database);
-tg->items = connectedLfFromGenePredInRangeExtra(tg, conn, tg->table,
-                                        chromName, winStart, winEnd, TRUE);
-hFreeConn(&conn);
+maybeLiftGenePred(tg, tg->tdb->table, chromName, winStart, winEnd, TRUE);
+
 /* filter items on selected criteria if filter is available */
 filterItems(tg, genePredClassFilter, "include");
 }
 
 void lookupKnownNames(struct linkedFeatures *lfList)
 /* This converts the Genie ID to the HUGO name where possible. */
 {
 struct linkedFeatures *lf;
 char query[256];
 struct sqlConnection *conn = hAllocConn(database);
 
 if (hTableExists(database, "knownMore"))
     {
     struct knownMore *km;
     struct sqlResult *sr;
@@ -7799,31 +7840,35 @@
 
 char *refGeneMapName(struct track *tg, void *item)
 /* Return un-abbreviated gene name. */
 {
 struct linkedFeatures *lf = item;
 char buffer[1024];
 safecpy(buffer, sizeof buffer, lf->name);
 chopSuffix(buffer);
 return cloneString(buffer);
 }
 
 void lookupRefNames(struct track *tg)
 /* This converts the refSeq accession to a gene name where possible. */
 {
 struct linkedFeatures *lf;
-struct sqlConnection *conn = hAllocConn(database);
+char *liftDb = cloneString(trackDbSetting(tg->tdb, "quickLiftDb"));
+char *db = database;
+if (liftDb)
+    db = liftDb;
+struct sqlConnection *conn = hAllocConn(db);
 boolean isNative = !sameString(tg->table, "xenoRefGene");
 boolean labelStarted = FALSE;
 boolean useGeneName = FALSE;
 boolean useAcc =  TRUE;
 boolean useMim =  FALSE;
 char trackLabel[1024];
 char *labelString = tg->table;
 boolean isRefGene = TRUE;
 
 if (startsWith("ncbiRefSeq", labelString))
     {
     labelString="refSeqComposite";
     isRefGene = FALSE;
     }
 else if (tdbIsCompositeChild(tg->tdb) && sameWord("refGene", labelString))
@@ -8128,36 +8173,38 @@
 
 tg->ixAltColor = col;
 return(col);
 }
 
 Color refGeneColorByStatus(struct track *tg, char *name, struct hvGfx *hvg)
 /* Get refseq gene color from refSeqStatus.
  * Reviewed, Validated -> normal, Provisional -> lighter,
  * Predicted, Inferred(other) -> lightest
  * If no refSeqStatus, color it normally.
  */
 {
 int col = tg->ixColor;
 struct rgbColor *normal = &(tg->color);
 struct rgbColor lighter, lightest;
-struct sqlConnection *conn = hAllocConn(database);
+char *liftDb = cloneString(trackDbSetting(tg->tdb, "quickLiftDb"));
+char *db = (liftDb == NULL) ? database : liftDb;
+struct sqlConnection *conn = hAllocConn(db);
 struct sqlResult *sr;
 char **row;
 char query[256];
 
-if (startsWith("ncbiRefSeq", tg->table))
+if (startsWith("ncbiRefSeq", trackHubSkipHubName(tg->table)))
     {
     sqlSafef(query, sizeof query, "select status from ncbiRefSeqLink where id = '%s'", name);
     }
 else
     sqlSafef(query, sizeof query, "select status from %s where mrnaAcc = '%s'",
         refSeqStatusTable, name);
 sr = sqlGetResult(conn, query);
 if ((row = sqlNextRow(sr)) != NULL)
     {
     if (startsWith("Reviewed", row[0]) || startsWith("Validated", row[0]))
         {
         /* Use the usual color */
         }
     else if (startsWith("Provisional", row[0]))
         {
@@ -8183,33 +8230,35 @@
 
 Color refGeneColor(struct track *tg, void *item, struct hvGfx *hvg)
 /* Return color to draw refseq gene in. */
 {
 struct linkedFeatures *lf = item;
 
 /* allow itemAttr to override coloring */
 if (lf->itemAttr != NULL)
     return hvGfxFindColorIx(hvg, lf->itemAttr->colorR, lf->itemAttr->colorG, lf->itemAttr->colorB);
 
 /* If refSeqStatus is available, use it to determine the color.
  * Reviewed, Validated -> normal, Provisional -> lighter,
  * Predicted, Inferred(other) -> lightest
  * If no refSeqStatus, color it normally.
  */
-struct sqlConnection *conn = hAllocConn(database);
+char *liftDb = cloneString(trackDbSetting(tg->tdb, "quickLiftDb"));
+char *db = (liftDb == NULL) ? database : liftDb;
+struct sqlConnection *conn = hAllocConn(db);
 Color color = tg->ixColor;
-if (sqlTableExists(conn,  refSeqStatusTable) || hTableExists(database,  "ncbiRefSeqLink"))
+if (sqlTableExists(conn,  refSeqStatusTable) || hTableExists(db,  "ncbiRefSeqLink"))
     color = refGeneColorByStatus(tg, lf->name, hvg);
 hFreeConn(&conn);
 return color;
 }
 
 void ncbiRefSeqMethods(struct track *tg)
 /* Make NCBI Genes track */
 {
 tg->loadItems = loadNcbiRefSeq;
 tg->itemName = refGeneName;
 tg->mapItemName = ncbiRefGeneMapName;
 tg->itemColor = refGeneColor;
 }
 
 void refGeneMethods(struct track *tg)
@@ -13845,31 +13894,31 @@
 tg->mapItem       = bedPlusLabelMapItem;
 tg->nextPrevExon = simpleBedNextPrevEdge;
 }
 
 static char *omimAvSnpAaReplacement(char *db, char *name)
 /* Return replacement string associated with a OMIM AV (Allelic Variant) entry */
 {
 static char omimAvSnpBuffer[256];
 struct sqlConnection *conn;
 char query[256];
 struct sqlResult *sr;
 char **row;
 
 omimAvSnpBuffer[0] = '\0';
 
-conn = hAllocConn(database);
+conn = hAllocConn(db);
 sqlSafef(query,sizeof(query),
         "select repl2, dbSnpId, description from omimAv where avId='%s'", name);
 sr = sqlMustGetResult(conn, query);
 row = sqlNextRow(sr);
 
 if (row != NULL)
     {
     safef(omimAvSnpBuffer, sizeof(omimAvSnpBuffer), "%s, %s: %s", row[0], row[1], row[2]);
     }
 
 hFreeConn(&conn);
 sqlFreeResult(&sr);
 return(omimAvSnpBuffer);
 }
 
@@ -13886,31 +13935,31 @@
 tg->drawItemAt = bedPlusLabelDrawAt;
 tg->mapItem    = bedPlusLabelMapItem;
 tg->nextPrevExon = simpleBedNextPrevEdge;
 }
 
 
 static char *omimLocationDescription(char *db, char *name)
 /* Return description of an OMIM entry */
 {
 static char omimLocationBuffer[512];
 struct sqlConnection *conn;
 char query[256];
 
 omimLocationBuffer[0] = '\0';
 
-conn = hAllocConn(database);
+conn = hAllocConn(db);
 sqlSafef(query,sizeof(query),
         "select geneName from omimGeneMap2 where omimId=%s", name);
 (void)sqlQuickQuery(conn, query, omimLocationBuffer, sizeof(omimLocationBuffer));
 hFreeConn(&conn);
 return(omimLocationBuffer);
 }
 
 Color omimLocationColor(struct track *tg, void *item, struct hvGfx *hvg)
 /* set the color for omimLocation track items */
 {
 struct bed *el = item;
 char *phenClass;
 char query[256];
 struct sqlResult *sr;
 char **row;
@@ -13939,31 +13988,33 @@
 lighter.g = (6*normal->g + 4*255) / 10;
 lighter.b = (6*normal->b + 4*255) / 10;
 lighter.a = normal->a;
 
 lightest.r = (1*normal->r + 2*255) / 3;
 lightest.g = (1*normal->g + 2*255) / 3;
 lightest.b = (1*normal->b + 2*255) / 3;
 lightest.a = normal->a;
 
 class1Clr = hvGfxFindColorIx(hvg, lightest.r, lightest.g, lightest.b);
 class2Clr = hvGfxFindColorIx(hvg, lighter.r, lighter.g, lighter.b);
 class3Clr = hvGfxFindColorIx(hvg, normal->r, normal->g, normal->b);
 class4Clr = hvGfxFindColorIx(hvg, 105,50,155);
 classOtherClr = hvGfxFindColorIx(hvg, 190, 190, 190);   // light gray
 
-struct sqlConnection *conn = hAllocConn(database);
+char *liftDb = cloneString(trackDbSetting(tg->tdb, "quickLiftDb"));
+char *db = (liftDb == NULL) ? database : liftDb;
+struct sqlConnection *conn = hAllocConn(db);
 
 sqlSafef(query, sizeof(query),
       "select omimId, %s from omimPhenotype where omimId=%s", omimPhenotypeClassColName, el->name);
 sr = sqlMustGetResult(conn, query);
 row = sqlNextRow(sr);
 
 hFreeConn(&conn);
 
 if (row == NULL)
     {
     // set to gray if this entry does not have any disorder info
     sqlFreeResult(&sr);
     return classOtherClr;
     }
 else
@@ -15206,32 +15257,32 @@
                 from black, to the specified color */
     deltaR = (finalR - altR) / altColors;
     deltaG = (finalG - altG) / altColors;
     deltaB = (finalB - altB) / altColors;
     // speculative - no harm, but there's no current way for a track to set its alpha,
     // so both final and altA should be 255
     deltaA = (finalA - altA) / altColors;
     }
 
 /* fill in subtracks of composite track */
 for (tdbRef = tdbRefList; tdbRef != NULL; tdbRef = tdbRef->next)
     {
     subTdb = tdbRef->val;
 
     subtrack = trackFromTrackDb(subTdb);
-    handler = lookupTrackHandlerClosestToHome(subTdb);
-    if (handler != NULL)
+    boolean avoidHandler = FALSE;// trackDbSettingOn(tdb, "avoidHandler");
+    if (!avoidHandler && ( handler = lookupTrackHandlerClosestToHome(subTdb)) != NULL)
         handler(subtrack);
 
     /* Add subtrack settings (table, colors, labels, vis & pri).  This is only
      * needed in the "not noInherit" case that hopefully will go away soon. */
     subtrack->track = subTdb->track;
     subtrack->table = subTdb->table;
     subtrack->shortLabel = subTdb->shortLabel;
     subtrack->longLabel = subTdb->longLabel;
     subtrack->priority = subTdb->priority;
     subtrack->parent = track;
 
     /* Add color gradient. */
     if (finalR || finalG || finalB)
 	{
 	subtrack->color.r = altR;