d6039d2a5b455ea12543034b5f959886d6d7e51f
kate
  Thu Mar 24 20:45:39 2016 -0700
1. Add -log option to bedScore. 2. Score GTEx gene track bed files based on total median expression level across all tissues, for use in dense mode (gray-scale based on total expression), and display score on details page. 3. Implement viz for squished mode -- show color of highest expressed tissue if over threshold, and show tissue name in mouseover.  refs #15645

diff --git src/hg/hgTracks/gtexTracks.c src/hg/hgTracks/gtexTracks.c
index caa71a4..13dacfa 100644
--- src/hg/hgTracks/gtexTracks.c
+++ src/hg/hgTracks/gtexTracks.c
@@ -108,45 +108,62 @@
 
 int getTissueCount(char *version)
 /* Get and cache the number of tissues in GTEx tissue table */
 {
 static int tissueCount = 0;
 
 if (!tissueCount)
     tissueCount = slCount(getTissues(version));
 return tissueCount;
 }
 
 char *getTissueName(int id, char *version)
 /* Get tissue name from id, cacheing */
 {
 static char **tissueNames = NULL;
-
 struct gtexTissue *tissue;
 int count = getTissueCount(version);
 if (!tissueNames)
     {
     struct gtexTissue *tissues = getTissues(version);
     AllocArray(tissueNames, count);
     for (tissue = tissues; tissue != NULL; tissue = tissue->next)
         tissueNames[tissue->id] = cloneString(tissue->name);
     }
 if (id >= count)
     errAbort("GTEx tissue table problem: can't find id %d\n", id);
 return tissueNames[id];
 }
 
