5e55b76e29e2ac663dcfa4e288bd0caa701ab3da
hiram
  Mon May 3 13:36:12 2021 -0700
adding mouseOverFunction trackDb variable and feature to turn off mouse over value display for averaged values refs #27457

diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c
index a49dea9..c2f4211 100644
--- src/hg/hgTracks/wigTrack.c
+++ src/hg/hgTracks/wigTrack.c
@@ -859,43 +859,51 @@
 Color lightColor = MG_BLACK;	// Will be overriden
 Color clipColor = MG_MAGENTA;
 enum wiggleTransformFuncEnum transformFunc = wigCart->transformFunc;
 enum wiggleGraphOptEnum lineBar = wigCart->lineBar;
 boolean whiskers = (wigCart->windowingFunction == wiggleWindowingWhiskers
 			&& width < winEnd-winStart);
 struct wigMouseOver *mouseOverData = NULL;
 	/* list of mouse over data, if created here */
 
 boolean skipMouseOvers = TRUE;	/* assuming not using */
 int mouseOverX2 = -1;
 double previousValue = 0;
 if (enableMouseOver)
     skipMouseOvers = FALSE;
 
+boolean noAverage = FALSE;
+boolean dropMouseOverData = FALSE;	// will become TRUE if noAverage
+					// condition is encountered
+char *mouseOverFunction = trackDbSetting(tg->tdb, "mouseOverFunction");
+if (sameOk(mouseOverFunction, "noAverage"))
+    noAverage = TRUE;
+
 /*	right now this is a simple pixel by pixel loop.  Future
  *	enhancements could draw boxes where pixels
  *	are all the same height in a run.
  */
 for (x1 = 0; x1 < width; ++x1)
     {
     int x = x1 + xOff;
     int preDrawIndex = x1 + preDrawZero;
     struct preDrawElement *p = &preDraw[preDrawIndex];
     /* ===== mouseOver calculations===== */
-    if (enableMouseOver)
+    if (enableMouseOver && !dropMouseOverData)
         {
-        if (!skipMouseOvers && (p->count > 0)) /* checking mouseOver construction */
+        /* checking if mouseOver construction is allowed */
+        if (!skipMouseOvers && (p->count > 0) && !(noAverage && p->count>1))
             {
             if (p->count > 0)	/* allow any number of values to display */
                 {
                 double thisValue = p->sumData/p->count;	/*average if count > 1*/
                 if (mouseOverX2 < 0)    /* first valid data found */
                     {
 		    struct wigMouseOver *dataItem;
 		    AllocVar(dataItem);
                     mouseOverX2 = x1+1;
                     dataItem->x1 = x1;
                     dataItem->x2 = mouseOverX2;
                     dataItem->value = thisValue;
 		    dataItem->valueCount = p->count;
 		    slAddHead(&mouseOverData, dataItem);
                     previousValue = thisValue;
@@ -914,31 +922,34 @@
                         dataItem->x2 = mouseOverX2;
                         dataItem->value = thisValue;
 			dataItem->valueCount = p->count;
 			slAddHead(&mouseOverData, dataItem);
                         previousValue = thisValue;
                         }
                     else	/* continue run of same data value */
                         mouseOverX2 = x1+1;
                     }
                 }
             else
                 skipMouseOvers = TRUE;	/* has become too dense to make sense */
             }
         else /* perhaps entered region without values after some data already */
             {
-            if (mouseOverX2 > 0)	/* yes, been in data, end it here */
+
+            if (noAverage && p->count>1)
+              dropMouseOverData = TRUE;
+            else if (mouseOverX2 > 0)	/* yes, been in data, end it here */
                 {
 		mouseOverData->x2 = mouseOverX2;
                 mouseOverX2 = -1;	/* start over with new data when found*/
                 }
             }
         /* potentially end the last mouseOver box */
         if (mouseOverX2 > 0 && mouseOverX2 > mouseOverData->x2)
                 mouseOverData->x2 = mouseOverX2;
 
         }       //      if (enableMouseOver)
     else
 	skipMouseOvers = TRUE;
 
     /* ===== done with mouseOver calculations===== */
 
@@ -1140,53 +1151,55 @@
         else if (vis == tvDense || vis == tvSquish)
 	    {
 	    double grayValue;
 	    int grayIndex;
 	    /* honor the viewLimits, data below is white, data above is black */
 	    grayValue = max(dataValue,graphLowerLimit);
 	    grayValue = min(grayValue,graphUpperLimit);
 	    grayIndex = ((grayValue-graphLowerLimit)/graphRange)*MAX_WIG_VALUE;
 
 	    drawColor =
 		tg->colorShades[grayInRange(grayIndex, 0, MAX_WIG_VALUE)];
 	    doLine(image, x, yOff, tg->lineHeight, drawColor);
             }   /*	vis == tvDense || vis == tvSquish	*/
 	}	/*	if (preDraw[].count)	*/
     }	/*	for (x1 = 0; x1 < width; ++x1)	*/
