5be304c4bdd41bd4452a4b9f1b8fcf37930079e4
braney
  Fri Feb 3 11:09:59 2017 -0800
allow arbitrary fields with a bigBed file to be used for labels.  #18782

diff --git src/hg/hgTracks/bigBedTrack.c src/hg/hgTracks/bigBedTrack.c
index 2a5f1e8..9653b4c 100644
--- src/hg/hgTracks/bigBedTrack.c
+++ src/hg/hgTracks/bigBedTrack.c
@@ -110,30 +110,49 @@
 /* return a given field from the bb->rest field, NULL on error */
 {
 if (fieldIdx==0) // we don't return the first(=name) field of bigBed
     return NULL;
 char *rest = cloneString(bb->rest);
 char *restFields[1024];
 int restCount = chopTabs(rest, restFields);
 char *field = NULL;
 if (fieldIdx < restCount)
     field = cloneString(restFields[fieldIdx]);
 freeMem(rest);
 return field;
 }
 
 
+char *makeLabel(struct track *track,  struct bigBedInterval *bb)
+// Build a label for a bigBedTrack from the requested label fields.
+{
+char *restFields[256];
+chopTabs(cloneString(bb->rest), restFields);
+struct dyString *dy = newDyString(128);
+boolean firstTime = TRUE;
+struct slInt *labelInt = track->labelColumns;
+for(; labelInt; labelInt = labelInt->next)
+    {
+    if (!firstTime)
+        dyStringPrintf(dy, "/");
+
+    dyStringPrintf(dy, "%s", restFields[labelInt->val - 3]);
+    firstTime = FALSE;
+    }
+return dyStringCannibalize(&dy);
+}
+
 void bigBedAddLinkedFeaturesFromExt(struct track *track,
 	char *chrom, int start, int end, int scoreMin, int scoreMax, boolean useItemRgb,
 	int fieldCount, struct linkedFeatures **pLfList, int maxItems)
 /* Read in items in chrom:start-end from bigBed file named in track->bbiFileName, convert
  * them to linkedFeatures, and add to head of list. */
 {
 struct lm *lm = lmInit(0);
 struct trackDb *tdb = track->tdb;
 struct bigBedInterval *bb, *bbList = bigBedSelectRangeExt(track, chrom, start, end, lm, maxItems);
 char *scoreFilter = cartOrTdbString(cart, track->tdb, "scoreFilter", NULL);
 char *mouseOverField = cartOrTdbString(cart, track->tdb, "mouseOverField", NULL);
 int minScore = 0;
 if (scoreFilter)
     minScore = atoi(scoreFilter);
 
@@ -166,44 +185,47 @@
 	    reverseComplement(seq, strlen(seq));
 	lf->extra = seq;
 	lf->cds = cds;
 	}
     else
 	{
         char startBuf[16], endBuf[16];
         char *bedRow[32];
 
         bigBedIntervalToRow(bb, chromName, startBuf, endBuf, bedRow, ArraySize(bedRow));
 	struct bed *bed = bedLoadN(bedRow, fieldCount);
 	lf = bedMungToLinkedFeatures(&bed, tdb, fieldCount,
 	    scoreMin, scoreMax, useItemRgb);
 	}
 
+    lf->label = makeLabel(track,  bb);
     if (sameString(track->tdb->type, "bigGenePred") || startsWith("genePred", track->tdb->type))
         {
         struct genePred  *gp = lf->original = genePredFromBigGenePred(chromName, bb); 
         lf->extra = gp->name2;
         lf->isBigGenePred = TRUE;
         }
 
     char* mouseOver = restField(bb, mouseOverIdx);
     lf->mouseOver   = mouseOver; // leaks some memory, cloneString handles NULL ifself 
 
     if (scoreFilter == NULL || lf->score >= minScore)
 	slAddHead(pLfList, lf);
     }
 lmCleanup(&lm);
+
+track->itemName = bigLfItemName;
 }
 
 
 boolean canDrawBigBedDense(struct track *tg)
 /* Return TRUE if conditions are such that can do the fast bigBed dense data fetch and
  * draw. */
 {
 return tg->isBigBed;
 }
 
 
 void bigBedDrawDense(struct track *tg, int seqStart, int seqEnd,
         struct hvGfx *hvg, int xOff, int yOff, int width,
         MgFont *font, Color color)
 /* Use big-bed summary data to quickly draw bigBed. */
@@ -235,21 +257,37 @@
     else
 	{
 	int x;
 	for (x=0; x<width; ++x)
 	    {
 	    if (summary[x].validCount > 0)
 		{
 		hvGfxBox(hvg, x+xOff, yOff, 1, tg->heightPer, color);
 		}
 	    }
 	}
     }
 freez(&tg->summary);
 }
 
+char *bigBedItemName(struct track *tg, void *item)
+// return label for simple beds
+{
+struct bed *bed = (struct bed *)item;
+
+return bed->label;
+}
+
+char *bigLfItemName(struct track *tg, void *item)
+// return label for linked features
+{
+struct linkedFeatures *lf = (struct linkedFeatures *)item;
+
+return lf->label;
+}
+
 void bigBedMethods(struct track *track, struct trackDb *tdb, 
                                 int wordCount, char *words[])
 /* Set up bigBed methods. */
 {
 complexBedMethods(track, tdb, TRUE, wordCount, words);
 }