+char *getTissueDescription(int id, char *version)
+/* Get tissue description from id, cacheing */
+{
+static char **tissueDescriptions = NULL;
+struct gtexTissue *tissue;
+int count = getTissueCount(version);
+if (!tissueDescriptions)
+    {
+    struct gtexTissue *tissues = getTissues(version);
+    AllocArray(tissueDescriptions, count);
+    for (tissue = tissues; tissue != NULL; tissue = tissue->next)
+        tissueDescriptions[tissue->id] = cloneString(tissue->description);
+    }
+if (id >= count)
+    errAbort("GTEx tissue table problem: can't find id %d\n", id);
+return tissueDescriptions[id];
+}
+
 struct rgbColor *getGtexTissueColors(char *version)
 /* Get RGB colors from tissue table */
 {
 struct gtexTissue *tissues = getTissues(version);
 struct gtexTissue *tissue = NULL;
 int count = slCount(tissues);
 struct rgbColor *colors;
 AllocArray(colors, count);
 int i = 0;
 for (tissue = tissues; tissue != NULL; tissue = tissue->next)
     {
     // TODO: reconcile 
     colors[i] = (struct rgbColor){.r=COLOR_32_BLUE(tissue->color), .g=COLOR_32_GREEN(tissue->color), .b=COLOR_32_RED(tissue->color)};
     //colors[i] = mgColorIxToRgb(NULL, tissue->color);
     i++;
@@ -276,33 +293,75 @@
 
 static int filteredTissueCount(struct track *tg)
 /* Count of tissues to display */
 {
 struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData;
 return hashNumEntries(extras->tissueFilter);
 }
 
 static boolean filterTissue(struct track *tg, char *name)
 /* Does tissue pass filter */
 {
 struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData;
 return (hashLookup(extras->tissueFilter, name) != NULL);
 }
 
+static int maxTissueForGene(struct gtexGeneBed *geneBed)
+/* Return id of highest expressed tissue for gene, if significantly higher than median.
+ * If none are over threshold, return -1 */
+{
+double maxScore = 0.0, expScore;
+double totalScore = 0.0;
+int maxNum = 0, i;
+int expCount = geneBed->expCount;
+for (i=0; i<expCount; i++)
+    {
+    expScore = geneBed->expScores[i];
+    if (expScore > maxScore)
+        {
+        maxScore = max(maxScore, expScore);
+        maxNum = i;
+        }
+    totalScore += expScore;
+    }
+// threshold to consider this gene tissue specific -- a tissue contributes > 10% to 
+// total expression level
+//uglyf("gene=%s maxScore=%0.2f totalScore=%0.2f ", geneBed->name, maxScore, totalScore);
+if (totalScore < 1 || maxScore <= totalScore * .1)
+    return -1;
+return maxNum;
+}
+
+static Color gtexGeneItemColor(struct track *tg, void *item, struct hvGfx *hvg)
+/* A bit of tissue-specific coloring in squish mode only, on geneBed item */
+{
+struct gtexGeneBed *geneBed = (struct gtexGeneBed *)item;
+int id = maxTissueForGene(geneBed);
+if (id < 0)
+    return MG_BLACK;
+struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData;
+//uglyf("COLOR maxNum=%d<br>", maxNum);
+struct rgbColor color = extras->colors[id];
+return hvGfxFindColorIx(hvg, color.r, color.g, color.b);
+}
+
 static void gtexGeneLoadItems(struct track *tg)
 /* Load method for track items */
 {
+if (tg->visibility == tvSquish || tg->limitedVis == tvSquish)
+    tg->itemColor = gtexGeneItemColor;
+
 /* Get track UI info */
 struct gtexGeneExtras *extras;
 AllocVar(extras);
 tg->extraUiData = extras;
 
 /* Get version info from track table name */
 extras->version = gtexVersionSuffix(tg->table);
 extras->doLogTransform = cartUsualBooleanClosestToHome(cart, tg->tdb, FALSE, GTEX_LOG_TRANSFORM, 
                                                 GTEX_LOG_TRANSFORM_DEFAULT);
 char *samples = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, 
                                                 GTEX_SAMPLES, GTEX_SAMPLES_DEFAULT);
 extras->graphType = cloneString(samples);
 if (sameString(samples, GTEX_SAMPLES_COMPARE_SEX))
     extras->isComparison = TRUE;
 char *comparison = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, GTEX_COMPARISON_DISPLAY,
@@ -540,34 +599,35 @@
     }
 double viewMax = (double)cartUsualIntClosestToHome(cart, tg->tdb, FALSE, 
                                 GTEX_MAX_LIMIT, GTEX_MAX_LIMIT_DEFAULT);
 double maxMedian = ((struct gtexGeneExtras *)tg->extraUiData)->maxMedian;
 return valToClippedHeight(maxExp, maxMedian, viewMax, gtexMaxGraphHeight(), extras->doLogTransform);
 }
 
 static void gtexGeneDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, 
                 double scale, MgFont *font, Color color, enum trackVisibility vis)
 /* Draw tissue expression bar graph over gene model. 
    Optionally, draw a second graph under gene, to compare sample sets */
 {
 struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData;
 struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item;
 struct gtexGeneBed *geneBed = geneInfo->geneBed;
-// Color in dense mode using geneClass
+// Color in squish mode using geneClass
 Color statusColor = getGeneClassColor(hvg, geneBed);
 if (vis != tvFull && vis != tvPack)
     {
+uglyf("<br>drawAt %s\n", geneBed->name);
     bedDrawSimpleAt(tg, geneBed, hvg, xOff, y, scale, font, statusColor, vis);
     return;
     }
 
 int heightPer = tg->heightPer;
 int graphX = gtexGraphX(geneBed);
 if (graphX < 0)
     return;
 
 // draw gene model
 int topGraphHeight = gtexGeneGraphHeight(tg, geneInfo, TRUE);
 topGraphHeight = max(topGraphHeight, tl.fontHeight);
 int yZero = topGraphHeight + y - 1;  // yZero is bottom of graph
 int yGene = yZero + gtexGeneMargin() - 1;
 tg->heightPer = gtexGeneModelHeight(extras) + 1;
@@ -684,31 +744,31 @@
                                         extras->doLogTransform);
     if (graphPadding == 0 || sameString(colorScheme, GTEX_COLORS_GTEX))
         hvGfxBox(hvg, x1, yZero, barWidth, height, fillColorIx);
     else
         hvGfxOutlinedBox(hvg, x1, yZero, barWidth, height, fillColorIx, lineColorIx);
     // mark clipped bar with magenta tip
     if (!extras->doLogTransform && expScore > viewMax)
         hvGfxBox(hvg, x1, yZero + height, barWidth, 1, clipColor);
     x1 = x1 + barWidth + graphPadding;
     }
 }
 
 static int gtexGeneItemHeightOptionalMax(struct track *tg, void *item, boolean isMax)
 {
 if (tg->visibility == tvSquish || tg->visibility == tvDense)
-    return 0;
+    return tgFixedItemHeight(tg, item);
 struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData;
 if (isMax)
     {
     int extra = 0;
     if (((struct gtexGeneExtras *)tg->extraUiData)->isComparison)
         extra = gtexMaxGraphHeight() + 2;
     return gtexMaxGraphHeight() + gtexGeneMargin() + gtexGeneModelHeight(extras) + extra;
     }
 if (item == NULL)
     return 0;
 struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item;
 
 if (geneInfo->height != 0)
     return geneInfo->height;
 int topGraphHeight = gtexGeneGraphHeight(tg, geneInfo, TRUE);
@@ -742,38 +802,49 @@
 {
 static char buf[128];
 safef(buf, sizeof(buf), "%s (%.1f %s%s%sRPKM)", tissue->description, 
                                 doLogTransform ? log10(expScore+1.0) : expScore,
                                 qualifier != NULL ? qualifier : "",
                                 qualifier != NULL ? " " : "",
                                 doLogTransform ? "log " : "");
 return buf;
 }
 
 static void gtexGeneMapItem(struct track *tg, struct hvGfx *hvg, void *item, char *itemName, 
                         char *mapItemName, int start, int end, int x, int y, int width, int height)
 /* Create a map box on gene model and label, and one for each tissue (bar in the graph) in
  * pack or full mode.  Just single map for squish/dense modes */
 {
-if (tg->visibility == tvDense || tg->visibility == tvSquish)
+if (tg->visibility == tvDense)
     {
     genericMapItem(tg, hvg, item, itemName, itemName, start, end, x, y, width, height);
     return;
     }
 struct gtexGeneInfo *geneInfo = item;
-struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData;
 struct gtexGeneBed *geneBed = geneInfo->geneBed;
+struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData;
+if (tg->visibility == tvSquish)
+    {
+    int tisId = maxTissueForGene(geneBed);
+    char *maxTissue = "";
+    if (tisId > 1)
+        maxTissue = getTissueDescription(tisId, extras->version);
+    char buf[128];
+    safef(buf, sizeof buf, "%s %s%s", geneBed->name, tisId > 0 ? "+":"", maxTissue);
+    mapBoxHc(hvg, start, end, x, y, width, height, tg->track, mapItemName, buf);
+    return;
+    }
 int topGraphHeight = gtexGeneGraphHeight(tg, geneInfo, TRUE);
 topGraphHeight = max(topGraphHeight, tl.fontHeight);        // label
 int yZero = topGraphHeight + y - 1;  // yZero is bottom of graph
 //int yGene = yZero + gtexGeneMargin() - 1;
 int x1 = insideX;
 
 
 // add maps to tissue bars in expresion graph
 struct gtexTissue *tissues = getTissues(extras->version);
 struct gtexTissue *tissue = NULL;
 int barWidth = gtexBarWidth();
 int padding = gtexGraphPadding();
 double maxMedian = ((struct gtexGeneExtras *)tg->extraUiData)->maxMedian;
 
 int graphX = gtexGraphX(geneBed);