616062bf13f7e2b83b636936ec237d22caad6d94
kate
  Tue Mar 28 21:18:23 2017 -0700
Add boxplot to details page. Fix colors on track config page. refs #18736

diff --git src/hg/hgc/barChartClick.c src/hg/hgc/barChartClick.c
index eab9e29..62ce56d 100644
--- src/hg/hgc/barChartClick.c
+++ src/hg/hgc/barChartClick.c
@@ -1,76 +1,186 @@
-/* Details pages for GTEx tracks */
+/* Details pages for barChart tracks */
 
 /* 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 "hgc.h"
 #include "hCommon.h"
 
 #include "barChartBed.h"
 #include "barChartCategory.h"
+#include "barChartData.h"
+#include "barChartSample.h"
 #include "barChartUi.h"
 
-static struct barChartBed *getBarChart(char *item, char *chrom, int start, int end, char *table)
+static struct barChartBed *getBarChart(char *item, char *chrom, int start, int end, char *track)
 /* Retrieve barChart BED item from the main track table */
 {
 struct barChartBed *barChart = NULL;
 struct sqlConnection *conn = hAllocConn(database);
 char **row;
 char query[512];
 struct sqlResult *sr;
-if (sqlTableExists(conn, table))
+if (sqlTableExists(conn, track))
     {
     sqlSafef(query, sizeof query, 
                 "SELECT * FROM %s WHERE name='%s'"
                     "AND chrom='%s' AND chromStart=%d AND chromEnd=%d", 
-                                table, item, chrom, start, end);
+                                track, item, chrom, start, end);
     sr = sqlGetResult(conn, query);
     row = sqlNextRow(sr);
     if (row != NULL)
         {
         barChart = barChartBedLoad(row);
         }
     sqlFreeResult(&sr);
     }
 hFreeConn(&conn);
 return barChart;
 }
 
-#define BAR_CHART_UNITS_DEFAULT "Value"
+static struct barChartData *getSampleVals(char *track, char *item)
+/* Get data values for this item (locus) from all samples */
+{
+char table[256];
+safef(table, sizeof(table), "%s%s", track, "Data");
+struct sqlConnection *conn = hAllocConn(database);
+if (!sqlTableExists(conn, table))
+    {
+    hFreeConn(&conn);
+    conn = hAllocConn("hgFixed");
+    if (!sqlTableExists(conn, table))
+        {
+        hFreeConn(&conn);
+        return NULL;
+        }
+    }
+struct barChartData *vals = barChartDataLoadForLocus(conn, table, item);
+hFreeConn(&conn);
+return vals;
+}
+
+static char *makeDataFrame(char *track, struct barChartData *vals)
+/* Create R data frame from sample data.  This is a tab-sep file, one row per sample.
+   Return filename. */
+{
+// Get category for samples 
+char table[256];
+safef(table, sizeof(table), "%s%s", track, "Sample");
+struct sqlConnection *conn = hAllocConn(database);
+if (!sqlTableExists(conn, table))
+    {
+    hFreeConn(&conn);
+    conn = hAllocConn("hgFixed");
+    if (!sqlTableExists(conn, table))
+        {
+        hFreeConn(&conn);
+        return NULL;
+        }
+}
+char query[512];
+sqlSafef(query, sizeof(query), "SELECT * FROM %s", table);
+struct barChartSample *sample, *samples = barChartSampleLoadByQuery(conn, query);
+hFreeConn(&conn);
+struct hash *sampleHash = hashNew(0);
+for (sample = samples; sample != NULL; sample = sample->next)
+    {
+    hashAdd(sampleHash, sample->sample, sample);
+    }
+
+// Create data frame with columns for sample, category, value */
+struct tempName dfTn;
+trashDirFile(&dfTn, "hgc", "barChart", ".df.txt");
+FILE *f = fopen(dfTn.forCgi, "w");
+if (f == NULL)
+    errAbort("can't create temp file %s", dfTn.forCgi);
+fprintf(f, "sample\tcategory\tvalue\n");
+int i = 0;
+struct barChartData *val;
+for (val = vals; val != NULL; val = val->next)
+    {
+    struct barChartSample *sample = hashFindVal(sampleHash, val->sample);
+    if (sample == NULL)
+        warn("barChart track %s: unknown category for sample %s", track, val->sample);
+    else
+        fprintf(f, "%d\t%s\t%0.3f\n", i++, sample->category, val->value);
+    }
+fclose(f);
+return cloneString(dfTn.forCgi);
+}
+
+char *makeColorFile(struct trackDb *tdb)
+/* Make a file with category + color */
+{
+struct tempName colorTn;
+trashDirFile(&colorTn, "hgc", "barChartColors", ".txt");
+FILE *f = fopen(colorTn.forCgi, "w");
+if (f == NULL)
+    errAbort("can't create temp file %s", colorTn.forCgi);
+struct barChartCategory *categs = barChartUiGetCategories(database, tdb);
+struct barChartCategory *categ;
+fprintf(f, "%s\t%s\n", "category", "color");
+for (categ = categs; categ != NULL; categ = categ->next)
+    {
+    //fprintf(f, "%s\t#%06X\n", categ->label, categ->color);
+    fprintf(f, "%s\t%d\n", categ->label, categ->color);
+    }
+fclose(f);
+return cloneString(colorTn.forCgi);
+}
+
+static void printBoxplot(char *df, char *item, char *units, char *colorFile)
+/* Plot data frame to image file and include in HTML */
+{
+struct tempName pngTn;
+trashDirFile(&pngTn, "hgc", "barChart", ".png");
+
+/* Exec R in quiet mode, without reading/saving environment or workspace */
+char cmd[256];
+safef(cmd, sizeof(cmd), "Rscript --vanilla --slave hgcData/barChartBoxplot.R %s %s %s %s %s",
+                                item, units, colorFile, df, pngTn.forHtml);
+int ret = system(cmd);
+if (ret == 0)
+    printf("<img src = \"%s\" border=1><br>\n", pngTn.forHtml);
+}
 
 void doBarChartDetails(struct trackDb *tdb, char *item)
