141deaec9ba7a2912faedaf2a62fa189108b4c43
braney
  Thu Apr 13 12:15:01 2023 -0700
some final clean-up on logoMaf:   allow the user to turn it off, and
scale by the amount of the data within the clipping rectangle

diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c
index 367c06f..d8acb83 100644
--- src/hg/hgTracks/wigTrack.c
+++ src/hg/hgTracks/wigTrack.c
@@ -37,34 +37,35 @@
     int ix;		/* Position in list. */
     int height;		/* Pixel height of item. */
     unsigned span;      /* each value spans this many bases */
     unsigned count;     /* number of values to use */
     unsigned offset;    /* offset in File to fetch data */
     char *file; /* path name to data file, one byte per value */
     double lowerLimit;  /* lowest data value in this block */
     double dataRange;   /* lowerLimit + dataRange = upperLimit */
     unsigned validCount;        /* number of valid data values in this block */
     double sumData;     /* sum of the data points, for average and stddev calc */
     double sumSquares;      /* sum of data points squared, for stddev calc */
     double graphUpperLimit;	/* filled in by DrawItems	*/
     double graphLowerLimit;	/* filled in by DrawItems	*/
     };
 
-static boolean doLogo(struct trackDb *tdb)
+static boolean doLogo(struct track *tg)
 /* Are we going to draw a logo? */
 {
-return trackDbSettingOn(tdb, "logo") || (trackDbSetting(tdb, "logoMaf") != NULL); 
+struct wigCartOptions *wigCart = tg->wigCartData;
+return trackDbSettingOn(tg->tdb, "logo") || ((trackDbSetting(tg->tdb, "logoMaf") != NULL) && wigCart->doSequenceLogo); 
 }
 
 static void wigFillInColorLfArray(struct track *wigTrack, Color *colArray, int colSize,
 				  struct track *colorTrack)
 /* Fill in a color array with the linkedFeatures based colorTrack's
    color where it would normally have an exon. */
 {
 struct linkedFeatures *lf = NULL, *lfList = colorTrack->items;
 struct simpleFeature *sf = NULL;
 double scale = scaleForPixels(colSize);
 int x1 = 0, x2 = 0;
 int i = 0;
 for(lf = lfList; lf != NULL; lf = lf->next)
     {
     for (sf = lf->components; sf != NULL; sf = sf->next)
@@ -1222,32 +1223,30 @@
     double graphRange, enum trackVisibility vis, struct wigCartOptions *wigCart, int seqStart, int seqEnd)
 {
 boolean baseCmpl = cartUsualBooleanDb(cart, database, COMPLEMENT_BASES_VAR, FALSE);
 struct preDrawElement *preDraw = preDrawContainer->preDraw;
 struct wigGraphOutput *wgo = tg->wigGraphOutput;
 //struct wigMouseOver *mouseOverData = NULL;
 unsigned numBases = seqEnd - seqStart;
 struct dnaSeq *seq = hChromSeq(database, chromName, seqStart, seqEnd);
 if (baseCmpl)
     complement(seq->dna, seq->size);
 
 struct pixelCountBin *pixelBins = wgo->pixelBins;
 double *yOffsets = wgo->yOffsets;
 int numTrack = wgo->numTrack;
 Color clipColor = MG_MAGENTA;
-WigVerticalLineVirtual vLine = wgo->vLine;
-void *image = wgo->image;
 #define doLine(image, x, y, height, color) {vLine(image, x, y, height, color); }
 
 int h = tg->lineHeight;	/*	the height of our drawing window */
 double scaleFactor = h/graphRange;
 struct wigMouseOver *mouseOverData = getMouseOverData(tg, preDraw, width, xOff, preDrawZero);
 
 struct mafBaseProbs *baseProbs = wigCart->baseProbs;
 if (baseProbs != NULL)
     {
     // initialize our nucleotide probability data structure
     probVals[0].next = &probVals[1];
     probVals[1].next = &probVals[2];
     probVals[2].next = &probVals[3];
 
     boolean baseCmpl = cartUsualBooleanDb(cart, database, COMPLEMENT_BASES_VAR, FALSE);
@@ -1314,30 +1313,35 @@
 	 *	to the graphing space, the data value is at:
 	 *	h * ((graphUpperLimit - dataValue)/graphRange)
 	 *	and a data value zero line is at:
 	 *	h * (graphUpperLimit/graphRange)
 	 *	These may end up to be negative meaning they are above
 	 *	the upper graphing limit, or be very large, meaning they
          *      are below the lower graphing limit.  This is OK, the
          *      clipping will be taken care of by the vgBox() function.
          */
 
         if (vis == tvFull || vis == tvPack)
             {
 #define scaleHeightToPixels(val) (min(BIGNUM,(scaleFactor * (graphUpperLimit - (val)) + yOff)))
 #define doLine(image, x, y, height, color) {vLine(image, x, y, height, color); }
                 {
+                // since we're drawing a sequence logo, we want to scale by the part of the line within the clipping window
+                if (dataValue > graphUpperLimit)
+                    dataValue = graphUpperLimit;
+                else if (dataValue < graphLowerLimit)
+                    dataValue = graphLowerLimit;
                 int y0 = graphUpperLimit * scaleFactor;
                 int y1 = (graphUpperLimit - dataValue)*scaleFactor;
                 if (yOffsets)
                     {
                     if (numTrack > 0)
                         {
                         y0 = (graphUpperLimit  - yOffsets[(numTrack-1) *  width + x1]) *scaleFactor;
                         y1 = (graphUpperLimit - dataValue - yOffsets[(numTrack-1) *  width + x1])*scaleFactor;
                         }
                     }
 
                 int boxHeight = max(1,abs(y1 - y0));
                 int boxTop = min(y1,y0);
 
                 //	positive data value exactly equal to Bottom pixel
@@ -1414,37 +1418,37 @@
                             }
                         else
                             {
                             hvGfxTextInBox(hvg, x, yOff+boxTop, baseWidth - 1, boxHeight,
                                 color, font, string);
                             }
                         }
                     }
                 if (((boxTop+boxHeight) == 0) && !isnan(dataValue))
                     boxHeight += 1;
                 }
 	    double stackValue = dataValue;
 
 	    if ((yOffsets != NULL) && (numTrack > 0))
 		stackValue += yOffsets[(numTrack-1) *  width + x1];
-	    if (stackValue > graphUpperLimit)
+	    if (stackValue >= graphUpperLimit)
                 {
-		doLine(image, x, yOff, 2, clipColor);
+                hvGfxLine(hvg, x, yOff, x+baseWidth, yOff, clipColor);
                 }
-	    else if (stackValue < graphLowerLimit)
+	    else if (stackValue <= graphLowerLimit)
                 {
-		doLine(image, x, yOff + h - 1, 2, clipColor);
+                hvGfxLine(hvg, x, yOff + h - 1, x+baseWidth, yOff + h - 1, clipColor);
                 }
 #undef scaleHeightToPixels	/* No longer use this symbol */
             }   /*	vis == tvFull || vis == tvPack */
         }
     }	/*	for (x1 = 0; x1 < width; ++x1)	*/
 
 return(mouseOverData);
 }
 
 struct wigMouseOver *graphPreDrawContainer(struct preDrawContainer *preDrawContainer,
     int preDrawZero, int width, struct track *tg, struct hvGfx *hvg,
     int xOff, int yOff, double graphUpperLimit, double graphLowerLimit,
     double graphRange, enum trackVisibility vis, struct wigCartOptions *wigCart)
 /* Draw the graphs for all tracks in container. */
 {
@@ -1698,31 +1702,31 @@
     }
 
 /* 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)
     {
     graphLowerLimit = graphUpperLimit - 1;
     }
 graphRange = graphUpperLimit - graphLowerLimit;
 
 wigTrackSetGraphOutputDefault(tg, xOff, yOff, width, hvg);
 
 struct wigMouseOver *mouseOverData = NULL;
-if (zoomedToCodonLevel && doLogo(tg->tdb) && vis != tvDense)
+if (zoomedToCodonLevel && doLogo(tg) && vis != tvDense)
     mouseOverData = logoPreDrawContainer(preContainer,
         preDrawZero, width, tg, hvg, xOff, yOff,
         graphUpperLimit, graphLowerLimit, graphRange, vis, wigCart, seqStart, seqEnd);
 else
     mouseOverData = 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,
@@ -1942,30 +1946,31 @@
     freeMem(currentFile);
     }
 return pre;
 }
 
 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. */
 {
 char *logoMaf = trackDbSetting(tg->tdb, "logoMaf");
 
 if (logoMaf != NULL)
     {
     struct wigCartOptions *wigCart = tg->wigCartData;
+    if (wigCart->doSequenceLogo)
         wigCart->baseProbs = hgMafProbs(database, logoMaf, chromName, seqStart, seqEnd, '+');
     }
 
 struct preDrawContainer *pre = wigLoadPreDraw(tg, seqStart, seqEnd, width);
 if (pre != NULL)
     {
     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 */
 {
@@ -2167,30 +2172,31 @@
  */
 wigCart->lineBar = wigFetchGraphTypeWithCart(cart,tdb,tdb->track, (char **) NULL);
 wigCart->horizontalGrid = wigFetchHorizontalGridWithCart(cart,tdb,tdb->track, (char **) NULL);
 
 wigCart->autoScale = wigFetchAutoScaleWithCart(cart,tdb,tdb->track, (char **) NULL);
 wigCart->windowingFunction = wigFetchWindowingFunctionWithCart(cart,tdb,tdb->track, (char **) NULL);
 wigCart->smoothingWindow = wigFetchSmoothingWindowWithCart(cart,tdb,tdb->track, (char **) NULL);
 
 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 = (enum wiggleAlwaysZeroEnum)wigFetchAlwaysZeroWithCart(cart,tdb,tdb->track, (char **) NULL);
 wigCart->transformFunc = (enum wiggleTransformFuncEnum)wigFetchTransformFuncWithCart(cart,tdb,tdb->track, (char **) NULL);
 wigCart->doNegative = wigFetchDoNegativeWithCart(cart,tdb,tdb->track, (char **) NULL);
+wigCart->doSequenceLogo = wigFetchDoSequenceLogoWithCart(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;
 
 wigCart->aggregateFunction = wigFetchAggregateFunctionWithCart(cart,tdb,tdb->track, (char **) NULL);