f8de331fce87ec0df45e71399f7450c0dd69d189
braney
  Sat May 6 17:31:44 2017 -0700
on going work on custom composites

diff --git src/hg/hgTracks/multiWig.c src/hg/hgTracks/multiWig.c
index 6ba20a2..0d4cc9f 100644
--- src/hg/hgTracks/multiWig.c
+++ src/hg/hgTracks/multiWig.c
@@ -230,51 +230,43 @@
 static struct wigGraphOutput *setUpWgo(int xOff, int yOff, int width, int height, int numTracks, struct wigCartOptions *wigCart, struct hvGfx *hvg)
 {
 /* Deal with tranparency possibly */
 struct wigGraphOutput *wgo;
 struct floatPic *floatPic = NULL;
 switch(wigCart->aggregateFunction)
     {
     case wiggleAggregateTransparent:
 	{
 	//int height = tg->lineHeight;
 	floatPic = floatPicNew(width, height);
 	floatPicSet(floatPic, 1, 1, 1);
 	wgo = wigGraphOutputTransparent(floatPic);
 	break;
 	}
+    case wiggleAggregateSubtract:
     case wiggleAggregateNone:
+    case wiggleAggregateAdd:
     case wiggleAggregateSolid:
 	{
 	wgo = wigGraphOutputSolid(xOff, yOff, hvg);
 	break;
 	}
     case wiggleAggregateStacked:
 	{
 	wgo = wigGraphOutputStack(xOff, yOff, width, numTracks, hvg);
 	break;
 	}
-    case wiggleAggregateAdd:
-	{
-	wgo = wigGraphOutputStack(xOff, yOff, width, numTracks, hvg);
-	break;
-	}
-    case wiggleAggregateSubtract:
-	{
-	wgo = wigGraphOutputStack(xOff, yOff, width, numTracks, hvg);
-	break;
-	}
     default:
 	{
 	errAbort("bad aggregate function (value: %d)\n", wigCart->aggregateFunction);
 	break;
 	}
     }
 return wgo;
 }
 
 
 static void multiWigPreDraw(struct track *tg, int seqStart, int seqEnd,
         struct hvGfx *hvg, int xOff, int yOff, int width, 
         MgFont *font, Color color, enum trackVisibility vis)
 /* Pre-Draw multiWig container calls preDraw on all subtracks. */
 {
@@ -395,30 +387,71 @@
 	    wigCart->minY = graphUpperLimit;
 	    wigCart->maxY = graphLowerLimit;
 	    struct preDrawContainer *pre = tgs->preDrawContainer;
 	    if (pre != NULL)  // pre maybe null if the load fails
 		{
 		pre->graphUpperLimit = graphUpperLimit;
 		pre->graphLowerLimit = graphLowerLimit;
 		}
 	    tgs->graphUpperLimit = graphUpperLimit;
 	    tgs->graphLowerLimit = graphLowerLimit;
 	    }
 	}
     }
 }
 
+static void mergeWiggles(struct track *tg, boolean add)
+{
+struct preDrawContainer *firstPre = tg->preDrawContainer;
+
+struct track *firstTrack = tg;
+struct wigCartOptions *wigCart = (struct wigCartOptions *) tg->wigCartData;
+int ii;
+
+for(tg = tg->next; tg; tg = tg->next)
+    {
+    struct preDrawContainer *pre = tg->preDrawContainer;
+
+    for(ii=firstPre->preDrawZero; ii < firstPre->preDrawZero + firstPre->width; ii++)
+        {
+        struct preDrawElement *firstPreDraw = &firstPre->preDraw[ii];
+        struct preDrawElement *thisPreDraw = &pre->preDraw[ii];
+        if (add)
+            firstPreDraw->smooth += thisPreDraw->smooth;
+        else
+            firstPreDraw->smooth -= thisPreDraw->smooth;
+        }
+    }
+if (wigCart->autoScale == wiggleScaleAuto)
+    {
+    double upperLimit = wigEncodeStartingUpperLimit;
+    double lowerLimit = wigEncodeStartingLowerLimit;
+    for(ii=firstPre->preDrawZero; ii < firstPre->preDrawZero + firstPre->width; ii++)
+        {
+        struct preDrawElement *firstPreDraw = &firstPre->preDraw[ii];
+        if (firstPreDraw->smooth < lowerLimit)
+            lowerLimit = firstPreDraw->smooth;
+        if (firstPreDraw->smooth > upperLimit)
+            upperLimit = firstPreDraw->smooth;
+        }
+    firstTrack->graphLowerLimit = lowerLimit;
+    firstTrack->graphUpperLimit = upperLimit;
+    firstPre->graphLowerLimit = lowerLimit;
+    firstPre->graphUpperLimit = upperLimit;
+    }
+}
+
 static void multiWigDraw(struct track *tg, int seqStart, int seqEnd,
         struct hvGfx *hvg, int xOff, int yOff, int width, 
         MgFont *font, Color color, enum trackVisibility vis)
 /* Draw items in multiWig container. */
 {
 struct track *subtrack;
 boolean errMsgShown = FALSE;
 int y = yOff;
 boolean errMsgFound = FALSE;
 // determine if any subtracks had errors and count them up
 for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next)
     {
     if (isSubtrackVisible(subtrack) )
 	{
 	if (subtrack->networkErrMsg)
@@ -430,30 +463,35 @@
     {
     int clipXBak, clipYBak, clipWidthBak, clipHeightBak;
     hvGfxGetClip(hvg, &clipXBak, &clipYBak, &clipWidthBak, &clipHeightBak);
     hvGfxUnclip(hvg);
     hvGfxSetClip(hvg, fullInsideX, yOff, fullInsideWidth, tg->height);
     // use the height of the multiWig 
     Color yellow = hvGfxFindRgb(hvg, &undefinedYellowColor);
     hvGfxBox(hvg, fullInsideX, yOff, fullInsideWidth, tg->height, yellow);
     hvGfxUnclip(hvg);
     hvGfxSetClip(hvg, clipXBak, clipYBak, clipWidthBak, clipHeightBak);
     }
 
 struct wigCartOptions *wigCart = tg->wigCartData;
 struct wigGraphOutput *wgo = tg->wigGraphOutput;
 
+if (wigCart->aggregateFunction == wiggleAggregateAdd || wigCart->aggregateFunction == wiggleAggregateSubtract)
+    {
+    mergeWiggles(tg->subtracks, wigCart->aggregateFunction == wiggleAggregateAdd);
+    tg->subtracks->next = NULL;
+    }
 int numTrack = 0;
 for (subtrack = tg->subtracks; subtrack != NULL; subtrack = subtrack->next)
     {
     if (isSubtrackVisible(subtrack))
 	{
         if (!subtrack->networkErrMsg || !errMsgShown)
 	    {
 	    if (subtrack->networkErrMsg)
 	       errMsgShown = TRUE;
 	    wgo->numTrack = numTrack++;
 	    subtrack->wigGraphOutput = wgo;
 	    int height = subtrack->totalHeight(subtrack, vis);
 	    hvGfxSetClip(hvg, xOff, y, width, height);
 	    if (wigCart->aggregateFunction != wiggleAggregateNone)
 		subtrack->lineHeight = tg->lineHeight;