bb7c285d51eabd45fe7fbb3ae297acd0324915b7
kent
  Tue Apr 19 15:09:50 2011 -0700
Refactoring in hopes of making auto-scale work as you'd hope with multiwigs.  That still isn't there, this is just preliminaries.
diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c
index c31ea99..2f1a6b7 100644
--- src/hg/hgTracks/wigTrack.c
+++ src/hg/hgTracks/wigTrack.c
@@ -114,39 +114,41 @@
     colorTrack->loadItems(colorTrack);
     colorTrack->ixColor = hvGfxFindRgb(hvg, &colorTrack->color);
     colorTrack->ixAltColor = hvGfxFindRgb(hvg, &colorTrack->altColor);
     }
 
 if(colorTrack->drawItemAt == linkedFeaturesDrawAt)
     wigFillInColorLfArray(wigTrack, colorArray, colSize, colorTrack);
 else if(colorTrack->drawItemAt == bedDrawSimpleAt)
     wigFillInColorBedArray(wigTrack, colorArray, colSize, colorTrack, hvg);
 
 if(trackLoaded && colorTrack->freeItems != NULL)
     colorTrack->freeItems(colorTrack);
 }
 
 void wigSetCart(struct track *track, char *dataID, void *dataValue)
-    /*	set one of the variables in the wigCart	*/
+/*	set one of the variables in the wigCart.  Actually just MIN_Y or MAX_Y	*/
 {
 struct wigCartOptions *wigCart;
 wigCart = (struct wigCartOptions *) track->extraUiData;
 
 if (sameWord(dataID, MIN_Y))
     wigCart->minY = *((double *)dataValue);
 else if (sameWord(dataID, MAX_Y))
     wigCart->maxY = *((double *)dataValue);
+else
+    internalErr();
 }
 
 /*	these two routines unused at this time	*/
 #if defined(NOT)
 static void wigItemFree(struct wigItem **pEl)
     /* Free up a wigItem. */
 {
 struct wigItem *el = *pEl;
 if (el != NULL)
     {
     /* freeMem(el->name);	DO NOT - this belongs to tg->mapName */
     freeMem(el->db);
     freeMem(el->file);
     freez(pEl);
     }
@@ -529,54 +531,46 @@
 
 sqlFreeResult(&sr);
 hFreeConn(&conn);
 
 slReverse(&wiList);
 tg->items = wiList;
 }	/*	wigLoadItems()	*/
 
 static void wigFreeItems(struct track *tg) {
 #if defined(DEBUG)
 safef(dbgMsg, DBGMSGSZ, "I haven't seen wigFreeItems ever called ?");
 wigDebugPrint("wigFreeItems");
 #endif
 }
 
-struct preDrawElement * initPreDraw(int width, int *preDrawSize,
-	int *preDrawZero)
-/*	initialize a preDraw array of size width	*/
+struct preDrawContainer *initPreDrawContainer(int width)
+/* Initialize preDraw of given size */
 {
-struct preDrawElement *preDraw = (struct preDrawElement *)NULL;
-int i = 0;
-
-/*	we are going to keep an array that is three times the size of
- *	the screen to allow a screen full on either side of the visible
- *	region.  Those side screens can be used in the smoothing
- *	operation so there won't be any discontinuity at the visible screen
- *	boundaries.
- */
-*preDrawSize = width * 3;
-*preDrawZero = width / 3;
-preDraw = (struct preDrawElement *) needMem ((size_t)
-		*preDrawSize * sizeof(struct preDrawElement));
-for (i = 0; i < *preDrawSize; ++i)
+struct preDrawContainer *pre;
+AllocVar(pre);
+int size = pre->preDrawSize = width + 2*wiggleSmoothingMax;	
+pre->preDrawZero = wiggleSmoothingMax;
+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 preDraw;
+return pre;
 }
 
 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);
     }
 return x;
 }
 
@@ -1110,32 +1104,32 @@
     if (Span < minimalSpan)
 	minimalSpan = Span;
     }
 hashElFreeList(&elList);
 
 /*	There may not be a span of 1, use whatever is lowest	*/
 if (minimalSpan > usingDataSpan)
     usingDataSpan = minimalSpan;
 
 return usingDataSpan;
 }
 
 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 *preDrawList,
-	int preDrawZero, int preDrawSize, double *retGraphUpperLimit, double *retGraphLowerLimit)
+	struct preDrawContainer *preDrawList, int preDrawZero, 
+	int preDrawSize, double *retGraphUpperLimit, double *retGraphLowerLimit)
 /* Draw once we've figured out predraw... */
 {
 enum wiggleYLineMarkEnum yLineOnOff;
 double yLineMark;
 
 /*	determined from data	*/
 double overallUpperLimit = wigEncodeStartingUpperLimit;
 double overallLowerLimit = wigEncodeStartingLowerLimit;
 double overallRange=0;		/*	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	*/
 Color *colorArray = NULL;       /*	Array of pixels to be drawn.	*/
 struct wigCartOptions *wigCart = (struct wigCartOptions *) tg->extraUiData;
@@ -1214,65 +1208,63 @@
 
 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;
 }
 
