dab44418c480b8c931d0b86af916bbb3bf64ffe3 kent Fri Jan 1 08:06:26 2021 -0800 Adding barChartStatsUrl tag. Right now it is ignored by the browser if barChartMatrixUrl is present. It points to a tab separated file with a label row and a few required fields. diff --git src/hg/hgc/barChartClick.c src/hg/hgc/barChartClick.c index 4852218..72bc3df 100644 --- src/hg/hgc/barChartClick.c +++ src/hg/hgc/barChartClick.c @@ -3,30 +3,31 @@ /* Copyright (C) 2015 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "common.h" #include "hash.h" #include "hdb.h" #include "hvGfx.h" #include "trashDir.h" #include "hCommon.h" #include "hui.h" #include "asParse.h" #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" #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 */ @@ -390,80 +391,104 @@ static void printBarChart(struct barChartBed *chart, struct trackDb *tdb, double maxVal, char *metric) /* Plot bar chart without quartiles or anything fancy just using SVG */ { /* Load up input labels, color, and data */ struct barChartCategory *categs = barChartUiGetCategories(database, tdb); 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 = trackDbSetting(tdb, "barChartStatsUrl"); +struct hash *statsHash = NULL; +int countStatIx = 0; +double statsSize = 0.0; +if (statsFile != NULL) + { + char *required[] = {"cluster", "count", "total"}; + struct fieldedTable *ft = fieldedTableFromTabFile( + statsFile, statsFile, required, ArraySize(required)); + statsHash = fieldedTableIndex(ft, "cluster"); + countStatIx = fieldedTableFindFieldIx(ft, "count"); + statsSize = 8*(fieldedTableMaxColChars(ft, countStatIx)+1); + } + /* Some constants that control layout */ double heightPer=18.0; double totalWidth=1250.0; 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 barOffset = labelOffset + labelWidth; +double statsOffset = labelOffset + labelWidth; +double barOffset = statsOffset + statsSize; double barMaxWidth = totalWidth-barOffset - 45; // The 45 is to leave room for ~6 digit number at end. double totalHeight = headerHeight + heightPer * categCount + borderSize; printf("<svg width=\"%g\" height=\"%g\">\n", totalWidth, totalHeight); /* Draw header */ printf("<rect width=\"%g\" height=\"%g\" style=\"fill:#%s\"/>\n", totalWidth, headerHeight, HG_COL_HEADER); printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%s</text>\n", labelOffset, innerHeight-1, innerHeight-1, "Sample"); +if (statsSize > 0.0) + printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%s</text>\n", + statsOffset, innerHeight-1, innerHeight-1, "N"); printf("<text 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; replaceChar(categ->label, '_', ' '); 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); if (i&1) // every other time printf("<rect x=\"%g\" y=\"%g\" width=\"%g\" height=\"%g\" style=\"fill:#%06X\"/>\n", - labelOffset, yPos, labelWidth, innerHeight, 0xFFFFFF); - printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\" clip-path=\"url(#labelClip)\"\">%s</text>\n", - labelOffset, yPos+innerHeight-1, innerHeight-1, categ->label); + labelOffset, yPos, labelWidth+statsSize, innerHeight, 0xFFFFFF); printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\" clip-path=\"url(#labelClip)\"\">%s</text>\n", labelOffset, yPos+innerHeight-1, innerHeight-1, categ->label); + if (statsSize > 0.0) + { + struct fieldedRow *fr = hashFindVal(statsHash, categ->label); + if (fr != NULL) + { + printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%s</text>\n", + statsOffset, yPos+innerHeight-1, innerHeight-1, fr->row[countStatIx]); + } + } printf("<text x=\"%g\" y=\"%g\" font-size=\"%g\">%5.3f</text>\n", barOffset+barWidth+2, yPos+innerHeight-1, innerHeight-1, score); } printf("<svg>"); } struct asColumn *asFindColByIx(struct asObject *as, int ix) /* Find AS column by index */ { struct asColumn *asCol; int i; for (i=0, asCol = as->columnList; asCol != NULL && i<ix; asCol = asCol->next, i++); return asCol; }