3904cbc6353d7d6d09d7615bfddf7449456588f5
kent
  Tue Apr 19 16:54:41 2011 -0700
Making autoscale work as you'd hope for multiWigs - where all the wigs have a common scale.
diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c
index 2f1a6b7..10144ee 100644
--- src/hg/hgTracks/wigTrack.c
+++ src/hg/hgTracks/wigTrack.c
@@ -538,50 +538,57 @@
 
 static void wigFreeItems(struct track *tg) {
 #if defined(DEBUG)
 safef(dbgMsg, DBGMSGSZ, "I haven't seen wigFreeItems ever called ?");
 wigDebugPrint("wigFreeItems");
 #endif
 }
 
 struct preDrawContainer *initPreDrawContainer(int width)
 /* Initialize preDraw of given size */
 {
 struct preDrawContainer *pre;
 AllocVar(pre);
 int size = pre->preDrawSize = width + 2*wiggleSmoothingMax;	
 pre->preDrawZero = wiggleSmoothingMax;
+pre->width = width;
 struct preDrawElement *preDraw = AllocArray(pre->preDraw, pre->preDrawSize);
 int i;
 for (i = 0; i < size; ++i)
     {
     preDraw[i].count = 0;
     preDraw[i].max = wigEncodeStartingUpperLimit;
     preDraw[i].min = wigEncodeStartingLowerLimit;
     }
 return pre;
 }
 
+double wiggleLogish(double x)
+/* Return log-like transform without singularity at 0. */
+{
+if (x >= 0)
+    return log(1+x);
+else
+    return -log(1-x);
+}
+
 static double doTransform(double x, enum wiggleTransformFuncEnum transformFunc)
 /* Do log-type transformation if asked. */
 {
 if (transformFunc == wiggleTransformFuncLog)
     {
-    if (x >= 0)
-	x = log(1+x);
-    else
-	x = -log(1-x);
+    x = wiggleLogish(x);
     }
 return x;
 }
 
 
 void preDrawWindowFunction(struct preDrawElement *preDraw, int preDrawSize,
 	enum wiggleWindowingEnum windowingFunction,
 	enum wiggleTransformFuncEnum transformFunc)
 /*	apply windowing function to the values in preDraw array	*/
 {
 int i;
 
 /*	Determine the raw plotting value	*/
 for (i = 0; i < preDrawSize; ++i)
     {
@@ -679,70 +686,78 @@
 return (overallUpperLimit - overallLowerLimit);
 }
 
 double preDrawAutoScale(struct preDrawElement *preDraw, int preDrawZero,
     int width, enum wiggleScaleOptEnum autoScale,
     double *overallUpperLimit, double *overallLowerLimit,
     double *graphUpperLimit, double *graphLowerLimit,
     double *overallRange, double *epsilon, int lineHeight,
     double maxY, double minY, enum wiggleAlwaysZeroEnum alwaysZero)
 /*	if autoScaling, scan preDraw array and determine limits */
 {
 double graphRange;
 
 if (autoScale == wiggleScaleAuto)
     {
-    int i;
+    int i, lastI = preDrawZero+width;
 
     /* reset limits for auto scale */
-    for (i = preDrawZero; i < preDrawZero+width; ++i)
+    for (i = preDrawZero; i < lastI; ++i)
 	{
 	/*	count is non-zero meaning valid data exists here	*/
 	if (preDraw[i].count)
 	    {
 	    if (preDraw[i].smooth > *overallUpperLimit)
 		*overallUpperLimit = preDraw[i].smooth;
 	    if (preDraw[i].smooth < *overallLowerLimit)
 		*overallLowerLimit = preDraw[i].smooth;
 	    }
 	}
     if (alwaysZero == wiggleAlwaysZeroOn)
 	{
 	if ( *overallUpperLimit < 0)
 	    *overallUpperLimit = 0.0;
 	else if ( *overallLowerLimit > 0)
 	    *overallLowerLimit = 0.0;
 	}
     *overallRange = *overallUpperLimit - *overallLowerLimit;
     if (*overallRange == 0.0)
 	{
 	if (*overallUpperLimit > 0.0)
 	    {
 	    *graphUpperLimit = *overallUpperLimit;
 	    *graphLowerLimit = 0.0;
-	    } else if (*overallUpperLimit < 0.0) {
+	    } 
+	else if (*overallUpperLimit < 0.0) 
+	    {
 	    *graphUpperLimit = 0.0;
 	    *graphLowerLimit = *overallUpperLimit;
-	    } else {
+	    } 
+	else 
+	    {
 	    *graphUpperLimit = 1.0;
 	    *graphLowerLimit = -1.0;
 	    }
-	} else {
+	} 
+    else 
+        {
 	*graphUpperLimit = *overallUpperLimit;
 	*graphLowerLimit = *overallLowerLimit;
 	}
-    } else {
+    } 
+else 
+    {
 	*graphUpperLimit = maxY;
 	*graphLowerLimit = minY;
     }
 graphRange = *graphUpperLimit - *graphLowerLimit;
 *epsilon = graphRange / lineHeight;
 return(graphRange);
 }
 
 static Color * makeColorArray(struct preDrawElement *preDraw, int width,
     int preDrawZero, struct wigCartOptions *wigCart, struct track *tg, struct hvGfx *hvg)
 /*	allocate and fill in a coloring array based on another track */
 {
 char *colorTrack = wigCart->colorTrack;
 int x1;
 Color *colorArray = NULL;       /*	Array of pixels to be drawn.	*/
@@ -1173,68 +1188,70 @@
 	graphLowerLimit = thisGraphLowerLimit;
 	}
     else
 	{
 	if (overallUpperLimit < thisOverallUpperLimit)
 	    overallUpperLimit = thisOverallUpperLimit;
 	if (overallLowerLimit > thisOverallLowerLimit)
 	    overallLowerLimit = thisOverallLowerLimit;
 	if (graphUpperLimit < thisGraphUpperLimit)
 	    graphUpperLimit = thisGraphUpperLimit;
 	if (graphLowerLimit > thisGraphLowerLimit)
 	    graphLowerLimit = thisGraphLowerLimit;
 	}
     }
 
