50d5df2a88178ea49caa2fd1b41ce28af84f219f
braney
  Mon May 8 12:36:08 2023 -0700
support bigMaf for sequence logos

diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c
index 7a84bab..62e2573 100644
--- src/hg/hgTracks/wigTrack.c
+++ src/hg/hgTracks/wigTrack.c
@@ -15,30 +15,31 @@
 #include "wiggle.h"
 #include "hmmstats.h"
 #include "scoredRef.h"
 #ifndef GBROWSE
 #include "customTrack.h"
 #endif /* GBROWSE */
 #include "wigCommon.h"
 #include "imageV2.h"
 #include "memgfx.h"
 #include "udc.h"
 #include "trashDir.h"
 #include "jsonWrite.h"
 #include "dnaMotif.h"
 #include "maf.h"
 #include "hgMaf.h"
+#include "chromAlias.h"
 
 struct wigItem
 /* A wig track item. */
     {
     struct wigItem *next;
     int start, end;	/* Start/end in chrom (aka browser) coordinates. */
     char *db;		/* Database */
     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 */
@@ -1236,54 +1237,56 @@
 int numTrack = wgo->numTrack;
 Color clipColor = MG_MAGENTA;
 #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];
+    probVals[3].next = NULL;
 
     boolean baseCmpl = cartUsualBooleanDb(cart, database, COMPLEMENT_BASES_VAR, FALSE);
     if (baseCmpl)
         {
         probVals[3].nuc = "A";
         probVals[3].color = MG_RED;
         probVals[2].nuc = "C";
         probVals[2].color = MG_BROWN;
         probVals[1].nuc = "G";
         probVals[1].color = MG_BLUE;
         probVals[0].nuc = "T";
         probVals[0].color = MG_GREEN;
         }
     else
         {
         probVals[0].nuc = "A";
         probVals[0].color = MG_RED;
         probVals[1].nuc = "C";
         probVals[1].color = MG_BROWN;
         probVals[2].nuc = "G";
         probVals[2].color = MG_BLUE;
         probVals[3].nuc = "T";
         probVals[3].color = MG_GREEN;
         }
+    probList = probVals;  // a sortable list 
     }
 
 double xIncr = (double)width / numBases;
 unsigned baseNum;
 for(baseNum = 0; baseNum < numBases; baseNum++)
     {
     int x1 = ceil(baseNum * xIncr);
     int x = x1 + xOff;
     int baseWidth = xIncr;
     int base = seq->dna[baseNum];
     int preDrawIndex = x1 + preDrawZero;
     struct preDrawElement *p = &preDraw[preDrawIndex];
 
     assert(x1/pixelBins->binSize < pixelBins->binCount);
     unsigned long *bitCount = &pixelBins->bins[x1/pixelBins->binSize];
@@ -1418,35 +1421,35 @@
                             }
                         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)
                 {
                 hvGfxLine(hvg, x, yOff, x+baseWidth, yOff, clipColor);
                 }
-	    else if (stackValue <= graphLowerLimit)
+	    else if (stackValue < graphLowerLimit)
                 {
                 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)
@@ -1936,43 +1939,60 @@
 		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 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. */
+void wigLogoMafCheck(struct track *tg,  int start, int end)
+/* Check to see if we should draw a sequence logo for the wiggle contents. */
 {
 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, '+');
+        {
+        // see if the MAF is a bigBed
+        if (endsWith(logoMaf, ".bb") || endsWith(logoMaf, ".bigMaf"))
+            {
+            struct bbiFile *bbi = bigBedFileOpenAlias(logoMaf, chromAliasFindAliases);
+            wigCart->baseProbs = hgBigMafProbs(database, bbi, chromName, start, end, '+');
+            bbiFileClose(&bbi);
+            tg->bbiFile = NULL;
+            }
+        else  // otherwise it's a table
+            wigCart->baseProbs = hgMafProbs(database, logoMaf, chromName, start, end, '+');
         }
+    }
+}
+
+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. */
+{
+wigLogoMafCheck(tg, 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 */
 {
 double graphUpperLimit = -BIGDOUBLE;
 double graphLowerLimit = BIGDOUBLE;