668110379c7c18bc75dd2db8747821b387fb28d6 chmalee Fri Jan 27 10:22:57 2023 -0800 Redraw barChart svgs on the client so the column widths can be wide enough for labels, refs #28439 diff --git src/hg/hgc/barChartClick.c src/hg/hgc/barChartClick.c index ca51ddc..a9b03fe 100644 --- src/hg/hgc/barChartClick.c +++ src/hg/hgc/barChartClick.c @@ -14,30 +14,31 @@ #include "hgc.h" #include "trackHub.h" #include "memgfx.h" #include "hgColors.h" #include "fieldedTable.h" #include "barChartBed.h" #include "barChartCategory.h" #include "barChartData.h" #include "barChartSample.h" #include "barChartUi.h" #include "hgConfig.h" #include "facetedBar.h" #include "pipeline.h" #include "chromAlias.h" +#include "jsHelper.h" #define EXTRA_FIELDS_SIZE 256 struct barChartItemData /* Measured value for a sample and the sample category at a locus. * Used for barChart track details (boxplot) */ { struct barChartItemData *next; /* Next in singly linked list. */ char *sample; /* Sample identifier */ char *category; /* Sample category (from barChartSample table or barChartSampleUrl file) */ double value; /* Measured value (e.g. expression level) */ }; struct barChartPlusRow /* Keep original row around for url processing */ @@ -418,30 +419,31 @@ return longest * 1.02; } void deunderbarColumn(struct fieldedTable *ft, int fieldIx) /* Ununderbar all of a column inside table because space/underbar gets * so confusing */ { struct fieldedRow *row; for (row = ft->rowList; row != NULL; row = row->next) replaceChar(row->row[fieldIx], '_', ' '); } static void svgBarChart(struct barChartBed *chart, struct trackDb *tdb, double maxVal, char *metric) /* Plot bar chart without quartiles or anything fancy just using SVG */ { +jsIncludeFile("hgc.js", NULL); puts("<p>"); /* Load up input labels, color, and data */ struct barChartCategory *categs = barChartUiGetCategories(database, tdb, NULL); int categCount = slCount(categs); if (categCount != chart->expCount) { warn("Problem in %s barchart track. There are %d categories in trackDb and %d in data", tdb->track, categCount, chart->expCount); return; } char *statsFile = hReplaceGbdb(trackDbSetting(tdb, "barChartStatsUrl")); struct hash *statsHash = NULL; int countStatIx = 0; double statsSize = 0.0; @@ -462,77 +464,77 @@ double borderSize = 1.0; double headerHeight = heightPer + 2*borderSize; double innerHeight=heightPer-borderSize; double labelWidth = longestLabelSize(categs) + 9; // Add some because size is just estimate if (labelWidth > totalWidth/2) labelWidth = totalWidth/2; // Don't let labels take up more than half double patchWidth = heightPer; double labelOffset = patchWidth + 2*borderSize; double statsOffset = labelOffset + labelWidth; double barOffset = statsOffset + statsSize; double statsRightOffset = barOffset - 9; double barNumLabelWidth = estimateStringWidth(" 1234.000"); double barMaxWidth = totalWidth-barOffset -barNumLabelWidth ; double totalHeight = headerHeight + heightPer * categCount + borderSize; -printf("<svg width=\"%g\" height=\"%g\">\n", totalWidth, totalHeight); +printf("<svg id='svgBarChart' width=\"%g\" height=\"%g\">\n", totalWidth, totalHeight); /* Draw header */ printf("<rect width=\"%g\" height=\"%g\" style=\"fill:#%s\"/>\n", totalWidth, headerHeight, HG_COL_HEADER); char *sampleLabel = trackDbSettingOrDefault(tdb, "barChartLabel", "Sample"); -printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%s</text>\n", +printf("<text class=\"sampleLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\">%s</text>\n", labelOffset, innerHeight-1, innerHeight-1, sampleLabel); if (statsSize > 0.0) - printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\" text-anchor=\"end\">%s</text>\n", + printf("<text class=\"statsLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\" text-anchor=\"end\">%s</text>\n", statsRightOffset, innerHeight-1, innerHeight-1, "N"); -printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%s %s</text>\n", +printf("<text class=\"valueLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\">%s %s</text>\n", barOffset, innerHeight-1, innerHeight-1, metric, "Value"); /* Set up clipping path for the pesky labels, which may be too long */ printf("<clipPath id=\"labelClip\"><rect x=\"%g\" y=\"0\" width=\"%g\" height=\"%g\"/></clipPath>\n", labelOffset, barOffset-labelOffset, totalHeight); double yPos = headerHeight; struct barChartCategory *categ; int i; for (i=0, categ=categs; i<categCount; ++i , categ=categ->next, yPos += heightPer) { double score = chart->expScores[i]; double barWidth = 0; if (maxVal > 0.0) barWidth = barMaxWidth * score/maxVal; char *deunder = cloneString(categ->label); replaceChar(deunder, '_', ' '); printf("<rect x=\"0\" y=\"%g\" width=\"15\" height=\"%g\" style=\"fill:#%06X\"/>\n", yPos, innerHeight, categ->color); - printf("<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:#%06X\"/>\n", - barOffset, yPos, barWidth, innerHeight, categ->color); + printf("<rect id=\"bar%d\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:#%06X\"/>\n", + i+1, barOffset, yPos, barWidth, innerHeight, categ->color); if (i&1) // every other time - printf("<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:#%06X\"/>\n", + printf("<rect class=\"sampleBand\" x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:#%06X\"/>\n", labelOffset, yPos, labelWidth+statsSize, innerHeight, 0xFFFFFF); - printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\" clip-path=\"url(#labelClip)\"\">%s</text>\n", + printf("<text class=\"sampleLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\" clip-path=\"url(#labelClip)\"\">%s</text>\n", labelOffset, yPos+innerHeight-1, innerHeight-1, deunder); if (statsSize > 0.0) { struct fieldedRow *fr = hashFindVal(statsHash, deunder); if (fr != NULL) { - printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\" text-anchor=\"end\">%s</text>\n", + printf("<text class=\"statsLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\" text-anchor=\"end\">%s</text>\n", statsRightOffset, yPos+innerHeight-1, innerHeight-1, fr->row[countStatIx]); } } - printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%5.3f</text>\n", + printf("<text class=\"valueLabel\" x=\"%g\" y=\"%g\" font-size=\"%g\">%5.3f</text>\n", barOffset+barWidth+2, yPos+innerHeight-1, innerHeight-1, score); } printf("</svg>"); } static void printBarChart(char *item, struct barChartBed *chart, struct trackDb *tdb, double maxVal, char *metric) /* Plot bar chart without expressionMatrix or R plots*/ { char *statsFile = hReplaceGbdb(trackDbSetting(tdb, "barChartStatsUrl")); char *facets = trackDbSetting(tdb, "barChartFacets"); if (facets != NULL && statsFile != NULL) facetedBarChart(item, chart, tdb, maxVal, statsFile, facets, metric); else