ea1646068170b191834889377e21b1bd51259175
kent
  Mon Jan 11 12:56:25 2021 -0800
Putting this under control of svgBarChart variable in hg.conf to keep feature from leaking to users too soon.  Changing N column display of numbers to be right justified as numbers usually are.  Looking up with names in stats table with and without underbars..

diff --git src/hg/hgc/barChartClick.c src/hg/hgc/barChartClick.c
index 72bc3df..230f54e 100644
--- src/hg/hgc/barChartClick.c
+++ src/hg/hgc/barChartClick.c
@@ -10,30 +10,31 @@
 #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"
+#include "hgConfig.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) */
     };
 
 static struct hash *getTrackCategories(struct trackDb *tdb)
 /* Get list of categories from trackDb.  This may be a subset of those in matrix. 
@@ -418,75 +419,79 @@
     }
 
 /* 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 statsOffset = labelOffset + labelWidth;
 double barOffset = statsOffset + statsSize;
+double statsRightOffset = barOffset - 9;
 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\" 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", 
     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, '_', ' ');
+    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);
     if (i&1)  // every other time
 	printf("<rect 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", 
- 	labelOffset, yPos+innerHeight-1, innerHeight-1, categ->label);
+ 	labelOffset, yPos+innerHeight-1, innerHeight-1, deunder);
     if (statsSize > 0.0)
 	{
 	struct fieldedRow *fr = hashFindVal(statsHash, categ->label);
+	if (fr == NULL)
+	    fr = hashFindVal(statsHash, deunder);
 	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\" 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", 
 	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++);
@@ -558,20 +563,21 @@
 puts("<p>");
 if (vals != NULL)
     {
     // Print boxplot
     char *df = makeDataFrame(tdb->table, vals);
     char *colorFile = makeColorFile(tdb);
     printBoxplot(df, item, chartItem->name2, units, colorFile);
     printf("<br><a href='%s'>View all data points for %s%s%s%s</a>\n", df, 
                         chartItem->name, 
                         chartItem->name2 ? " (" : "",
                         chartItem->name2 ? chartItem->name2 : "",
                         chartItem->name2 ? ")" : "");
     }
 else
     {
+    if (cfgOptionBooleanDefault("svgBarChart", FALSE))
 	printBarChart(chartItem, tdb, highLevel, metric);
     }
 puts("<br>");
 }