447c433324a13653e1760bc7e4d1a854e517a1e6
braney
  Mon Dec 13 09:57:45 2021 -0800
fix mouseovers for logo wiggles

diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c
index 48e28ec..87deb7a 100644
--- src/hg/hgTracks/wigTrack.c
+++ src/hg/hgTracks/wigTrack.c
@@ -833,74 +833,53 @@
 return wgo;
 }
 
 struct wigGraphOutput *wigGraphOutputSolid(int xOff, int yOff, struct hvGfx *image)
 /* Get appropriate wigGraphOutput for non-transparent rendering */
 {
 struct wigGraphOutput *wgo;
 AllocVar(wgo);
 wgo->image = image;
 wgo->vLine = vLineViaHvg;
 wgo->xOff = xOff;
 wgo->yOff = yOff;
 return wgo;
 }
 
-struct wigMouseOver *graphPreDraw(struct preDrawElement *preDraw, int preDrawZero, int width,
-    struct track *tg, void *image, WigVerticalLineVirtual vLine, int xOff, int yOff, double *yOffsets, int numTrack,
-    double graphUpperLimit, double graphLowerLimit, double graphRange,
-    double epsilon, Color *colorArray, enum trackVisibility vis,
-    struct wigCartOptions *wigCart, struct pixelCountBin *pixelBins)
-/*	graph the preDraw array, returns mouse over data, or NULL */
+struct wigMouseOver *getMouseOverData(struct track *tg, struct preDrawElement *preDraw, int width, int xOff, int preDrawZero)
+/* Calculate the mouseOver data. */
 {
 int x1;
-int h = tg->lineHeight;	/*	the height of our drawing window */
-double scaleFactor = h/graphRange;
-Color oldDrawColor = colorArray[0] + 1;	/* Just to be different from 1st drawColor. */
-Color mediumColor = MG_BLACK;	// Will be overriden
-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 */
+boolean dropMouseOverData = FALSE;	// will become TRUE if noAverage
 int mouseOverX2 = -1;
+struct wigMouseOver *mouseOverData = NULL;
 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");
+boolean noAverage = FALSE;
 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.
- */
+if (enableMouseOver)
+    skipMouseOvers = FALSE;
+					// condition is encountered
+/* ===== mouseOver calculations===== */
 for (x1 = 0; x1 < width; ++x1)
     {
-    int x = x1 + xOff;
+    //int x = x1 + xOff;
     int preDrawIndex = x1 + preDrawZero;
     struct preDrawElement *p = &preDraw[preDrawIndex];
-    /* ===== mouseOver calculations===== */
     if (enableMouseOver && !dropMouseOverData)
         {
         /* 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;
@@ -939,32 +918,68 @@
             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;
+    }
+if (dropMouseOverData)
+    slFreeList(&mouseOverData);
 
-    /* ===== done with mouseOver calculations===== */
+return mouseOverData;
+}
+
+struct wigMouseOver *graphPreDraw(struct preDrawElement *preDraw, int preDrawZero, int width,
+    struct track *tg, void *image, WigVerticalLineVirtual vLine, int xOff, int yOff, double *yOffsets, int numTrack,
+    double graphUpperLimit, double graphLowerLimit, double graphRange,
+    double epsilon, Color *colorArray, enum trackVisibility vis,
+    struct wigCartOptions *wigCart, struct pixelCountBin *pixelBins)
+/*	graph the preDraw array, returns mouse over data, or NULL */
+{
+int x1;
+int h = tg->lineHeight;	/*	the height of our drawing window */
+double scaleFactor = h/graphRange;
+Color oldDrawColor = colorArray[0] + 1;	/* Just to be different from 1st drawColor. */
+Color mediumColor = MG_BLACK;	// Will be overriden
+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);
+	/* list of mouse over data, if created here */
+
+struct wigMouseOver *mouseOverData = getMouseOverData(tg, preDraw, width, xOff, preDrawZero);
+
+/*	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];
 
     assert(x1/pixelBins->binSize < pixelBins->binCount);
     unsigned long *bitCount = &pixelBins->bins[x1/pixelBins->binSize];
 
     Color drawColor = colorArray[x1];
     if (drawColor != oldDrawColor)
         {
 	mediumColor = somewhatLighterColor32(drawColor);
 	lightColor = somewhatLighterColor32(mediumColor);
 	oldDrawColor = drawColor;
         }
 
     /*	count is non-zero meaning valid data exists here	*/
     if (p->count)
 	{
@@ -1153,218 +1168,67 @@
 	    {
 	    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()	*/
 
-#ifdef NOTNOW
-static void drawLogoChar( struct hvGfx *hvg, int xOff, int yOff, struct dnaMotif *motif, int width, int height, int count, boolean flip)
-{
-int orangeColor = hvGfxFindColorIx(hvg, 230, 130, 0);
-int blueColor = hvGfxFindColorIx(hvg, 0,114,198);
-int greenColor = hvGfxFindColorIx(hvg, 28,206,40);
-
-int ii;
-FILE *f;
-struct tempName pngTn;
-unsigned char *buf;
-
-buf = needMem(width + 1);
-makeTempName(&pngTn, "logo", ".pgm");
-dnaMotifToLogoPGM(motif, width / count, width  , (double)height - 2, NULL, "../trash", pngTn.forCgi);
-
-f = mustOpen(pngTn.forCgi, "r");
-
-/* get rid of header */
-for(ii=0; ii < 4; ii++)
-    while(fgetc(f) != '\n')
-	;
-
-/* map colors from PGM to browser colors */
-Color *colors = needMem(sizeof(Color) * (1+width));
-for(ii=0; ii < height; ii++)
-    {
-    int jj;
-    mustRead(f, buf, width);
-
-    for(jj=0; jj < width + 2; jj++)
-	{
-	if (buf[jj] == 255) colors[jj] = MG_WHITE;
-	else if (buf[jj] == 0x87) colors[jj] = MG_RED;
-	else if (buf[jj] == 0x60) colors[jj] = greenColor;
-	else if (buf[jj] == 0x7f) colors[jj] = blueColor;
-	else if (buf[jj] == 0x62) colors[jj] = orangeColor;
-	}
-
-    if (flip)
-        {
-        int pos = yOff + height - ii;
-        hvGfxVerticalSmear(hvg,xOff,pos,width ,1, colors,TRUE);
-            //        hvGfxBox(hvg, xOff, pos, width, 1, MG_BLACK);
-        }
-    else
-        hvGfxVerticalSmear(hvg,xOff,yOff+ii,width ,1, colors,TRUE);
-    }
-hvGfxUnclip(hvg);
-
-fclose(f);
-remove(pngTn.forCgi);
-}
-#endif
-
-struct dnaMotif *getMotif(int numBases)
-{
-struct dnaMotif *motif;
-AllocVar(motif);
-motif->name = NULL;
-motif->columnCount = numBases;
-motif->aProb = needMem(sizeof(float) * motif->columnCount);
-motif->cProb = needMem(sizeof(float) * motif->columnCount);
-motif->gProb = needMem(sizeof(float) * motif->columnCount);
-motif->tProb = needMem(sizeof(float) * motif->columnCount);
-
-return motif;
-}
-
 static struct wigMouseOver *logoPreDrawContainer(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, int seqStart, int seqEnd)
 {
 struct preDrawElement *preDraw = preDrawContainer->preDraw;
 struct wigGraphOutput *wgo = tg->wigGraphOutput;
-struct wigMouseOver *mouseOverData = NULL;
+//struct wigMouseOver *mouseOverData = NULL;
 unsigned numBases = seqEnd - seqStart;
 struct dnaSeq *seq = hChromSeq(database, chromName, seqStart, seqEnd);
 struct pixelCountBin *pixelBins = wgo->pixelBins;
 double *yOffsets = wgo->yOffsets;
 int numTrack = wgo->numTrack;
 Color clipColor = MG_MAGENTA;
 WigVerticalLineVirtual vLine = wgo->vLine;
 void *image = wgo->image;
 #define doLine(image, x, y, height, color) {vLine(image, x, y, height, color); }
 
 int h = tg->lineHeight;	/*	the height of our drawing window */
 double scaleFactor = h/graphRange;
-
-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;
-
-struct dnaMotif *motifPos = getMotif(numBases);
-struct dnaMotif *motifNeg = getMotif(numBases);
+struct wigMouseOver *mouseOverData = getMouseOverData(tg, preDraw, width, xOff, preDrawZero);
 
 double xIncr = (double)width / numBases;
 unsigned baseNum;
 int lastX = xOff;
 for(baseNum = 0; baseNum < numBases; baseNum++)
     {
     int x1 = baseNum * xIncr;
     int x = x1 + xOff;
     int width = x - lastX;
     int base = seq->dna[baseNum];
     lastX = x;
     int preDrawIndex = x1 + preDrawZero;
     struct preDrawElement *p = &preDraw[preDrawIndex];
-    /* ===== mouseOver calculations===== */
-    if (enableMouseOver && !dropMouseOverData)
-        {
-        /* 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;
-                    }
-                else	/* see if we need a new item */
-                    {
-#define epsilonLimit 1.0e-6
-                    if (fabs(thisValue - previousValue) > epsilonLimit)
-                        {
-                        /* finish off the existing run of data (list head)*/
-                        mouseOverData->x2 = mouseOverX2;
-                        mouseOverX2 = x1+1;
-			struct wigMouseOver *dataItem;
-			AllocVar(dataItem);
-                        dataItem->x1 = x1;
-                        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 (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===== */
 
     assert(x1/pixelBins->binSize < pixelBins->binCount);
     unsigned long *bitCount = &pixelBins->bins[x1/pixelBins->binSize];
 
     /*	count is non-zero meaning valid data exists here	*/
     if (p->count)
 	{
 	/*	data value has been picked by previous scanning.
 	 *	Could be smoothed, maybe not.
 	 */
 	double dataValue = p->smooth;
 
         /* save a number that represents how many pixels that would be set if we were drawing bars.
          * This may used for sorting later on */
         int iy0 = graphUpperLimit * scaleFactor;
@@ -1401,106 +1265,80 @@
                     if (numTrack > 0)
                         {
                         y0 = (graphUpperLimit  - yOffsets[(numTrack-1) *  width + x1]) *scaleFactor;
                         y1 = (graphUpperLimit - dataValue - yOffsets[(numTrack-1) *  width + x1])*scaleFactor;
                         }
                     }
 
                 int boxHeight = max(1,abs(y1 - y0));
                 int boxTop = min(y1,y0);
 
                 //	positive data value exactly equal to Bottom pixel
                 //  make sure it draws at least a pixel there
                 if (boxTop == h)
                     boxTop = h - 1;
 
-                // negative data value exactly equal to top pixel
-                // make sure it draws something
-                double prob = (double)(dataValue) / (graphUpperLimit - graphLowerLimit);
-                    
                 char string[2];
                 string[0] = toupper(base);
                 string[1] = 0;
                 MgFont *font = tl.font;
                 int height = dataValue * scaleFactor;
                 unsigned color = MG_BLACK;
                 if (base == 'a')
                     color = MG_RED;
                 else if (base == 't')
                     color = MG_GREEN;
                 else if (base == 'c')
                     color = MG_BROWN;
                 else if (base == 'g')
                     color = MG_BLUE;
                 if (abs(dataValue) > 0.1)
                     {
                     if (dataValue < 0)
                         {
-                        //hvGfxBox(image, x, yOff+graphUpperLimit * scaleFactor, width, -height, MG_RED);
                         hvGfxTextInBox(hvg, x, yOff+graphUpperLimit * scaleFactor, width - 1, dataValue * scaleFactor,
                             color, font, string);
                         }
                     else
                         {
-                       // hvGfxBox(image, x, yOff-height+graphUpperLimit * scaleFactor, width, height, MG_RED);
-
                         hvGfxTextInBox(hvg, x, yOff-height+graphUpperLimit * scaleFactor, width - 1, dataValue * scaleFactor,
                             color, font, string);
                         }
                     }
                 if (((boxTop+boxHeight) == 0) && !isnan(dataValue))
                     boxHeight += 1;
-                struct dnaMotif *motif;
-                if (dataValue < 0)
-                    {
-                    motif = motifNeg;
-                    prob = -prob;
-                    }
-                else
-                    motif = motifPos;
-                if (base == 'a')
-                    motif->aProb[baseNum] = prob;
-                if (base == 't')
-                    motif->tProb[baseNum] = prob;
-                if (base == 'c')
-                    motif->cProb[baseNum] = prob;
-                if (base == 'g')
-                    motif->gProb[baseNum] = prob;
                 }
 	    double stackValue = dataValue;
 
 	    if ((yOffsets != NULL) && (numTrack > 0))
 		stackValue += yOffsets[(numTrack-1) *  width + x1];
 	    if (stackValue > graphUpperLimit)
                 {
 		doLine(image, x, yOff, 2, clipColor);
                 }
 	    else if (stackValue < graphLowerLimit)
                 {
 		doLine(image, x, yOff + h - 1, 2, clipColor);
                 }
 #undef scaleHeightToPixels	/* No longer use this symbol */
             }   /*	vis == tvFull || vis == tvPack */
         }
     }	/*	for (x1 = 0; x1 < width; ++x1)	*/
 
-if (dropMouseOverData)
-    slFreeList(&mouseOverData);
 return(mouseOverData);
 }
 
-
 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);
 
@@ -1745,31 +1583,32 @@
     }
 
 /* if we're autoscaling and the range is 0 this implies that all values
  * in the given range are the same.  We create a bottom of the scale
  * by subtracting one from the only value.
  * This results in drawing a box that fills the range. */
 if (graphUpperLimit == graphLowerLimit)
     {
     graphLowerLimit = graphUpperLimit - 1;
     }
 graphRange = graphUpperLimit - graphLowerLimit;
 
 wigTrackSetGraphOutputDefault(tg, xOff, yOff, width, hvg);
 
 struct wigMouseOver *mouseOverData = NULL;
-if (zoomedToCodonLevel && trackDbSettingOn(tg->tdb, "logo"))
+//if (zoomedToCodonLevel && trackDbSettingOn(tg->tdb, "logo"))
+if (zoomedToBaseLevel && trackDbSettingOn(tg->tdb, "logo"))
     mouseOverData = logoPreDrawContainer(preContainer,
         preDrawZero, width, tg, hvg, xOff, yOff,
         graphUpperLimit, graphLowerLimit, graphRange, vis, wigCart, seqStart, seqEnd);
 else
     mouseOverData = graphPreDrawContainer(preContainer,
         preDrawZero, width, tg, hvg, xOff, yOff,
         graphUpperLimit, graphLowerLimit, graphRange, vis, wigCart);
 
 drawZeroLine(vis, wigCart->horizontalGrid,
     graphUpperLimit, graphLowerLimit,
     hvg, xOff, yOff, width, tg->lineHeight);
 
 drawArbitraryYLine(vis, (enum wiggleGridOptEnum)wigCart->yLineOnOff,
     graphUpperLimit, graphLowerLimit,
     hvg, xOff, yOff, width, tg->lineHeight, wigCart->yLineMark, graphRange,