77022fe69d73bf7488dedd6a7a0c5a9dea3e854a hiram Tue Oct 27 14:16:26 2020 -0700 appears to be working OK even in dynamic update move refs #21980 diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c index b78a3e0..5240177 100644 --- src/hg/hgTracks/wigTrack.c +++ src/hg/hgTracks/wigTrack.c @@ -840,124 +840,124 @@ wgo->image = image; wgo->vLine = vLineViaHvg; wgo->xOff = xOff; wgo->yOff = yOff; return wgo; } /* prototype version of mouseOverData using this static array, * will alter this to be a private linked list */ static struct wigMouseOver *mouseOverData = NULL; static int mouseOverIdx = -1; struct wigMouseOver { - int x; /* x,y coordinates bottom left corner of box */ - int y; - int width; /* width,height of this box */ - int height; + int x1; /* beginning of a rectangle for this value */ + int x2; /* end of the rectangle */ double value; /* data value for this region */ }; void 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 */ { 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); +/* start new data for a new track, freez old data if exists */ +if (mouseOverData) + { + mouseOverIdx = -1; + freez(&mouseOverData); + } AllocArray(mouseOverData, width); int mouseOverX2 = -1; double previousValue = 0; boolean skipMouseOvers = FALSE; #define epsilonLimit 1.0e-6 // if (psOutput) // skipMouseOvers = 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 (!skipMouseOvers && (p->count > 0)) /* checking mouseOver construction */ { if (p->count < 3) /* allow 1 or 2 values to display */ { double thisValue = p->sumData/p->count; /* average if 2 */ if (mouseOverX2 < 0) /* first valid data found */ { ++mouseOverIdx; mouseOverX2 = x1+1; - mouseOverData[mouseOverIdx].x = xOff+x1; - mouseOverData[mouseOverIdx].width = mouseOverX2 - x1; - mouseOverData[mouseOverIdx].y = yOff; - mouseOverData[mouseOverIdx].height = h; + mouseOverData[mouseOverIdx].x1 = x1; + mouseOverData[mouseOverIdx].x2 = mouseOverX2; mouseOverData[mouseOverIdx].value = thisValue; previousValue = thisValue; } else /* see if we need a new item */ { if (fabs(thisValue - previousValue) > epsilonLimit) { /* finish off the existing run of data */ - mouseOverData[mouseOverIdx].width = mouseOverX2 - (mouseOverData[mouseOverIdx].x - xOff); + mouseOverData[mouseOverIdx].x2 = mouseOverX2; mouseOverX2 = x1+1; ++mouseOverIdx; - mouseOverData[mouseOverIdx].x = xOff+x1; - mouseOverData[mouseOverIdx].width = mouseOverX2 - x1; - mouseOverData[mouseOverIdx].y = yOff; - mouseOverData[mouseOverIdx].height = h; + mouseOverData[mouseOverIdx].x1 = x1; + mouseOverData[mouseOverIdx].x2 = mouseOverX2; mouseOverData[mouseOverIdx].value = thisValue; 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 */ { - mouseOverData[mouseOverIdx].width = mouseOverX2 - (mouseOverData[mouseOverIdx].x - xOff); + mouseOverData[mouseOverIdx].x2 = mouseOverX2; mouseOverX2 = -1; /* start over with new data when found */ } } /* potentially end the last mouseOver box */ - if (mouseOverX2 > 0 && (mouseOverX2 - (mouseOverData[mouseOverIdx].x - xOff)) > mouseOverData[mouseOverIdx].width) - mouseOverData[mouseOverIdx].width = mouseOverX2 - (mouseOverData[mouseOverIdx].x - xOff); + if (mouseOverX2 > 0 && mouseOverX2 > mouseOverData[mouseOverIdx].x2) + mouseOverData[mouseOverIdx].x2 = mouseOverX2; /* ===== done with mouseOver calculations===== */ 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 */ @@ -1149,31 +1149,34 @@ 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 (skipMouseOvers || mouseOverIdx < 0) + { + mouseOverIdx = -1; freez(&mouseOverData); + } } /* graphPreDraw() */ static void 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; graphPreDraw(preDraw, preDrawZero, width, tg, wgo->image, wgo->vLine, wgo->xOff, wgo->yOff, wgo->yOffsets, wgo->numTrack, @@ -1433,72 +1436,76 @@ wigTrackSetGraphOutputDefault(tg, xOff, yOff, width, hvg); 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, wigCart->yLineOnOff); #ifdef NOT_READY_TO_GO -if (mouseOverData) +if (NULL != mouseOverData) { static boolean beenHereDoneThat = FALSE; struct tempName jsonData; trashDirFile(&jsonData, "hgt", tg->track, ".json"); FILE *trashJson = mustOpen(jsonData.forCgi, "w"); struct jsonWrite *jw = jsonWriteNew(); jsonWriteObjectStart(jw, NULL); jsonWriteListStart(jw, tg->track); int i; /* could put up a 'no data' box when these items are not contiguous * e.g. when gaps interrupt the track data */ for (i = 0; i <= mouseOverIdx; ++i) { jsonWriteObjectStart(jw, NULL); - jsonWriteNumber(jw, "x1", (long long)mouseOverData[i].x); - jsonWriteNumber(jw, "y1", (long long)mouseOverData[i].y); - jsonWriteNumber(jw, "x2", (long long)(mouseOverData[i].x + mouseOverData[i].width)); - jsonWriteNumber(jw, "y2", (long long)(mouseOverData[i].y + mouseOverData[i].height)); + jsonWriteNumber(jw, "x1", (long long)mouseOverData[i].x1); + jsonWriteNumber(jw, "x2", (long long)mouseOverData[i].x2); jsonWriteDouble(jw, "v", mouseOverData[i].value); jsonWriteObjectEnd(jw); } jsonWriteListEnd(jw); jsonWriteObjectEnd(jw); fputs(jw->dy->string,trashJson); + mouseOverIdx = -1; + freez(&mouseOverData); // This is the hidden signal to the javaScript of where to pick up // the json file hPrintf("\n"); carefulClose(&trashJson); if (! beenHereDoneThat ) { hPrintf("
. . . mouseDbg
. . . mouse X,Y
. . . eventRects
. . . debug message