-
 overallRange = overallUpperLimit - overallLowerLimit;
 graphRange = graphUpperLimit - graphLowerLimit;
 epsilon = graphRange / tg->lineHeight;
 struct preDrawElement *preDraw = preDrawList->preDraw;
-colorArray = makeColorArray(preDraw, width, preDrawZero,
-    wigCart, tg, hvg);
+colorArray = makeColorArray(preDraw, width, preDrawZero, wigCart, tg, hvg);
 
 /* now draw all the containers */
 for(preContainer = preDrawList; preContainer; preContainer = preContainer->next)
     {
     struct preDrawElement *preDraw = preContainer->preDraw;
     graphPreDraw(preDraw, preDrawZero, width,
 	tg, hvg, xOff, yOff, graphUpperLimit, graphLowerLimit, graphRange,
 	epsilon, colorArray, vis, wigCart);
     }
 
 drawZeroLine(vis, wigCart->horizontalGrid,
     graphUpperLimit, graphLowerLimit,
     hvg, xOff, yOff, width, tg->lineHeight);
 
 drawArbitraryYLine(vis, wigCart->yLineOnOff,
     graphUpperLimit, graphLowerLimit,
     hvg, xOff, yOff, width, tg->lineHeight, wigCart->yLineMark, graphRange,
     wigCart->yLineOnOff);
 
 wigMapSelf(tg, hvg, seqStart, seqEnd, xOff, yOff, width);
 
 freez(&colorArray);
 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->preDraw and also preDrawSize and preDrawZero. */
+/* 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[PATH_LEN];
 int wibFH = 0;		/*	file handle to binary file */
 int i;				/* an integer loop counter	*/
 int x1 = 0;			/*	screen coordinates	*/
 int x2 = 0;			/*	screen coordinates	*/
 int usingDataSpan = 1;		/* will become larger if possible */
 
 if (tg->items == NULL)
     return NULL;
 
 currentFile[0] = '\0';
@@ -1620,19 +1637,20 @@
 track->loadItems = wigLoadItems;
 track->freeItems = wigFreeItems;
 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->extraUiData = (void *) wigCart;
 track->colorShades = shadesOfGray;
 track->drawLeftLabels = wigLeftLabels;
+track->loadPreDraw = wigLoadPreDraw;
 /*	the lfSubSample type makes the image map function correctly */
 track->subType = lfSubSample;     /*make subType be "sample" (=2)*/
 
 }	/*	wigMethods()	*/