+
 /* Details of barChart item */
 {
 int start = cartInt(cart, "o");
 int end = cartInt(cart, "t");
-struct barChartBed *barChart = getBarChart(item, seqName, start, end, tdb->table);
-if (barChart == NULL)
+struct barChartBed *chartItem = getBarChart(item, seqName, start, end, tdb->table);
+if (chartItem == NULL)
     errAbort("Can't find item %s in barChart table %s\n", item, tdb->table);
 
 genericHeader(tdb, item);
 int categId;
-float highLevel = barChartHighestValue(barChart, &categId);
-printf("<b>Highest value: </b> %0.2f in %s<br>\n", 
-                highLevel, barChartUiGetCategoryLabelById(categId, database, tdb));
-printf("<b>Total all values: </b> %0.2f<br>\n", barChartTotalValue(barChart));
-printf("<b>Score: </b> %d<br>\n", barChart->score); 
+float highLevel = barChartHighestValue(chartItem, &categId);
+char *units = trackDbSettingClosestToHomeOrDefault(tdb, BAR_CHART_UNIT, "");
+printf("<b>Maximum value: </b> %0.2f %s in %s<br>\n", 
+                highLevel, units, barChartUiGetCategoryLabelById(categId, database, tdb));
+printf("<b>Total all values: </b> %0.2f<br>\n", barChartTotalValue(chartItem));
+printf("<b>Score: </b> %d<br>\n", chartItem->score); 
 printf("<b>Genomic position: "
                 "</b>%s <a href='%s&db=%s&position=%s%%3A%d-%d'>%s:%d-%d</a><br>\n", 
                     database, hgTracksPathAndSettings(), database, 
-                    barChart->chrom, barChart->chromStart+1, barChart->chromEnd,
-                    barChart->chrom, barChart->chromStart+1, barChart->chromEnd);
+                    chartItem->chrom, chartItem->chromStart+1, chartItem->chromEnd,
+                    chartItem->chrom, chartItem->chromStart+1, chartItem->chromEnd);
+struct barChartData *vals = getSampleVals(tdb->table, item);
+if (vals != NULL)
+    {
+    // Print boxplot
     puts("<p>");
-
-#ifdef BOXPLOT
-struct tempName pngTn;
-if (barChartBoxplot(barChart->name, &pngTn))
-    printf("<img src = \"%s\" border=1><br>\n", pngTn.forHtml);
-printf("<br>");
-#endif
+    char *df = makeDataFrame(tdb->table, vals);
+    char *colorFile = makeColorFile(tdb);
+    printBoxplot(df, item, units, colorFile);
+    }
+puts("<br>");
 printTrackHtml(tdb);
 }
+