7f07969209248e6ad775df9417b9b185147c1cd2 hiram Thu Oct 29 14:36:56 2020 -0700 allow mouseOver to turn on and off via hg.conf variable refs #21980 diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c index df66159..9466183 100644 --- src/hg/hgTracks/wigTrack.c +++ src/hg/hgTracks/wigTrack.c @@ -13,30 +13,32 @@ #include "hdb.h" #include "hgTracks.h" #include "wiggle.h" #include "hmmstats.h" #include "scoredRef.h" #ifndef GBROWSE #include "customTrack.h" #endif /* GBROWSE */ #include "wigCommon.h" #include "imageV2.h" #include "memgfx.h" #include "udc.h" #include "trashDir.h" #include "jsonWrite.h" +extern boolean enableMouseOver; + struct wigItem /* A wig track item. */ { struct wigItem *next; int start, end; /* Start/end in chrom (aka browser) coordinates. */ char *db; /* Database */ int ix; /* Position in list. */ int height; /* Pixel height of item. */ unsigned span; /* each value spans this many bases */ unsigned count; /* number of values to use */ unsigned offset; /* offset in File to fetch data */ char *file; /* path name to data file, one byte per value */ double lowerLimit; /* lowest data value in this block */ double dataRange; /* lowerLimit + dataRange = upperLimit */ unsigned validCount; /* number of valid data values in this block */ @@ -865,54 +867,60 @@ /* 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 (enableMouseOver) + { +verbose(0, "# DBG enableMouseOver '%s'\n", tg->track); if (mouseOverData) { mouseOverIdx = -1; freez(&mouseOverData); } AllocArray(mouseOverData, width); + } +else +verbose(0, "# DBG OFF enableMouseOver '%s'\n", tg->track); 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 (enableMouseOver) + { 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].x1 = x1; mouseOverData[mouseOverIdx].x2 = mouseOverX2; mouseOverData[mouseOverIdx].value = thisValue; previousValue = thisValue; } else /* see if we need a new item */ @@ -935,30 +943,33 @@ 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].x2 = mouseOverX2; mouseOverX2 = -1; /* start over with new data when found */ } } /* potentially end the last mouseOver box */ if (mouseOverX2 > 0 && mouseOverX2 > mouseOverData[mouseOverIdx].x2) mouseOverData[mouseOverIdx].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]; 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) @@ -1148,36 +1159,38 @@ { 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 (enableMouseOver) + { 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, graphUpperLimit, graphLowerLimit, graphRange, @@ -1435,33 +1448,33 @@ 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 (NULL != mouseOverData) +if (enableMouseOver && mouseOverData) { +verbose(0, "# DBG writing json for track '%s'\n", tg->track); 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].x1); @@ -1473,31 +1486,30 @@ jsonWriteObjectEnd(jw); fputs(jw->dy->string,trashJson); carefulClose(&trashJson); mouseOverIdx = -1; freez(&mouseOverData); if (! beenHereDoneThat ) { hPrintf("<div id='mouseOverContainer' class='wigMouseOver'>\n"); hPrintf(" <span id='mouseOverText' class=wigMouseOverValue'>\n"); hPrintf(" </span>\n"); hPrintf("</div>\n"); beenHereDoneThat = TRUE; } } else -#endif wigMapSelf(tg, hvg, seqStart, seqEnd, xOff, yOff, width); } 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;