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;