a981318c28445664c4fb9c6ef2b6918e2094da98 chmalee Fri Mar 4 14:38:29 2022 -0800 Changes from code review. Also restore original bar width calculation as it makes barChartStretchToItem work better, refs #29021 diff --git src/hg/hgTracks/barChartTrack.c src/hg/hgTracks/barChartTrack.c index 9d7765d..0a9dce2 100644 --- src/hg/hgTracks/barChartTrack.c +++ src/hg/hgTracks/barChartTrack.c @@ -381,31 +381,31 @@ /* How wide is chart if we go by standard bar chart size? */ { struct barChartTrack *extras = (struct barChartTrack *)tg->extraUiData; int count = filteredCategoryCount(extras); return (extras->barWidth * count) + (extras->padding * (count-1)) + 2; } static int windowsTotalIntersection(struct window *list, char *chrom, int chromStart, int chromEnd) /* Return total size all bits of region defined by chrom/start/end that intersects windows list */ { if (list == NULL || list->next == NULL) { double scale = scaleForWindow(insideWidth, winStart, winEnd); int leftBlank = round(scale * (max(winStart, chromStart) - winStart)); int rightBlank = round(scale * (winEnd - min(winEnd, chromEnd))); - return (double)insideWidth - leftBlank - rightBlank; + return insideWidth - leftBlank - rightBlank; } long long totalGenoSize = 0; int totalPixelSize = 0; struct window *w; int totalIntersect = 0; for (w = list; w != NULL; w = w->next) { totalPixelSize += w->insideWidth;; totalGenoSize += w->winEnd - w->winStart; if (sameString(w->chromName, chrom)) { int single = rangeIntersection(w->winStart, w->winEnd, chromStart, chromEnd); if (single > 0) totalIntersect += single; @@ -542,32 +542,32 @@ filterCategories(tg); /* Test that configuration matches data file */ if (bedList != NULL) { int categCount = getCategoryCount(tg); int expCount = bedList->expCount; if (categCount != expCount) warn("Bar chart track: category count mismatch between trackDb (%d) and data file (%d)", categCount, expCount); } int barCount = filteredCategoryCount(extras); // users can set minimum bar width and padding in trackDb -char *userBarWidth = trackDbSetting(tdb, BAR_CHART_USER_BAR_WIDTH); -char *userBarPadding = trackDbSetting(tdb, BAR_CHART_USER_BAR_PADDING); +char *userSettingMinBarWidth = trackDbSetting(tdb, BAR_CHART_USER_BAR_MIN_WIDTH); +char *userSettingMinBarPadding = trackDbSetting(tdb, BAR_CHART_USER_BAR_MIN_PADDING); /* Scaling here is pretty ad-hoc! */ double scale = 1.0; if (barCount <= 20) scale = 2.5; else if (barCount <= 40) scale = 1.6; else if (barCount <= 60) scale = 1.0; else scale = 60.0/barCount; #ifdef OLD else if (barCount <= 120) scale = 0.8; else if (barCount <= 200) @@ -608,54 +608,55 @@ } else if (winSize < extras->winSmallGraph) { extras->boxModelHeight = SMALL_BAR_CHART_MODEL_HEIGHT; extras->barWidth = SMALL_BAR_WIDTH * scale; extras->padding = SMALL_GRAPH_PADDING * scale; extras->maxHeight = SMALL_GRAPH_HEIGHT; } else { extras->boxModelHeight = MIN_BAR_CHART_MODEL_HEIGHT; extras->barWidth = MIN_BAR_WIDTH * scale; extras->padding = MIN_GRAPH_PADDING * scale; extras->maxHeight = tl.fontHeight * 4; } + if (extras->barWidth > 1) extras->barWidth = floor(extras->barWidth); if (extras->barWidth <= 1 && extras->padding == 1) { extras->barWidth = 2; extras->padding = 0; } if (extras->barWidth < 1) { extras->barWidth = 1; extras->padding = 0; } else extras->barWidth = round(extras->barWidth); -if (userBarWidth) +if (userSettingMinBarWidth) { - int barWidth = sqlUnsigned(userBarWidth); - extras->barWidth = barWidth > extras->barWidth ? barWidth : extras->barWidth; + int userMinBarWidth = sqlUnsigned(userSettingMinBarWidth); + extras->barWidth = max(userMinBarWidth, extras->barWidth); } -if (userBarPadding) +if (userSettingMinBarPadding) { - int barPadding = sqlUnsigned(userBarPadding); - extras->padding = barPadding > extras->padding ? barPadding : extras->padding; + int userMinBarPadding = sqlUnsigned(userSettingMinBarPadding); + extras->padding = max(userMinBarPadding, extras->padding); } extras->modelHeight = extras->boxModelHeight + 3; extras->margin = 1; extras->squishHeight = tl.fontHeight - tl.fontHeight/2; extras->stretchToItem = trackDbSettingOn(tg->tdb, "barChartStretchToItem"); struct bed *bed, *next; for (bed = bedList; bed != NULL; bed = next) { next = bed->next; bed->next = NULL; /* Pop it off list */ AllocVar(itemInfo); itemInfo->bed = (struct bed *)bed; slAddHead(&list, itemInfo); @@ -762,51 +763,53 @@ drawGraphBox(tg, itemInfo, hvg, x0, yZero+1); struct rgbColor lineColor = {.r=0}; int lineColorIx = hvGfxFindColorIx(hvg, lineColor.r, lineColor.g, lineColor.b); int barWidth = extras->barWidth; char *colorScheme = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, BAR_CHART_COLORS, BAR_CHART_COLORS_DEFAULT); Color clipColor = MG_MAGENTA; // draw bar graph int i; int expCount = bed->expCount; struct barChartCategory *categ; int barCount = filteredCategoryCount(extras), barsDrawn = 0; double invCount = 1.0/barCount; -char *userBarWidth = trackDbSetting(tg->tdb, BAR_CHART_USER_BAR_WIDTH); -if ((extras->padding == 0 || sameString(colorScheme, BAR_CHART_COLORS_USER)) - && !userBarWidth) - { - // scale the barWidth on the graph size at this zoom level - barWidth = max(barWidth, graphWidth * invCount); - } +char *userSettingMinBarWidth = trackDbSetting(tg->tdb, BAR_CHART_USER_BAR_MIN_WIDTH); +int userMinBarWidth = 0; +if (userSettingMinBarWidth) + userMinBarWidth = sqlUnsigned(userSettingMinBarWidth); for (i=0, categ=extras->categories; i<expCount && categ != NULL; i++, categ=categ->next) { if (!filterCategory(extras, categ->name)) continue; struct rgbColor fillColor = extras->colors[i]; int fillColorIx = hvGfxFindColorIx(hvg, fillColor.r, fillColor.g, fillColor.b); double expScore = bed->expScores[i]; int height = valToClippedHeight(expScore, extras->maxMedian, extras->maxViewLimit, extras->maxHeight, extras->doLogTransform); boolean isClipped = (!extras->doLogTransform && expScore > extras->maxViewLimit); int barTop = yZero - height + 1; if (extras->padding == 0 || sameString(colorScheme, BAR_CHART_COLORS_USER)) { - x1 = x0 + (barWidth * barsDrawn); + int cStart = barsDrawn * graphWidth * invCount; + int cEnd = (barsDrawn+1) * graphWidth * invCount; + x1 = cStart + x0; + barWidth = max(userMinBarWidth, cEnd - cStart - extras->padding); + if (x1 + barWidth > x0 + graphWidth) + break; hvGfxBox(hvg, x1, barTop, barWidth, height, fillColorIx); if (isClipped) hvGfxBox(hvg, x1, barTop, barWidth, 2, clipColor); barsDrawn += 1; } else { hvGfxOutlinedBox(hvg, x1, barTop, barWidth, height, fillColorIx, lineColorIx); // mark clipped bar with magenta tip if (isClipped) hvGfxBox(hvg, x1, barTop, barWidth, 2, clipColor); x1 = x1 + barWidth + extras->padding; } } } @@ -891,47 +894,51 @@ int labelWidth = mgFontStringWidth(tl.font, itemName); getItemX(start, end, &x1, &x2); if (x1-labelWidth <= insideX) labelWidth = 0; // map over label int itemHeight = itemInfo->height; mapBoxHc(hvg, itemStart, itemEnd, x1-labelWidth, y, labelWidth, itemHeight-3, tg->track, mapItemName, itemName); int graphX = barChartX(bed); int graphWidth = chartWidth(tg, itemInfo); int barCount = filteredCategoryCount(extras); char label[256]; +char *userSettingMinBarWidth= trackDbSetting(tg->tdb, BAR_CHART_USER_BAR_MIN_WIDTH); +int userMinBarWidth = 0; +if (userSettingMinBarWidth) + userMinBarWidth = sqlUnsigned(userSettingMinBarWidth); if (barCount <= graphWidth) // Don't create map boxes if less than one pixel per bar { // add maps to category bars struct barChartCategory *categs = getCategories(tg); struct barChartCategory *categ = NULL; int x0 = insideX + graphX; double invCount = 1.0/barCount; int i = 0, barsDrawn = 0; int extraAtTop = 4; for (categ = categs; categ != NULL; categ = categ->next, i++) { if (!filterCategory(extras, categ->name)) continue; x1 = barsDrawn * graphWidth * invCount; barsDrawn += 1; x2 = barsDrawn * graphWidth * invCount; - int width = max(1, x2-x1); + int width = max(userMinBarWidth, max(1, x2-x1)); double expScore = bed->expScores[i]; int height = valToClippedHeight(expScore, extras->maxMedian, extras->maxViewLimit, extras->maxHeight, extras->doLogTransform); height = min(height+extraAtTop, extras->maxHeight); mapBoxHc(hvg, itemStart, itemEnd, x0 + x1, yZero-height, width, height, tg->track, mapItemName, chartMapText(tg, categ, expScore)); } safef(label, sizeof(label), "%s - click for faceted view or hover over a bar for sample values", itemName); } else safef(label, sizeof(label), "%s - zoom in to resolve individual bars or click for details", itemName);