d5c4d42b034674749ffbad338e76df5822e18ed6
kate
  Fri Jun 5 17:12:42 2015 -0700
First cut GTEX gene track display. refs #13504

diff --git src/hg/hgTracks/gtexTracks.c src/hg/hgTracks/gtexTracks.c
new file mode 100644
index 0000000..8e8bf07
--- /dev/null
+++ src/hg/hgTracks/gtexTracks.c
@@ -0,0 +1,177 @@
+/* GTEX 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 "hgTracks.h"
+#include "hvGfx.h"
+#include "rainbow.h"
+#include "gtexGeneBed.h"
+
+#define GRAPH_HEIGHT 100
+#define BAR_WIDTH 5
+#define MARGIN_WIDTH 1
+#define PADDING 2
+
+//#define GENCODE_CODING_COLOR 0x0c0c78    // rgb(12,12,120)
+//#define GENCODE_NONCODING_COLOR 0x006400 // rgb(0,100,0)
+//#define GENCODE_PROBLEM_COLOR 0xfe000  //rgb(254,0,0)  
+
+#define GENCODE_CODING_COLOR "12,12,120"
+#define GENCODE_NONCODING_COLOR "0,100,0"
+#define GENCODE_PROBLEM_COLOR "254,0,0"
+
+#define UNKNOWN_COLOR "1,1,1"
+
+static struct statusColors
+    {
+    Color coding;
+    Color nonCoding;
+    Color problem;
+    Color unknown;
+    } statusColors = {0,0,0};
+
+static int findColorIx(struct hvGfx *hvg, char *rgb)
+{
+unsigned char red, green, blue;
+parseColor(rgb, &red, &green, &blue);
+return (hvGfxFindColorIx(hvg, red, green, blue));
+//return MAKECOLOR_32(red, green, blue);
+}
+
+static void initGeneColors(struct hvGfx *hvg)
+{
+if (statusColors.coding != 0)
+    return;
+statusColors.coding = findColorIx(hvg, GENCODE_CODING_COLOR);
+statusColors.nonCoding = findColorIx(hvg, GENCODE_NONCODING_COLOR);
+statusColors.problem = findColorIx(hvg, GENCODE_PROBLEM_COLOR);
+statusColors.unknown = findColorIx(hvg, UNKNOWN_COLOR);
+}
+
+static int valToY(double val, double maxVal, int height)
+/* Convert a value from 0 to maxVal to 0 to height-1 */
+{
+double scaled = val/maxVal;
+int y = scaled * (height-1);
+return height - 1 - y;
+}
+
+struct gtexGeneExtras 
+    {
+    double maxExp;
+    };
+
+static void gtexGeneDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, 
+                    double scale, MgFont *font, Color color, enum trackVisibility vis)
+{
+struct gtexGeneBed *geneBed = item;
+//warn("item: %s, xOff=%d\n", geneBed->name, xOff);
+if (vis != tvFull && vis != tvPack)
+    {
+    initGeneColors(hvg);
+    // Color using transcriptClass
+    if (geneBed->transcriptClass == NULL)
+        color = statusColors.unknown;
+    if (sameString(geneBed->transcriptClass, "coding"))
+        color = statusColors.coding;
+    else if (sameString(geneBed->transcriptClass, "nonCoding"))
+        color = statusColors.nonCoding;
+    else if (sameString(geneBed->transcriptClass, "problem"))
+        color = statusColors.problem;
+    else 
+        color = statusColors.unknown;
+
+    bedDrawSimpleAt(tg, item, hvg, xOff, y, scale, font, color, vis);
+    return;
+    }
+int i;
+int expCount = geneBed->expCount;
+double invExpCount = 1.0/expCount;
+double maxExp = ((struct gtexGeneExtras *)tg->extraUiData)->maxExp;
+struct rgbColor lineColor = {.r=0};
+int lineColorIx = hvGfxFindColorIx(hvg, lineColor.r, lineColor.g, lineColor.b);
+int heightPer = tg->heightPer;
+
+int start = max(geneBed->chromStart, winStart);
+//int geneEnd = min(geneBed->chromEnd, winEnd);
+//int width = expCount * (BAR_WIDTH + PADDING);
+//int end = min(expCount*(BAR_WIDTH + PADDING), winEnd);
+//if (start > end)
+    //return;
+int x1 = round((start-winStart)*scale) + xOff;
+//int x2 = round((e-winStart)*scale) + xOff;
+
+int yBase = valToY(0, maxExp, heightPer) + y;
+//int yZero = yBase - 5;
+
+//int firstX = x1;
+for (i=0; i<expCount; i++)
+    {
+    double colPos = invExpCount * i;
+    struct rgbColor fillColor = saturatedRainbowAtPos(colPos);
+    int fillColorIx = hvGfxFindColorIx(hvg, fillColor.r, fillColor.g, fillColor.b);
+    double expScore = geneBed->expScores[i];
+    int yMedian = valToY(expScore, maxExp, heightPer) + y;
+    hvGfxOutlinedBox(hvg, x1, yMedian, BAR_WIDTH, yBase - yMedian, fillColorIx, lineColorIx);
+    //warn("x1=%d, yMedian=%d, height=%d\n", x1, yMedian, yBase-yMedian);
+    x1 = x1 + BAR_WIDTH + PADDING;
+    }
+// underline gene extent
+//hvGfxBox(hvg, firstX, yBase, round((geneEnd - start)*scale), 3, lineColorIx);
+
+// TODO: replace with cached table hash
+//char *tissueTable = "gtexTissue";
+//struct sqlConnection *conn = hAllocConn("hgFixed");
+//hFreeConn(&conn);
+}
+
+static struct gtexGeneBed *loadGtexGeneBed(char **row)
+{
+return gtexGeneBedLoad(row);
+}
+
+static void gtexGeneLoadItems(struct track *track)
+{
+bedLoadItem(track, track->table, (ItemLoader)loadGtexGeneBed);
+double maxExp = 0.0;
+int i;
+struct gtexGeneBed *geneBed;
+for (geneBed = track->items; geneBed != NULL; geneBed = geneBed->next)
+    for (i=0; i<geneBed->expCount; i++)
+        maxExp = (geneBed->expScores[i] > maxExp ? geneBed->expScores[i] : maxExp);
+struct gtexGeneExtras *extras;
+AllocVar(extras);
+extras->maxExp = maxExp;
+track->extraUiData = extras;
+}
+
+static int gtexGeneItemHeight(struct track *track, void *item)
+{
+if ((item == NULL) || (track->visibility == tvSquish) || (track->visibility == tvDense))
+    return 0;
+return GRAPH_HEIGHT;
+}
+
+static int gtexTotalHeight(struct track *track, enum trackVisibility vis)
+/* Figure out total height of track */
+{
+int height;
+if (track->visibility == tvSquish || track->visibility == tvDense)
+    height = 10;
+else 
+    height = GRAPH_HEIGHT;
+return tgFixedTotalHeightOptionalOverflow(track, vis, height, height, FALSE);
+}
+
+void gtexGeneMethods(struct track *track)
+{
+track->drawItemAt = gtexGeneDrawAt;
+track->loadItems = gtexGeneLoadItems;
+track->itemHeight = gtexGeneItemHeight;
+track->totalHeight = gtexTotalHeight;
+}
+
+
+