f7ae366edc0250eb4f61b52bc065ddbe6fa55cfd kent Sat Jan 30 14:16:21 2021 -0800 Making proportional bars respect selected categories, and setting categories from facets, so what gets drawn reflects what facets are selected in faceted mode. diff --git src/hg/hgTracks/barChartTrack.c src/hg/hgTracks/barChartTrack.c index d783df8..c9a390b 100644 --- src/hg/hgTracks/barChartTrack.c +++ src/hg/hgTracks/barChartTrack.c @@ -1,26 +1,28 @@ /* barGraph tracks - display a colored bargraph across each region in a file */ /* Copyright (C) 2015 The Regents of the University of California * See README in this or parent directory for licensing extrasrmation. */ #include "common.h" #include "hgTracks.h" #include "bed.h" #include "hvGfx.h" #include "spaceSaver.h" #include "hubConnect.h" +#include "fieldedTable.h" +#include "facetedTable.h" #include "barChartBed.h" #include "barChartCategory.h" #include "barChartUi.h" // If a category contributes more than this percentage, its color is displayed in squish mode // Could be a trackDb setting struct barChartTrack /* Track extras */ { boolean noWhiteout; /* Suppress whiteout of graph background (allow highlight, blue lines) */ double maxMedian; /* Maximum median across all categories */ boolean doLogTransform; /* Log10(x+1) */ boolean fitToGene; /* Fit our width to gene */ char *unit; /* Units for category values (e.g. RPKM) */ @@ -137,39 +139,58 @@ { extras->colors[i] = (struct rgbColor){.r=COLOR_32_BLUE(categ->color), .g=COLOR_32_GREEN(categ->color), .b=COLOR_32_RED(categ->color)}; i++; } } return extras->colors; } static void filterCategories(struct track *tg) /* Check cart for category selection. NULL out unselected categorys in category list */ { struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; struct barChartCategory *categ = NULL; extras->categories = getCategories(tg); extras->categoryFilter = hashNew(0); -if (cartListVarExistsAnyLevel(cart, tg->tdb, FALSE, BAR_CHART_CATEGORY_SELECT)) +char *barChartFacets = trackDbSetting(tg->tdb, "barChartFacets"); +char *barChartStatsUrl = trackDbSetting(tg->tdb, "barChartStatsUrl"); +if (barChartFacets != NULL && barChartStatsUrl != NULL) + { + struct fieldedTable *table = fieldedTableFromTabFile(barChartStatsUrl, + barChartStatsUrl, NULL, 0); + struct facetedTable *facTab = facetedTableFromTable(table, tg->track, barChartFacets); + struct slInt *sel, *selList = facetedTableSelectOffsets(facTab, cart); + for (sel = selList; sel != NULL; sel = sel->next) + { + char numBuf[16]; + safef(numBuf, sizeof(numBuf), "%d", sel->val); + char *numCopy = lmCloneString(extras->categoryFilter->lm, numBuf); + hashAdd(extras->categoryFilter, numCopy, numCopy); + } + return; + } +else if (cartListVarExistsAnyLevel(cart, tg->tdb, FALSE, BAR_CHART_CATEGORY_SELECT)) { struct slName *selectedValues = cartOptionalSlNameListClosestToHome(cart, tg->tdb, FALSE, BAR_CHART_CATEGORY_SELECT); if (selectedValues != NULL) { struct slName *name; for (name = selectedValues; name != NULL; name = name->next) + { hashAdd(extras->categoryFilter, name->name, name->name); + } return; } } /* no filter */ for (categ = extras->categories; categ != NULL; categ = categ->next) hashAdd(extras->categoryFilter, categ->name, categ->name); } static int filteredCategoryCount(struct barChartTrack *extras) /* Count of categories to display */ { return hashNumEntries(extras->categoryFilter); } static boolean filterCategory(struct barChartTrack *extras, char *name) @@ -841,112 +862,136 @@ if (oneWidth >= 5.0) { if (oneWidth > 7.0) barThinner = 0.8; else barThinner = 0.75; } int iStart = baseWidth*barIx/barCount; int iEnd = baseWidth*(barIx+1)/barCount; int iWidth = iEnd - iStart; int start = *pStart = iStart + bed->chromStart; *pEnd = start + iWidth*barThinner; } +static int countFilteredBars(struct track *tg) +/* Count up number of bars that remain after filtering */ +{ +struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; +struct barChartCategory *categ; +int count = 0; +for (categ=extras->categories; categ != NULL; categ=categ->next) + { + if (filterCategory(extras, categ->name)) + ++count; + } +return count; +} + + static void barsToGeneDrawAt(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 in proportional to gene way*/ { if (vis != tvFull && vis != tvPack) { barChartDrawAt(tg, item, hvg, xOff, y, scale, font, color, vis); return; } /* Fetch our item and the bed from it */ struct barChartItem *itemInfo = (struct barChartItem *)item; struct bed *bed = itemInfo->bed; /* Figure out where to draw things in Y dimension */ struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; int topGraphHeight = chartHeight(tg, itemInfo); topGraphHeight = max(topGraphHeight, tl.fontHeight); int yZero = topGraphHeight + y - 1; // yZero is bottom of graph int yGene = yZero + extras->margin; /* Figure out width between bars */ -int barCount = bed->expCount; +int barCount = countFilteredBars(tg); +int expCount = bed->expCount; -// drawScaledBox(hvg, bed->chromStart, bed->chromEnd, scale, xOff, y, topGraphHeight, MG_YELLOW); // ugly debug int i; Color clipColor = MG_MAGENTA; -for (i=0; i<barCount; ++i) +int outBarIx = 0; +struct barChartCategory *categ; +for (i=0, categ=extras->categories; i<expCount && categ != NULL; ++i, categ=categ->next) { + if (!filterCategory(extras, categ->name)) + continue; struct rgbColor rgb = extras->colors[i]; int color = hvGfxFindColorIx(hvg, rgb.r, rgb.g, rgb.b); int cStart, cEnd; - findBarPosX(bed, scale, i, barCount, &cStart, &cEnd); + findBarPosX(bed, scale, outBarIx, barCount, &cStart, &cEnd); double expScore = bed->expScores[i]; int height = valToClippedHeight(expScore, extras->maxMedian, extras->maxViewLimit, extras->maxHeight, extras->doLogTransform); drawScaledBox(hvg, cStart, cEnd, scale, xOff, y+topGraphHeight-height, height, color); if (!extras->doLogTransform && expScore > extras->maxViewLimit) drawScaledBox(hvg, cStart, cEnd, scale, xOff, yZero-height+1, 2, clipColor); + ++outBarIx; } // Draw the line our graph sits on top of drawScaledBox(hvg, bed->chromStart, bed->chromEnd, scale, xOff, yGene+1, extras->boxModelHeight, MG_GRAY); } static void barsToGeneMapItem(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) */ { enum trackVisibility vis = trackVisAfterLimit(tg); if (vis != tvFull && vis != tvPack) { barChartMapItem(tg, hvg, item, itemName, mapItemName, start, end, x, y, width, height); return; } - struct barChartTrack *extras = tg->extraUiData; struct barChartItem *itemInfo = item; struct bed *bed = itemInfo->bed; -if (width > bed->expCount) // When get down to less than a pixel suppress the bar-by-bar map boxes*/ +int barCount = countFilteredBars(tg); +if (width > barCount) // When get down to less than a pixel suppress the bar-by-bar map boxes*/ { int i = 0; + int outBarIx = 0; struct barChartCategory *categs = getCategories(tg); struct barChartCategory *categ; int topGraphHeight = chartHeight(tg, itemInfo); double scale = scaleForWindow(insideWidth, winStart, winEnd); for (categ = categs; categ != NULL; categ = categ->next, i++) { + if (!filterCategory(extras, categ->name)) + continue; int cStart, cEnd; - findBarPosX(bed, scale, i, bed->expCount, &cStart, &cEnd); + findBarPosX(bed, scale, outBarIx, barCount, &cStart, &cEnd); int x1,x2; if (scaledBoxToPixelCoords(cStart, cEnd, scale, 0, &x1, &x2)) { double expScore = bed->expScores[i]; int height = valToClippedHeight(expScore, extras->maxMedian, extras->maxViewLimit, extras->maxHeight, extras->doLogTransform); mapBoxHc(hvg, bed->chromStart, bed->chromEnd, x1+insideX, y+topGraphHeight-height, x2-x1, height, tg->track, mapItemName, chartMapText(tg, categ, expScore)); } + ++outBarIx; } } mapBoxHc(hvg, bed->chromStart, bed->chromEnd, x, y, width, height, tg->track, itemName, NULL); } void barChartMethods(struct track *tg) /* Bar Chart track type: draw fixed width chart of colored bars over a BED item */ { tg->bedSize = 8; bedMethods(tg); tg->canPack = TRUE; tg->loadItems = barChartLoadItems; tg->itemName = barChartItemName; tg->mapItemName = barChartMapItemName; tg->itemHeight = barChartItemHeight;