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 */