+
+if (dropMouseOverData)
+    slFreeList(&mouseOverData);
 return(mouseOverData);
 }	/*	graphPreDraw()	*/
 
 static struct wigMouseOver *graphPreDrawContainer(struct preDrawContainer *preDrawContainer,
     int preDrawZero, int width, struct track *tg, struct hvGfx *hvg,
     int xOff, int yOff, double graphUpperLimit, double graphLowerLimit,
     double graphRange, enum trackVisibility vis, struct wigCartOptions *wigCart)
 /* Draw the graphs for all tracks in container. */
 {
 double epsilon = graphRange / tg->lineHeight;
 struct preDrawElement *preDraw = preDrawContainer->preDraw;
 Color *colorArray = makeColorArray(preDraw, width, preDrawZero, wigCart, tg, hvg);
 struct wigGraphOutput *wgo = tg->wigGraphOutput;
 struct wigMouseOver *mouseOverData = graphPreDraw(preDraw, preDrawZero, width,
 	tg, wgo->image, wgo->vLine, wgo->xOff, wgo->yOff, wgo->yOffsets,
 	wgo->numTrack, graphUpperLimit, graphLowerLimit, graphRange,
 	epsilon, colorArray, vis, wigCart, wgo->pixelBins);
 
 freez(&colorArray);
 return mouseOverData;
 }
 
-
 void drawZeroLine(enum trackVisibility vis,
     enum wiggleGridOptEnum horizontalGrid,
     double graphUpperLimit, double graphLowerLimit,
     struct hvGfx *hvg, int xOff, int yOff, int width, int lineHeight)
 /*	draw a line at y=0 on the graph	*/
 {
 /*	Do we need to draw a zero line ?
  *	This is to be generalized in the future to allow horizontal grid
  *	lines, perhaps user specified to indicate thresholds.
  */
 if ((vis == tvFull) && (horizontalGrid == wiggleHorizontalGridOn))
     {
     Color black = hvGfxFindColorIx(hvg, 0, 0, 0);
     int x1, x2, y1, y2;
 
@@ -1447,39 +1460,40 @@
         {
         jsonWriteObjectStart(mouseOverJson, NULL);
         jsonWriteNumber(mouseOverJson, "x1", (long long)dataItem->x1);
         jsonWriteNumber(mouseOverJson, "x2", (long long)dataItem->x2);
         jsonWriteDouble(mouseOverJson, "v", dataItem->value);
         jsonWriteNumber(mouseOverJson, "c", dataItem->valueCount);
         jsonWriteObjectEnd(mouseOverJson);
         }
     jsonWriteListEnd(mouseOverJson);
     jsonWriteObjectEnd(mouseOverJson);
     slFreeList(&mouseOverData);
     // hidden element to pass along jsonUrl file name and also the trigger
     // that this track has data to display.
     hPrintf("<div id='mouseOver_%s' name='%s' class='hiddenText mouseOverData' jsonUrl='%s'></div>\n", tg->track, tg->track, mouseOverJsonFile->forCgi);
     }
-// Might need something like this later for other purposes
-// else if (enableMouseOver)       // system enabled, but no data for this track
-//     {
-    /* signal to indicate zoom in required to see data */
-//     hPrintf("<div id='mouseOver_%s' name='%s' class='hiddenText mouseOverData'></div>\n", tg->track, tg->track);
-//     }
+else if (enableMouseOver)
+    {
+    jsonWriteObjectStart(mouseOverJson, tg->track);
+    jsonWriteString(mouseOverJson, "t", tg->tdb->type);
+    jsonWriteString(mouseOverJson, "mo", "noAverage");
+    jsonWriteObjectEnd(mouseOverJson);
+    }
 
 wigMapSelf(tg, hvg, seqStart, seqEnd, xOff, yOff, width);
-}
+}	/*	void wigDrawPredraw()	*/
 
 struct preDrawContainer *wigLoadPreDraw(struct track *tg, int seqStart, int seqEnd, int width)
 /* Do bits that load the predraw buffer tg->preDrawContainer. */
 {
 /* Just need to do this once... */
 if (tg->preDrawContainer)
     return tg->preDrawContainer;
 
 struct wigItem *wi;
 double pixelsPerBase = scaleForPixels(width);
 double basesPerPixel = 1.0;
 int itemCount = 0;
 char *currentFile = NULL;
 //char *currentFileRewrite = NULL;
 struct udcFile *wibFH = NULL;	/*	file handle to binary file */