-
-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 *wigLoadPreDraw(struct track *tg, int seqStart, int seqEnd, int width)
+/* Do bits that load the predraw buffer tg->preDraw and also preDrawSize and preDrawZero. */
 {
 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 */
-struct preDrawElement *preDraw;	/* to accumulate everything in prep for draw */
-int preDrawZero;		/* location in preDraw where screen starts */
-int preDrawSize;		/* size of preDraw array */
 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;
+    return NULL;
 
 currentFile[0] = '\0';
 
 if (pixelsPerBase > 0.0)
     basesPerPixel = 1.0 / pixelsPerBase;
 
 /*	width - width of drawing window in pixels
  *	pixelsPerBase - pixels per base
  *	basesPerPixel - calculated as 1.0/pixelsPerBase
  */
 itemCount = 0;
 
-preDraw = initPreDraw(width, &preDrawSize, &preDrawZero);
+/* Allocate predraw and save it and related info in the track. */
+struct preDrawContainer *pre = tg->preDrawContainer = initPreDrawContainer(width);
+struct preDrawElement *preDraw = pre->preDraw;	/* to accumulate everything in prep for draw */
+int preDrawZero = pre->preDrawZero;		/* location in preDraw where screen starts */
+int preDrawSize = pre->preDrawSize;		/* size of preDraw array */
 
 usingDataSpan = wigFindSpan(tg, basesPerPixel);
 
 /*	walk through all the data and prepare the preDraw array	*/
 for (wi = tg->items; wi != NULL; wi = wi->next)
     {
     size_t bytesRead;		/* to check fread being OK */
     int dataOffset = 0;		/*	within data block during drawing */
 
     ++itemCount;
 
 
     /*	Now that we know what Span to draw, see if this item should be
      *	drawn at all.
      */
@@ -1386,44 +1378,46 @@
 		if (upperLimit > preDraw[xCoord].max)
 		    preDraw[xCoord].max = upperLimit;
 		if (wi->lowerLimit < preDraw[xCoord].min)
 		    preDraw[xCoord].min = wi->lowerLimit;
 		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)
     {
     close(wibFH);
     wibFH = 0;
     }
+return pre;
+}
 
-/*	now we are ready to draw.  Each element in the preDraw[] array
- *	cooresponds to a single pixel on the screen
- */
-
-struct preDrawContainer *preDrawContainer;
-AllocVar(preDrawContainer);
-preDrawContainer->preDraw = preDraw;
+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 = wigLoadPreDraw(tg, seqStart, seqEnd, width);
+if (pre != NULL)
+    {
 wigDrawPredraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis,
-	preDrawContainer, preDrawZero, preDrawSize, &tg->graphUpperLimit, &tg->graphLowerLimit);
-
-freeMem(preDrawContainer);
-freeMem(preDraw);
-}	/*	wigDrawItems()	*/
+	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->extraUiData;
 
@@ -1548,31 +1542,30 @@
 	    }	/*	drawing 0.0 and perhaps yLineMark	*/
 	}	/* if (height >= (3 * fontHeight))	*/
     }	/*	if (tg->visibility == tvFull)	*/
 } /* wigAxisLeftLabels */
 
 void wigLeftLabels(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)
 /*	drawing left labels	*/
 {
 wigLeftAxisLabels(tg, seqStart, seqEnd, hvg, xOff, yOff, width, height, withCenterLabels,
 	font, color, vis, tg->shortLabel, tg->graphUpperLimit, tg->graphLowerLimit, TRUE);
 }
 
-
 struct wigCartOptions *wigCartOptionsNew(struct cart *cart, struct trackDb *tdb, int wordCount, char *words[])
 /* Create a wigCartOptions from cart contents and tdb. */
 {
 struct wigCartOptions *wigCart;
 
 int defaultHeight;	/*	truncated by limits	*/
 double yLineMark;	/*	from trackDb or cart */
 int maxHeight = atoi(DEFAULT_HEIGHT_PER);
 int minHeight = MIN_HEIGHT_PER;
 
 AllocVar(wigCart);
 
 /*	These Fetch functions look for variables in the cart bounded by
  *	limits specified in trackDb or returning defaults
  */
@@ -1586,30 +1579,37 @@
 wigFetchMinMaxPixelsWithCart(cart,tdb,tdb->track, &minHeight, &maxHeight, &defaultHeight);
 wigFetchYLineMarkValueWithCart(cart,tdb,tdb->track, &yLineMark);
 wigCart->yLineMark = yLineMark;
 wigCart->yLineOnOff = wigFetchYLineMarkWithCart(cart,tdb,tdb->track, (char **) NULL);
 wigCart->alwaysZero = wigFetchAlwaysZeroWithCart(cart,tdb,tdb->track, (char **) NULL);
 wigCart->transformFunc = wigFetchTransformFuncWithCart(cart,tdb,tdb->track, (char **) NULL);
 
 wigCart->maxHeight = maxHeight;
 wigCart->defaultHeight = defaultHeight;
 wigCart->minHeight = minHeight;
 
 wigFetchMinMaxYWithCart(cart,tdb,tdb->track, &wigCart->minY, &wigCart->maxY, NULL, NULL, wordCount, words);
 
 wigCart->colorTrack = trackDbSetting(tdb, "wigColorBy");
 
+char *containerType = trackDbSetting(tdb, "container");
+if (containerType != NULL && sameString(containerType, "multiWig"))
+     wigCart->isMultiWig = TRUE;
+
+char *aggregate = wigFetchAggregateValWithCart(cart, tdb);
+if (aggregate != NULL)
+    wigCart->overlay = wigIsOverlayTypeAggregate(aggregate);
 return wigCart;
 }
 
 /* Make track group for wig multiple alignment.
  *	WARNING ! - track->visibility is merely the default value
  *	from the trackDb entry at this time.  It will be set after this
  *	 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;