4a64fe1801134843e9082ab6cea091a5d0eb1c4c
braney
  Sat Jun 7 11:29:44 2025 -0700
fix up the list of tracks that will get quickLifted by hgConvert

diff --git src/hg/lib/trackHub.c src/hg/lib/trackHub.c
index 8d268395b3c..04d3aaaea59 100644
--- src/hg/lib/trackHub.c
+++ src/hg/lib/trackHub.c
@@ -1524,30 +1524,31 @@
 }
 
 static char *vettedTracks[] =
 /* tracks that have been tested with quickLift */
 {
 "decipherSnvs",
 "omimLocation",
 "omimAvSnp",
 "ncbiRefSeq",
 "clinvar",
 "clinvarSubLolly",
 "pubsBlat",
 "pubsMarkerBand",
 "pubsMarkerSnp",
 "pubsMarkerGene",
+//"gtexGeneV8",
 };
 
 static boolean isVetted(char *track)
 /* Is this a track that's been tested with quickLift?  If not we don't want to do the special name handling on the track. */
 {
 static bool inited = FALSE;
 static struct hash *vettedHash = NULL;
 
 if (!inited)
     {
     vettedHash = newHash(10);
 
     int ii;
     int len = sizeof(vettedTracks) / sizeof(char *);
 
@@ -1604,56 +1605,71 @@
 bool enabledInTdb = subtrackEnabledInTdb(tdb);
 char option[1024];
 safef(option, sizeof(option), "%s_sel", tdb->track);
 boolean enabled = cartUsualBoolean(cart, option, enabledInTdb);
 if (overrideComposite)
     enabled = TRUE;
 return enabled;
 }       
             
         
 static void dumpTdbAndChildren(struct cart *cart, struct dyString *dy, struct trackDb *tdb)
 /* Put a trackDb entry into a dyString, stepping up the tree for some variables. */
 {
 struct hashCookie cookie = hashFirst(tdb->settingsHash);
 struct hashEl *hel;
+
+char *cartVis = cartOptionalString(cart, tdb->track);
+if (cartVis != NULL)
+    tdb->visibility = hTvFromString(cartVis);
 dyStringPrintf(dy, "visibility %s\n", hStringFromTv(tdb->visibility));
+
+if (tdbIsSuperTrack(tdb->parent))
+    dyStringPrintf(dy, "parent %s\n", tdb->parent->track);
+
 while ((hel = hashNext(&cookie)) != NULL)
     {   
-    if (differentString(hel->name, "track") && differentString(hel->name, "visibility"))
+    if (sameString(hel->name, "parent"))
         {
-        if (sameString(hel->name, "html"))
-            dyStringPrintf(dy, "%s %s\n", hel->name, trackHubSkipHubName((char *)hel->val));
+        char buffer[1024];
+
+        safef(buffer, sizeof buffer, "%s_sel", tdb->track);
+        char *cartSelected = cartOptionalString(cart, tdb->track);
+        if (cartSelected != NULL)
+            {
+            char *str = "off";
+            if (sameString(cartSelected, "1"))
+                str = "on";
+            dyStringPrintf(dy, "parent %s %s\n", tdb->parent->track, str);
+            }
         else
             dyStringPrintf(dy, "%s %s\n", hel->name, ((char *)hel->val));
         }
+    else if (sameString(hel->name, "html"))
+        dyStringPrintf(dy, "%s %s\n", hel->name, trackHubSkipHubName((char *)hel->val));
+    else if (differentString(hel->name, "track") && differentString(hel->name, "visibility"))
+        dyStringPrintf(dy, "%s %s\n", hel->name, ((char *)hel->val));
     }
 
 if (tdb->subtracks)
     {
     for (tdb = tdb->subtracks; tdb; tdb = tdb->next)
         {
         char *track =  trackHubSkipHubName(tdb->track);
         dyStringPrintf(dy, "\ntrack %s\nquickLifted on\n", track);
         if (!isVetted(track))
             dyStringPrintf(dy, "avoidHandler on\n");
-        if (isParentVisible(cart, tdb) &&  isSubtrackVisible(cart, tdb)) // child of supertrack
-            {
-            char *cartVis = cartOptionalString(cart, tdb->parent->track);
-            if (cartVis != NULL)
-                tdb->visibility = hTvFromString(cartVis);
-            }
         dumpTdbAndChildren(cart, dy, tdb);
         }
     }
 }
 
 
 
 struct dyString *trackDbString(struct cart *cart, struct trackDb *tdb)
 /* Convert a trackDb entry into a dyString. */
 {
 struct dyString *dy;
 
 // add a note that the name based handler shouldn't be used on this track
 // add a note that this is a quickLifted track so the browser will accept tracks that aren't big*
 dy = dyStringNew(200);
@@ -1664,56 +1680,57 @@
     {
     dyStringPrintf(dy, "superTrack on show\n");
     }
 
 if (!isVetted(track))
     dyStringPrintf(dy, "avoidHandler on\n");
     
 dumpTdbAndChildren(cart, dy, tdb);
 
 return dy;
 }
 
 static boolean validateOneTdb(char *db, struct trackDb *tdb, struct trackDb **badList)
 /* Make sure the tdb is a track type we grok. */
 {
-if (!( startsWith("bigBed", tdb->type) || \
+if (sameString("cytoBandIdeo", tdb->track) || !( startsWith("bigBed", tdb->type) || \
        startsWith("bigWig", tdb->type) || \
        startsWith("bigDbSnp", tdb->type) || \
        startsWith("bigGenePred", tdb->type) || \
        startsWith("gvf", tdb->type) || \
        startsWith("genePred", tdb->type) || \
        startsWith("narrowPeak", tdb->type) || \
        startsWith("bigLolly", tdb->type) || \
        sameString("bed", tdb->type) ||
        startsWith("bed ", tdb->type)))
     {
     printf("%s %s<BR>\n",tdb->track,tdb->type);
     return FALSE;
     }
 
 // make sure we have a bigDataUrl
 if (startsWith("bigBed", tdb->type) || \
        startsWith("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;
 }
 
 static struct trackDb * validateTdbChildren(struct cart *cart, char *db, struct trackDb *tdb, struct trackDb **badList)
 /* return a list of the children that can be quick lifted */
 {
 struct trackDb *validTdbs = NULL;
 struct trackDb *nextTdb;
 unsigned count = 0;
 
 if (tdb->subtracks)  // this is a view, descend again
     {
@@ -1754,91 +1771,91 @@
 // make sure we only output track types that can
 // be quickLifted.  Return true if we any tracks survive
 {
 if (tdb->subtracks)
     {
     tdb->subtracks = validateTdbChildren(cart, db, tdb->subtracks, badList);
 
     if (tdb->subtracks == NULL)
         return FALSE;
     return TRUE;
     }
 
 return validateOneTdb(db, tdb, badList);
 }
 
-static void walkTree(FILE *f, char *db, struct cart *cart,  struct trackDb *tdb, struct dyString *visDy, struct trackDb **badList)
-/* walk tree looking for visible tracks. */
+static void outTrack(FILE *f, struct cart *cart, struct trackDb *tdb, unsigned priority)
+/* Set priority and output track to hub. */
 {
-unsigned priority = 0;
-struct hash *haveSuper = newHash(0);
 char buffer[1024];
 
-for(; tdb; tdb = tdb->next)
-    {
-    boolean isVisible = FALSE;
+safef(buffer, sizeof buffer, "%d", priority);
+hashReplace(tdb->settingsHash, "priority", cloneString(buffer));
 
-    if (tdb->parent == NULL)  // not in super track
+struct dyString *dy = trackDbString(cart, tdb);
+fprintf(f, "%s\n", dy->string);
+}
+
+static boolean checkCartVisibility(struct cart *cart, struct trackDb *tdb)
 {
 char *cartVis = cartOptionalString(cart, tdb->track);
 if (cartVis != NULL)
-            {
     tdb->visibility = hTvFromString(cartVis);
+return (tdb->visibility != tvHide);
 }
-        isVisible =  tdb->visibility != tvHide;
-        }
+
+static void walkTree(FILE *f, char *db, struct cart *cart,  struct trackDb *tdb, struct dyString *visDy, struct trackDb **badList)
+/* walk tree looking for visible tracks to output to hub. */
+{
+unsigned priority = 1;
+struct hash *haveSuper = newHash(0);
+
+for(; tdb; tdb = tdb->next)
+    {
+    boolean isVisible =  FALSE;
+
+    if (tdb->parent == NULL)
+        isVisible = checkCartVisibility(cart, tdb);
     else if (isParentVisible(cart, tdb) &&  isSubtrackVisible(cart, tdb)) // child of supertrack
         {
         if (hashLookup(haveSuper, tdb->parent->track) == NULL)  // output yet?
             {
-            char *cartVis = cartOptionalString(cart, tdb->parent->track);
-            if (cartVis != NULL)
+            //if (checkCartVisibility(cart, tdb->parent))
                 {
-                tdb->parent->visibility = hTvFromString(cartVis);
-                }
-            safef(buffer, sizeof buffer, "%d", priority++);
-            hashReplace(tdb->parent->settingsHash, "priority", cloneString(buffer));
-            struct dyString *dy = trackDbString(cart, tdb->parent);
-            fprintf(f, "%s\n", dy->string);
+                tdb->parent->visibility = hTvFromString("tvShow");
+                outTrack(f, cart, tdb->parent, priority++);
 
                 hashStore(haveSuper, tdb->parent->track);
                 }
-        char *cartVis = cartOptionalString(cart, tdb->track);
-        if (cartVis != NULL)
-            tdb->visibility = hTvFromString(cartVis);
-        isVisible =  tdb->visibility != tvHide;
+            }
+        isVisible = checkCartVisibility(cart, tdb);
         }
 
     if (isVisible && validateTdb(cart, db, tdb, badList))
         {
         hashRemove(tdb->settingsHash, "superTrack");   // this gets inherited by subTracks(?)
 
-        safef(buffer, sizeof buffer, "%d", priority++);
-        hashReplace(tdb->settingsHash, "priority", cloneString(buffer));
-
         // is this a custom track?
         char *tdbType = trackDbSetting(tdb, "tdbType");
         if (tdbType != NULL)
             {
             hashReplace(tdb->settingsHash, "type", tdbType);
             hashReplace(tdb->settingsHash, "shortLabel", trackDbSetting(tdb, "name"));
             hashReplace(tdb->settingsHash, "longLabel", trackDbSetting(tdb, "description"));
             }
 
-        struct dyString *dy = trackDbString(cart, tdb);
-
-        fprintf(f, "%s\n", dy->string);
+        outTrack(f, cart, tdb, priority++);
         }
     }
 }
 
 static int cmpPriority(const void *va, const void *vb)
 /* Compare to sort based on priority; use shortLabel as secondary sort key. */
 {
 const struct trackDb *a = *((struct trackDb **)va);
 const struct trackDb *b = *((struct trackDb **)vb);
 float dif = 0;
 
 dif = a->groupPriority - b->groupPriority;
 if (dif == 0)
     dif = a->priority - b->priority;
 if (dif < 0)