efe42f68b1889404cfa56bbc020c273ebdb5fc8d
hiram
  Wed Jun 12 12:05:02 2024 -0700
now supporting bigDbSnp bigMaf and bigChain refs #24430

diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c
index af5d541..9fe2422 100644
--- src/hg/hubApi/hubApi.c
+++ src/hg/hubApi/hubApi.c
@@ -121,34 +121,36 @@
 slAddHead(&supportedTypes, el);
 el = newSlName("interact");
 slAddHead(&supportedTypes, el);
 el = newSlName("netAlign");
 slAddHead(&supportedTypes, el);
 el = newSlName("peptideMapping");
 slAddHead(&supportedTypes, el);
 el = newSlName("pgSnp");
 slAddHead(&supportedTypes, el);
 el = newSlName("bigBarChart");
 slAddHead(&supportedTypes, el);
 el = newSlName("bigInteract");
 slAddHead(&supportedTypes, el);
 el = newSlName("clonePos");
 slAddHead(&supportedTypes, el);
+el = newSlName("bigDbSnp");
+slAddHead(&supportedTypes, el);
 el = newSlName("bigMaf");
-// slAddHead(&supportedTypes, el);
-// el = newSlName("bigChain");
-// slAddHead(&supportedTypes, el);
+slAddHead(&supportedTypes, el);
+el = newSlName("bigChain");
+slAddHead(&supportedTypes, el);
 slNameSort(&supportedTypes);
 }	/*	static void initSupportedTypes()	*/
 
 static int publicHubCmpCase(const void *va, const void *vb)
 /* Compare two shortLabels, ignore case. */
 {
 const struct hubPublic *a = *((struct hubPublic **)va);
 const struct hubPublic *b = *((struct hubPublic **)vb);
 return strcasecmp(a->shortLabel, b->shortLabel);
 }
 
 static void publicHubSortCase(struct hubPublic **pList)
 /* Sort slName list, ignore case. */
 {
 slSort(pList, publicHubCmpCase);
@@ -382,32 +384,33 @@
 static int bbiBriefMeasure(char *type, char *bigDataUrl, char *bigDataIndex, long *chromCount, long *itemCount, struct dyString *errors, char **chromName, unsigned *chromSize)
 /* check a bigDataUrl to find chrom count and item count, return
  *   name of largest chrom and its size
  */
 {
 int retVal = 0;
 *chromCount = 0;
 *itemCount = 0;
 struct errCatch *errCatch = errCatchNew();
 if (errCatchStart(errCatch))
     {
     if (startsWithWord("bigNarrowPeak", type)
             || startsWithWord("bigBed", type)
             || startsWithWord("bigGenePred", type)
             || startsWithWord("bigPsl", type)
-            || startsWithWord("bigChain", type)
+            || startsWithWord("bigDbSnp", type)
             || startsWithWord("bigMaf", type)
+            || startsWithWord("bigChain", type)
             || startsWithWord("bigRmsk", type)
             || startsWithWord("bigBarChart", type)
             || startsWithWord("bigInteract", type))
         {
         struct bbiFile *bbi = NULL;
         bbi = bigBedFileOpen(bigDataUrl);
         struct bbiChromInfo *chromList = bbiChromList(bbi);
         *chromCount = slCount(chromList);
         *itemCount = bigBedItemCount(bbi);
         bbiLargestChrom(chromList, chromName, chromSize);
         bbiChromInfoFreeList(&chromList);
         bbiFileClose(&bbi);
         }
     else if (startsWithWord("bigWig", type))
         {
@@ -527,41 +530,54 @@
 	    hubSubTracks(hub, db, tdbEl, countTracks, chromCount, itemCount, chromName, chromSize, genome, errorString);
 	}
     }
 hPrintf("    </ul></li>\n");
 }	/* hubSubTracks() */
 
 static void showSubTracks(struct trackHub *hub, char *db, struct trackDb *tdb, struct hash *countTracks,
     char *chromName, unsigned chromSize, char *errorString)
 /* tdb has subtracks, show only subTracks, no details */
 {
 hPrintf("    <li><ul>\n");
 if (debug)
     hPrintf("    <li>subtracks for '%s' db: '%s'</li>\n", tdb->track, db);
 if (tdb->subtracks)
     {
+    struct dyString *extraDyFlags = dyStringNew(128);
+    if (debug)
+	dyStringAppend(extraDyFlags, ";debug=1");
+    if (jsonOutputArrays)
+	dyStringAppend(extraDyFlags, ";jsonOutputArrays=1");
+    char *extraFlags = dyStringCannibalize(&extraDyFlags);
     struct trackDb *tdbEl = NULL;
     for (tdbEl = tdb->subtracks; tdbEl; tdbEl = tdbEl->next)
 	{
         if (tdbIsCompositeView(tdbEl))
 	    hPrintf("<li><b>%s</b>: %s : composite view of parent: %s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track);
 	else
 	    {
 	    if (isSupportedType(tdbEl->type))
 		sampleUrl(hub, db, tdbEl, errorString);
 	    else
-		hPrintf("<li><b>%s</b>: %s : subtrack of parent: %s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track);
+                if (hub && hub->url)
+		    hPrintf("<li><b>%s</b>: %s : subtrack of parent: %s, genome %s, url %s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track, db, hub->url);
+                else
+		    {
+		    char urlReference[2048];
+		    safef(urlReference, sizeof(urlReference), " <a href='%s/getData/track?genome=%s;track=%s;maxItemsOutput=5%s' target=_blank>(sample data)</a>\n", urlPrefix, db, tdbEl->track, extraFlags);
+		    hPrintf("<li><b>%s</b>: %s : subtrack of parent: %s%s</li>\n", tdbEl->track, tdbEl->type, tdbEl->parent->track, urlReference);
+		    }
 	    }
 	hashCountTrack(tdbEl, countTracks);
         if (tdbEl->subtracks)
 	    showSubTracks(hub, db, tdbEl, countTracks, chromName, chromSize, errorString);
 	}
     }
 hPrintf("    </ul></li>\n");
 }
 
 static void trackSettings(char *db, struct trackDb *tdb, struct hash *countTracks)
 /* process the settingsHash for a trackDb, recursive when subtracks */
 {
 hPrintf("    <li><ul>\n");
 boolean protectedData = protectedTrack(db, tdb, tdb->track);
 struct hashEl *hel;