549dcd456f5d557e15426176e487f91246363548 kate Mon Apr 10 17:21:22 2017 -0700 Better integration with bigBed cod. Fixes loading problem and allows labelFields code to operate (not yet tested). refs #18736 diff --git src/hg/hgTracks/barChartTrack.c src/hg/hgTracks/barChartTrack.c index b4099fd..4d06e29 100644 --- src/hg/hgTracks/barChartTrack.c +++ src/hg/hgTracks/barChartTrack.c @@ -24,31 +24,31 @@ double maxMedian; /* Maximum median across all categories */ boolean doLogTransform; /* Log10(x+1) */ char *unit; /* Units for category values (e.g. RPKM) */ struct barChartCategory *categories; /* Category names, colors, etc. */ int categCount; /* Count of categories - derived from above */ char **categNames; /* Category names - derived from above */ char **categLabels; /* Category labels - derived from above */ struct rgbColor *colors; /* Colors for all categories */ struct hash *categoryFilter; /* NULL out excluded factors */ }; struct barChartItem /* BED item plus computed values for display */ { struct barChartItem *next; /* Next in singly linked list */ - struct barChartBed *bed; /* Item coords, name, exp count and values */ + struct bed *bed; /* Item coords, name, exp count and values */ int height; /* Item height in pixels */ }; /***********************************************/ /* Organize category info */ struct barChartCategory *getCategories(struct track *tg) /* Get and cache category info */ { struct barChartTrack *info = (struct barChartTrack *)tg->extraUiData; if (info->categories == NULL) info->categories = barChartUiGetCategories(database, tg->tdb); return info->categories; } @@ -180,93 +180,93 @@ static int filteredCategoryCount(struct track *tg) /* Count of categories to display */ { struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; return hashNumEntries(extras->categoryFilter); } static boolean filterCategory(struct track *tg, char *name) /* Does category pass filter */ { struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; return (hashLookup(extras->categoryFilter, name) != NULL); } -static int maxCategoryForItem(struct barChartBed *bed, int threshold) +static int maxCategoryForItem(struct bed *bed, int threshold) /* Return id of highest valued category for an item, if significantly higher than median. * If none are over threshold, return -1 */ { double maxScore = 0.0, expScore; double totalScore = 0.0; int maxNum = 0, i; int expCount = bed->expCount; for (i=0; i<expCount; i++) { expScore = bed->expScores[i]; if (expScore > maxScore) { maxScore = max(maxScore, expScore); maxNum = i; } totalScore += expScore; } // threshold to consider this item category specific -- a category contributes > threshold % to // total level if (totalScore < 1 || maxScore <= (totalScore * threshold * .01)) return -1; return maxNum; } static Color barChartItemColor(struct track *tg, void *item, struct hvGfx *hvg) /* A bit of category-specific coloring in squish mode only, on bed item */ // TODO: Need a good function here to pick threshold from category count. // Also maybe trackDb setting { -struct barChartBed *bed = (struct barChartBed *)item; +struct bed *bed = (struct bed *)item; int id = maxCategoryForItem(bed, SPECIFICITY_THRESHOLD); if (id < 0) return MG_BLACK; struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; struct rgbColor color = extras->colors[id]; return hvGfxFindColorIx(hvg, color.r, color.g, color.b); } static void barChartLoadItems(struct track *tg) /* Load method for track items */ { if (tg->visibility == tvSquish || tg->limitedVis == tvSquish) tg->itemColor = barChartItemColor; /* Get track UI info */ struct barChartTrack *extras; AllocVar(extras); tg->extraUiData = extras; extras->doLogTransform = cartUsualBooleanClosestToHome(cart, tg->tdb, FALSE, BAR_CHART_LOG_TRANSFORM, BAR_CHART_LOG_TRANSFORM_DEFAULT); extras->maxMedian = barChartUiMaxMedianScore(); extras->noWhiteout = cartUsualBooleanClosestToHome(cart, tg->tdb, FALSE, BAR_CHART_NO_WHITEOUT, BAR_CHART_NO_WHITEOUT_DEFAULT); extras->unit = trackDbSettingClosestToHomeOrDefault(tg->tdb, BAR_CHART_UNIT, ""); /* Get bed (names and all-sample category median scores) in range */ -loadSimpleBedWithLoader(tg, (bedItemLoader)barChartBedLoad); +loadSimpleBedWithLoader(tg, (bedItemLoader)barChartSimpleBedLoad); /* Create itemInfo items with BED and geneModels */ struct barChartItem *itemInfo = NULL, *list = NULL; -struct barChartBed *bed = (struct barChartBed *)tg->items; +struct bed *bed = (struct bed *)tg->items; /* Load category colors */ extras->colors = getCategoryColors(tg); filterCategories(tg); while (bed != NULL) { AllocVar(itemInfo); itemInfo->bed = bed; slAddHead(&list, itemInfo); bed = bed->next; itemInfo->bed->next = NULL; itemInfo->height = barChartItemHeight(tg, itemInfo); } @@ -331,31 +331,31 @@ else if (winSize < WIN_MED_GRAPH) return MED_GRAPH_HEIGHT; else return tl.fontHeight * 4; } static int barChartWidth(struct track *tg, struct barChartItem *itemInfo) /* Width of bar chart in pixels */ { int barWidth = barChartBarWidth(tg); int padding = barChartPadding(); int count = filteredCategoryCount(tg); return (barWidth * count) + (padding * (count-1)) + 2; } -static int barChartX(struct barChartBed *bed) +static int barChartX(struct bed *bed) /* Locate chart on X, relative to viewport. */ { int start = max(bed->chromStart, winStart); double scale = scaleForWindow(insideWidth, winStart, winEnd); int x1 = round((start - winStart) * scale); return x1; } static int barChartMargin() { return 1; } static int valToHeight(double val, double maxVal, int maxHeight, boolean doLogTransform) /* Log-scale and convert a value from 0 to maxVal to 0 to maxHeight-1 */ @@ -378,31 +378,31 @@ { double useVal = val; double useMax = maxVal; if (!doLogTransform) { useMax = maxView; if (val > maxView) useVal = maxView; } return valToHeight(useVal, useMax, barChartMaxHeight(), doLogTransform); } static int barChartHeight(struct track *tg, struct barChartItem *itemInfo) /* Determine height in pixels of graph. This will be the box for category with highest value */ { -struct barChartBed *bed = (struct barChartBed *)itemInfo->bed; +struct bed *bed = (struct bed *)itemInfo->bed; struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; int i; double maxExp = 0.0; int expCount = bed->expCount; double expScore; for (i=0; i<expCount; i++) { if (!filterCategory(tg, getCategoryName(tg, i))) continue; expScore = bed->expScores[i]; maxExp = max(maxExp, expScore); } double viewMax = (double)cartUsualIntClosestToHome(cart, tg->tdb, FALSE, BAR_CHART_MAX_LIMIT, BAR_CHART_MAX_LIMIT_DEFAULT); // TODO: add trackDb settings for MAX_LIMIT values ? @@ -421,31 +421,31 @@ static void drawGraphBase(struct track *tg, struct barChartItem *itemInfo, struct hvGfx *hvg, int x, int y) /* Draw faint line under graph to delineate extent when bars are missing (category w/ 0 value) */ { Color lightGray = MAKECOLOR_32(0xD1, 0xD1, 0xD1); int graphWidth = barChartWidth(tg, itemInfo); hvGfxBox(hvg, x, y, graphWidth, 1, lightGray); } static void barChartDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) /* Draw bar chart over item */ { struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; struct barChartItem *itemInfo = (struct barChartItem *)item; -struct barChartBed *bed = (struct barChartBed *)itemInfo->bed; +struct bed *bed = (struct bed *)itemInfo->bed; if (vis == tvDense) { bedDrawSimpleAt(tg, bed, hvg, xOff, y, scale, font, MG_WHITE, vis); // color ignored (using grayscale) return; } if (vis == tvSquish) { Color color = barChartItemColor(tg, bed, hvg); int height = barChartSquishItemHeight(); drawScaledBox(hvg, bed->chromStart, bed->chromEnd, scale, xOff, y, height, color); return; } int graphX = barChartX(bed); if (graphX < 0) @@ -467,31 +467,31 @@ static int barChartNonPropPixelWidth(struct track *tg, void *item) /* Return end chromosome coordinate of item, including graph */ { struct barChartItem *itemInfo = (struct barChartItem *)item; int graphWidth = barChartWidth(tg, itemInfo); return graphWidth; } static void barChartNonPropDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) { if (vis != tvFull && vis != tvPack) return; struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; struct barChartItem *itemInfo = (struct barChartItem *)item; -struct barChartBed *bed = (struct barChartBed *)itemInfo->bed; +struct bed *bed = (struct bed *)itemInfo->bed; int topGraphHeight = barChartHeight(tg, itemInfo); topGraphHeight = max(topGraphHeight, tl.fontHeight); int yZero = topGraphHeight + y - 1; // yZero is bottom of graph int graphX = barChartX(bed); int x1 = xOff + graphX; // x1 is at left of graph int keepX = x1; drawGraphBase(tg, itemInfo, hvg, keepX, yZero+1); if (!extras->noWhiteout) drawGraphBox(tg, itemInfo, hvg, keepX, yZero+1); struct rgbColor lineColor = {.r=0}; int lineColorIx = hvGfxFindColorIx(hvg, lineColor.r, lineColor.g, lineColor.b); int barWidth = barChartBarWidth(tg); @@ -500,36 +500,38 @@ BAR_CHART_COLORS_DEFAULT); Color clipColor = MG_MAGENTA; // draw bar graph double viewMax = (double)cartUsualIntClosestToHome(cart, tg->tdb, FALSE, BAR_CHART_MAX_LIMIT, BAR_CHART_MAX_LIMIT_DEFAULT); double maxMedian = ((struct barChartTrack *)tg->extraUiData)->maxMedian; int i; int expCount = bed->expCount; struct barChartCategory *categ; for (i=0, categ=extras->categories; i<expCount; i++, categ=categ->next) { if (!filterCategory(tg, categ->name)) continue; struct rgbColor fillColor = extras->colors[i]; - if (barWidth == 1 && sameString(colorScheme, BAR_CHART_COLORS_USER)) - { +/* // brighten colors a bit so they'll be more visible at this scale // TODO: think about doing this - //fillColor = barChartBrightenColor(fillColor); + if (barWidth == 1 && sameString(colorScheme, BAR_CHART_COLORS_USER)) + { + fillColor = barChartBrightenColor(fillColor); } +*/ int fillColorIx = hvGfxFindColorIx(hvg, fillColor.r, fillColor.g, fillColor.b); double expScore = bed->expScores[i]; int height = valToClippedHeight(expScore, maxMedian, viewMax, barChartMaxHeight(), extras->doLogTransform); if (graphPadding == 0 || sameString(colorScheme, BAR_CHART_COLORS_USER)) hvGfxBox(hvg, x1, yZero-height+1, barWidth, height, fillColorIx); else hvGfxOutlinedBox(hvg, x1, yZero-height+1, barWidth, height, fillColorIx, lineColorIx); // mark clipped bar with magenta tip if (!extras->doLogTransform && expScore > viewMax) hvGfxBox(hvg, x1, yZero-height+1, barWidth, 2, clipColor); x1 = x1 + barWidth + graphPadding; } } @@ -581,70 +583,70 @@ } static char *barChartMapText(struct track *tg, struct barChartCategory *categ, double expScore) /* Construct mouseover text for a chart bar */ { static char buf[128]; struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; safef(buf, sizeof(buf), "%s (%.1f %s)", categ->label, expScore, extras->unit); return buf; } static int barChartItemStart(struct track *tg, void *item) /* Return end chromosome coordinate of item, including graph */ { struct barChartItem *itemInfo = (struct barChartItem *)item; -struct barChartBed *bed = (struct barChartBed *)itemInfo->bed; +struct bed *bed = (struct bed *)itemInfo->bed; return bed->chromStart; } static int barChartItemEnd(struct track *tg, void *item) /* Return end chromosome coordinate of item, including graph */ { struct barChartItem *itemInfo = (struct barChartItem *)item; -struct barChartBed *bed = (struct barChartBed *)itemInfo->bed; +struct bed *bed = (struct bed *)itemInfo->bed; double scale = scaleForWindow(insideWidth, winStart, winEnd); int graphWidth = barChartWidth(tg, itemInfo); return max(bed->chromEnd, max(winStart, bed->chromStart) + graphWidth/scale); } static void getItemX(int start, int end, int *x1, int *x2) /* Return startX, endX based on item coordinates and current window */ // Residual (largely replaced by drawScaledBox -- still used by gene model bmap box { int s = max(start, winStart); int e = min(end, winEnd); double scale = scaleForWindow(insideWidth, winStart, winEnd); assert(x1); *x1 = round((double)((int)s-winStart)*scale + insideX); assert(x2); *x2 = round((double)((int)e-winStart)*scale + insideX); } static void barChartMapItem(struct track *tg, struct hvGfx *hvg, void *item, char *itemName, char *mapItemName, int start, int end, int x, int y, int width, int height) /* Create a map box on item and label, and one for each category (bar in the graph) in * pack or full mode. Just single map for squish/dense modes */ { if (tg->limitedVis == tvDense) { genericMapItem(tg, hvg, item, itemName, itemName, start, end, x, y, width, height); return; } struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; struct barChartItem *itemInfo = (struct barChartItem *)item; -struct barChartBed *bed = (struct barChartBed *)itemInfo->bed; +struct bed *bed = (struct bed *)itemInfo->bed; int itemStart = bed->chromStart; int itemEnd = bed->chromEnd; if (tg->limitedVis == tvSquish) { int categId = maxCategoryForItem(bed, SPECIFICITY_THRESHOLD); char *maxCateg = ""; if (categId > 1) maxCateg = getCategoryLabel(tg, categId); char buf[128]; safef(buf, sizeof buf, "%s %s", bed->name, maxCateg); int x1, x2; getItemX(itemStart, itemEnd, &x1, &x2); int width = max(1, x2-x1); mapBoxHc(hvg, itemStart, itemEnd, x1, y, width, height, tg->track, mapItemName, buf); @@ -787,31 +789,33 @@ MgFont *font, Color color, enum trackVisibility vis) { if (vis == tvSquish || vis == tvDense) { // NonProp routines not relevant to these modes, and they interfere // NOTE: they must be installed by barChartMethods() for pack mode tg->nonPropDrawItemAt = NULL; tg->nonPropPixelWidth = NULL; } } static char *barChartItemName(struct track *tg, void *item) /* Return item name */ { struct barChartItem *chartItem = (struct barChartItem *)item; -struct barChartBed *bed = (struct barChartBed *)chartItem->bed; +struct bed *bed = (struct bed *)chartItem->bed; +if (tg->isBigBed) + return bigBedItemName(tg, bed); return bed->name; } void barChartMethods(struct track *tg) /* Bar Chart track type: draw fixed width chart of colored bars over a BED item */ { // TODO: derive this from AS or trackDb ? tg->bedSize = 8; bedMethods(tg); tg->canPack = TRUE; tg->drawItemAt = barChartDrawAt; tg->preDrawItems = barChartPreDrawItems; tg->loadItems = barChartLoadItems; tg->mapItem = barChartMapItem; tg->itemName = barChartItemName;