52e0361ea89664bd1dbef9f6612a1662454cec0f
kate
  Tue Oct 20 16:25:00 2015 -0700
Initial code for R-based graph on GTEx details page. refs #15645

diff --git src/hg/hgc/gtexClick.c src/hg/hgc/gtexClick.c
index e2b27c1..c224b2e 100644
--- src/hg/hgc/gtexClick.c
+++ src/hg/hgc/gtexClick.c
@@ -31,30 +31,72 @@
     double min, max;    /* minimum, maximum value */
     double q1, median, q3;      /* quartiles */
     struct slDouble *valList;   /* used to create val array */
     };
 
 int cmpTissueSampleValsMedianScore(const void *va, const void *vb)
 /* Compare RPKM scores */
 {
 const struct tissueSampleVals *a = *((struct tissueSampleVals **)va);
 const struct tissueSampleVals *b = *((struct tissueSampleVals **)vb);
 if (a->median == b->median)
     return 0;
 return (a->median > b->median ? 1: -1);
 }
 
+void RGtexBoxplot(struct tissueSampleVals *tsvList)
+{
+// Tissue list is now sorted by GTEx tissue ordering.  
+// Sort by score descending.
+slSort(&tsvList, cmpTissueSampleValsMedianScore);
+slReverse(&tsvList);
+
+// Create R data frame
+struct tempName dfTn;
+trashDirFile(&dfTn, "hgc", "gtexGene", ".df.txt");
+FILE *f = fopen(dfTn.forCgi, "w");
+if (f == NULL)
+    errAbort("can't create temp file %s", dfTn.forCgi);
+fprintf(f, "sample\ttissue\trpkm\n");
+struct tissueSampleVals *tsv;
+int i;
+int sampleId=1;
+for (tsv = tsvList; tsv != NULL; tsv = tsv->next)
+    {
+    int count = tsv->count;
+    for (i=0; i<count; i++)
+        fprintf(f, "%d\t%s\t%0.3f\n", sampleId++, tsv->description, tsv->vals[i]);
+    }
+fclose(f);
+
+// Plot to PNG file
+struct tempName pngTn;
+trashDirFile(&pngTn, "hgc", "gtexGene", ".png");
+char cmd[256];
+// Exec R in quiet mode, without reading/saving environment or workspace
+safef(cmd, sizeof(cmd), "Rscript --gui=X11 --vanilla --slave gtex/geneBoxplot.R %s %s %s",  
+                                gtexGene->name, dfTn.forCgi, pngTn.forHtml);
+int ret = system(cmd);
+if (ret == 0)
+    {
+    printf("<IMG SRC = \"%s\" BORDER=1><BR>\n", pngTn.forHtml);
+    /*printf("<IMG SRC = \"%s\" BORDER=1 WIDTH=%d HEIGHT=%d><BR>\n",
+                    pngTn.forHtml, imageWidth, imageHeight);
+    */
+    }
+}
+
 void d3GtexBoxplot(struct tissueSampleVals *tsvList)
 {
 //puts("<script src='http://www.d3plus.org/js/d3.js'></script>\n");
 //puts("<script src='http://www.d3plus.org/js/d3plus.js'></script>\n");
 printf("<div id='expGraph'></div>\n");
 jsIncludeFile("d3.min.js", NULL);
 jsIncludeFile("d3plus.gtex.js", NULL);
 jsTrackingVar("geneName", gtexGene->name);
 jsTrackingVar("geneId", gtexGene->geneId);
 jsIncludeFile("gtex.js", NULL);
 }
 
 /* Dimensions of image parts */
 int pad = 2;
 int margin = 1;
@@ -297,31 +339,31 @@
     row = sqlNextRow(sr);
     if (row != NULL)
         {
         gtexGene = gtexGeneBedLoad(row);
         expCount = gtexGene->expCount;
         }
     sqlFreeResult(&sr);
     }
 hFreeConn(&conn);
 
 genericHeader(tdb, item);
 
 if (gtexGene != NULL)
     {
     // TODO: link to UCSC gene
-    printf("<b>Gene:</b> %s</a></br>", gtexGene->name);
+    printf("<b>Gene:</b> %s<br>", gtexGene->name);
     printf("<b>Ensembl ID:</b> %s<br>\n", gtexGene->geneId);
     printf("<a target='_blank' href='http://www.gtexportal.org/home/gene/%s'>View at GTEx portal</a><br>\n", gtexGene->geneId);
     puts("<p>");
     }
 
 // Get full sample data for this gene
 char *sampleDataTable = "gtexSampleData";
 conn = hAllocConn("hgFixed");
 assert(sqlTableExists(conn, sampleDataTable));
 sqlSafef(query, sizeof(query), "select * from %s where geneId='%s'", 
                 sampleDataTable, gtexGene->geneId);
 sr = sqlGetResult(conn, query);
 struct hash *tsHash = hashNew(0);
 struct tissueSampleVals *tsv;
 struct hashEl *hel;
@@ -360,32 +402,35 @@
     int count = tsv->count = slCount(tsv->valList);
     double *vals = AllocArray(tsv->vals, count);
     for (i=0; i<count; i++)
         {
         val = slPopHead(&tsv->valList);
         if (doLogTransform)
             vals[i] = log10(val->val+1.0);
         else
             vals[i] = val->val;
         }
     doubleBoxWhiskerCalc(tsv->count, tsv->vals, 
                                 &tsv->min, &tsv->q1, &tsv->median, &tsv->q3, &tsv->max);
     slAddHead(&tsList, tsv);
     }
 // TODO: Remove one
-if (cgiBoolean("d3"))
+char *viz = cgiUsualString("viz", "c");
+if (sameString(viz, "d3"))
     d3GtexBoxplot(tsList);
+else if (sameString(viz, "R"))
+    RGtexBoxplot(tsList);
 else
     drawGtexBoxplot(tsList, maxVal);
 
 // Track description
 printTrackHtml(tdb);
 
 // Print out tissue table with color assignments
 #ifdef DEBUG
 conn = hAllocConn("hgFixed");
 char *tissueTable = "gtexTissue";
 if (sqlTableExists(conn, tissueTable))
     {
     dyStringPrintf(dy, "<table>");
     dyStringPrintf(dy, "<tr><td><b>Color<b></td><td><b>Tissue<b></td></tr>\n");
     int i;