9944d8c4a72a426a07ed2d33a5ea535811dd4461 galt Sun Feb 7 23:26:52 2016 -0800 Issue 16666. Makes autoscale work with multi-region for wig, bedGraph, bigWig, and multiWig. doWiggle still TODO. diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c index 474f062..e7fb98f 100644 --- src/hg/hgTracks/wigTrack.c +++ src/hg/hgTracks/wigTrack.c @@ -1197,101 +1197,109 @@ /* There may not be a span of 1, use whatever is lowest */ if (minimalSpan > usingDataSpan) usingDataSpan = minimalSpan; return usingDataSpan; } void wigTrackSetGraphOutputDefault(struct track *tg, int xOff, int yOff, struct hvGfx *hvg) /* Set up to draw on hvg if no other destination set already */ { if (tg->wigGraphOutput == NULL) tg->wigGraphOutput = wigGraphOutputSolid(xOff, yOff, hvg); } -void wigDrawPredraw(struct track *tg, int seqStart, int seqEnd, +void wigPreDrawPredraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis, struct preDrawContainer *preContainer, int preDrawZero, int preDrawSize, double *retGraphUpperLimit, double *retGraphLowerLimit) -/* Draw once we've figured out predraw (numerical values to graph) we draw it here. +/* Figure out graph limits after running windowingFunction and smoothing if needed. * This code is shared by wig, bigWig, and bedGraph drawers. */ { -wigTrackSetGraphOutputDefault(tg, xOff, yOff, hvg); /* determined from data */ double graphUpperLimit=0; /* scaling choice will set these */ double graphLowerLimit=0; /* scaling choice will set these */ -double graphRange=0; /* scaling choice will set these */ double epsilon; /* range of data in one pixel */ struct wigCartOptions *wigCart = (struct wigCartOptions *) tg->wigCartData; /* width - width of drawing window in pixels * pixelsPerBase - pixels per base * basesPerPixel - calculated as 1.0/pixelsPerBase */ struct preDrawElement *preDraw = preContainer->preDraw; -if (preContainer->smoothingDone == FALSE) - { preDrawWindowFunction(preDraw, preDrawSize, wigCart->windowingFunction, wigCart->transformFunc, wigCart->doNegative); preDrawSmoothing(preDraw, preDrawSize, wigCart->smoothingWindow); - graphRange = preDrawAutoScale(preDraw, preDrawZero, width, +if (!preContainer->skipAutoscale) // multiWig does own autoscaling + { + preDrawAutoScale(preDraw, preDrawZero, width, wigCart->autoScale, wigCart->windowingFunction, &preContainer->graphUpperLimit, &preContainer->graphLowerLimit, &epsilon, tg->lineHeight, wigCart->maxY, wigCart->minY, wigCart->alwaysZero); } graphUpperLimit = preContainer->graphUpperLimit; graphLowerLimit = preContainer->graphLowerLimit; +if (retGraphUpperLimit != NULL) + *retGraphUpperLimit = graphUpperLimit; +if (retGraphLowerLimit != NULL) + *retGraphLowerLimit = graphLowerLimit; +} + +void wigDrawPredraw(struct track *tg, int seqStart, int seqEnd, + struct hvGfx *hvg, int xOff, int yOff, int width, + MgFont *font, Color color, enum trackVisibility vis, + struct preDrawContainer *preContainer, int preDrawZero, + int preDrawSize, double graphUpperLimit, double graphLowerLimit) +/* Draw once we've figured out predraw (numerical values to graph) we draw it here. + * This code is shared by wig, bigWig, and bedGraph drawers. */ +{ +struct wigCartOptions *wigCart = (struct wigCartOptions *) tg->wigCartData; +double graphRange; /* scaling choice will set this */ /* 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) { - graphRange = 1.0; graphLowerLimit = graphUpperLimit - 1; } -else - { graphRange = graphUpperLimit - graphLowerLimit; - } + +wigTrackSetGraphOutputDefault(tg, xOff, yOff, 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); wigMapSelf(tg, hvg, seqStart, seqEnd, xOff, yOff, width); -if (retGraphUpperLimit != NULL) - *retGraphUpperLimit = graphUpperLimit; -if (retGraphLowerLimit != NULL) - *retGraphLowerLimit = graphLowerLimit; } 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; @@ -1444,44 +1452,81 @@ preDraw[xCoord].sumData += wi->sumData; preDraw[xCoord].sumSquares += wi->sumSquares; } } } /* Draw if span is correct */ } /* for (wi = tg->items; wi != NULL; wi = wi->next) */ if (wibFH > 0) { udcFileClose(&wibFH); wibFH = 0; freeMem(currentFile); } return pre; } -static void wigDrawItems(struct track *tg, int seqStart, int seqEnd, +static void wigPreDrawItems(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw wiggle items that resolve to doing a box for each pixel. */ { struct preDrawContainer *pre = wigLoadPreDraw(tg, seqStart, seqEnd, width); if (pre != NULL) { - wigDrawPredraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis, + wigPreDrawPredraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis, pre, pre->preDrawZero, pre->preDrawSize, &tg->graphUpperLimit, &tg->graphLowerLimit); } } +void wigMultiRegionGraphLimits(struct track *tg) +/* Set common graphLimits across all windows */ +{ +double graphUpperLimit = -BIGDOUBLE; +double graphLowerLimit = BIGDOUBLE; +struct track *tgSave = tg; +struct window *w; +// find graphLimits across all windows. +for(w=windows,tg=tgSave; w; w=w->next,tg=tg->nextWindow) + { + if (tg->graphUpperLimit > graphUpperLimit) + graphUpperLimit = tg->graphUpperLimit; + if (tg->graphLowerLimit < graphLowerLimit) + graphLowerLimit = tg->graphLowerLimit; + } +// set same common graphLimits in all windows. +for(w=windows,tg=tgSave; w; w=w->next,tg=tg->nextWindow) + { + tg->graphUpperLimit = graphUpperLimit; + tg->graphLowerLimit = graphLowerLimit; + } +} + +static void wigDrawItems(struct track *tg, int seqStart, int seqEnd, + struct hvGfx *hvg, int xOff, int yOff, int width, + MgFont *font, Color color, enum trackVisibility vis) +/* Draw wiggle items that resolve to doing a box for each pixel. */ +{ +struct preDrawContainer *pre = tg->preDrawContainer; +if (pre != NULL) + { + wigDrawPredraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis, + pre, pre->preDrawZero, pre->preDrawSize, + tg->graphUpperLimit, tg->graphLowerLimit); + } +} + void wigLeftAxisLabels(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, int height, boolean withCenterLabels, MgFont *font, Color color, enum trackVisibility vis, char *shortLabel, double graphUpperLimit, double graphLowerLimit, boolean showNumbers) /* Draw labels on left for a wiggle-type track. */ { int fontHeight = tl.fontHeight+1; int centerOffset = 0; double lines[2]; /* lines to label */ int numberOfLines = 1; /* at least one: 0.0 */ int i; /* loop counter */ struct wigCartOptions *wigCart = (struct wigCartOptions *) tg->wigCartData; lines[0] = 0.0; @@ -1674,30 +1719,32 @@ * by hgTracks from its cart UI setting. When called in * TotalHeight it will then be the requested visibility. */ void wigMethods(struct track *track, struct trackDb *tdb, int wordCount, char *words[]) { struct wigCartOptions *wigCart = wigCartOptionsNew(cart, tdb, wordCount, words); track->minRange = wigCart->minY; track->maxRange = wigCart->maxY; track->graphUpperLimit = wigEncodeStartingUpperLimit; track->graphLowerLimit = wigEncodeStartingLowerLimit; wigCart->bedGraph = FALSE; /* signal to left labels */ track->loadItems = wigLoadItems; track->freeItems = wigFreeItems; +track->preDrawItems = wigPreDrawItems; +track->preDrawMultiRegion = wigMultiRegionGraphLimits; track->drawItems = wigDrawItems; track->itemName = wigNameCallback; track->mapItemName = wigNameCallback; track->totalHeight = wigTotalHeight; track->itemHeight = tgFixedItemHeight; track->itemStart = tgItemNoStart; track->itemEnd = tgItemNoEnd; /* the wigMaf parent will turn mapsSelf off */ track->mapsSelf = TRUE; track->wigCartData = (void *) wigCart; track->colorShades = shadesOfGray; track->drawLeftLabels = wigLeftLabels; track->loadPreDraw = wigLoadPreDraw; /* the lfSubSample type makes the image map function correctly */