1b04ae4a7eb27583b67ecc7b2215cb54c5824826
kate
  Tue Mar 8 17:21:11 2016 -0800
Fixes to mouseover on gene model and label so gene description is displayed properly. refs #15645

diff --git src/hg/hgTracks/gtexTracks.c src/hg/hgTracks/gtexTracks.c
index 39a495f..38b6ee6 100644
--- src/hg/hgTracks/gtexTracks.c
+++ src/hg/hgTracks/gtexTracks.c
@@ -24,35 +24,37 @@
                                    False if displayed as two graphs, one oriented downward */
     char *graphType;            /* Additional info about graph (e.g. type of comparison graph */
     struct rgbColor *colors;    /* Color palette for tissues */
     boolean doLogTransform;     /* Log10(x+1) */
     struct gtexTissue *tissues; /* Cache tissue names, descriptions */
     struct hash *tissueFilter;  /* For filter. NULL out excluded tissues */
     };
 
 struct gtexGeneInfo
 /* GTEx gene model, names, and expression medians */
     {
     struct gtexGeneInfo *next;  /* Next in singly linked list */
     struct gtexGeneBed *geneBed;/* Gene name, id, canonical transcript, exp count and medians 
                                         from BED table */
     struct genePred *geneModel; /* Gene structure from model table */
+    char *description;          /* Gene description */
     double *medians1;            /* Computed medians */
     double *medians2;            /* Computed medians for comparison (inverse) graph */
     int height;                  /* Item height in pixels */
     };
 
+#define MAX_DESC  200
 /***********************************************/
 /* Color gene models using GENCODE conventions */
 
 static struct rgbColor codingColor = {12, 12, 120}; // #0C0C78
 static struct rgbColor noncodingColor = {0, 100, 0}; // #006400
 static struct rgbColor pseudoColor = {255,51,255}; // #FF33FF
 static struct rgbColor problemColor = {254, 0, 0}; // #FE0000
 static struct rgbColor unknownColor = {1, 1, 1};
 
 static struct statusColors
 /* Color values for gene models */
     {
     Color coding;
     Color noncoding;
     Color pseudo;
@@ -333,30 +335,45 @@
 else
     {
     if (geneBed)
 	{
 	int expCount = geneBed->expCount;
 	extras->colors = getRainbow(&saturatedRainbowAtPos, expCount);
 	}
     }
 filterTissues(tg);
 
 while (geneBed != NULL)
     {
     AllocVar(geneInfo);
     geneInfo->geneBed = geneBed;
     geneInfo->geneModel = hashFindVal(modelHash, geneBed->geneId); // sometimes this is missing, hash returns NULL. do we check?
+    // NOTE: Consider loading all gene descriptions to save queries
+    char query[256];
+    sqlSafef(query, sizeof(query),
+            "select kgXref.description from kgXref where geneSymbol='%s'", geneBed->name);
+    struct sqlConnection *conn = hAllocConn(database);
+    char *desc = sqlQuickString(conn, query);
+    hFreeConn(&conn);
+    if (desc)
+        {
+        char *fromDetail = strstrNoCase(desc, "(from");
+        *fromDetail = 0;
+        if (strlen(desc) > MAX_DESC)
+            strcpy(desc+MAX_DESC, "...");
+        geneInfo->description = desc;
+        }
     slAddHead(&list, geneInfo);
     geneBed = geneBed->next;
     geneInfo->geneBed->next = NULL;
     if (extras->isComparison && (tg->visibility == tvFull || tg->visibility == tvPack))
         // compute medians based on configuration (comparisons, and later, filters)
         loadComputedMedians(geneInfo, extras);
     geneInfo->height = gtexGeneItemHeight(tg, geneInfo);
     }
 slReverse(&list);
 tg->items = list;
 }
 
 /***********************************************/
 /* Draw */
 
@@ -710,60 +727,46 @@
                                         boolean doLogTransform, char *qualifier)
 /* Construct mouseover text for tissue graph */
 {
 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 ful modes.  Just single map for squish/dense modes */
+ * pack or full mode.  Just single map for squish/dense modes */
 {
 if (tg->visibility == tvDense || tg->visibility == tvSquish)
     {
     genericMapItem(tg, hvg, item, itemName, itemName, start, end, x, y, width, height);
     return;
     }
-// add map boxes to gene model and label
 struct gtexGeneInfo *geneInfo = item;
 struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData;
 struct gtexGeneBed *geneBed = geneInfo->geneBed;
 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;
-if (!geneInfo->geneModel)
-    return;
-int geneStart = max(geneInfo->geneModel->txStart, winStart);
-int geneEnd = min(geneInfo->geneModel->txEnd, winEnd);
-double scale = scaleForWindow(insideWidth, winStart, winEnd);
-int x1 = round((double)((int)geneStart-winStart)*scale) + x;
-int x2 = round((double)((int)geneEnd-winStart)*scale) + x;
-int w = x2-x1;
-char query[256];
-sqlSafef(query, sizeof(query),
-        "select kgXref.description from kgXref, knownToEnsembl where knownToEnsembl.value='%s' and knownToEnsembl.name=kgXref.kgID", geneBed->transcriptId);
-struct sqlConnection *conn = hAllocConn(database);
-char *desc = sqlQuickString(conn, query);
-hFreeConn(&conn);
-mapBoxHc(hvg, start, end, x, yGene, w, gtexGeneModelHeight(extras)-1, tg->track, mapItemName, desc);
+//int yGene = yZero + gtexGeneMargin() - 1;
+int x1 = insideX;
+
 
 // add maps to tissue bars in expresion graph
 struct gtexTissue *tissues = getTissues();
 struct gtexTissue *tissue = NULL;
 int barWidth = gtexBarWidth();
 int padding = gtexGraphPadding();
 double maxMedian = ((struct gtexGeneExtras *)tg->extraUiData)->maxMedian;
 
 int graphX = gtexGraphX(geneBed);
 if (graphX < 0)
     return;
 
 // x1 is at left of graph
 x1 = insideX + graphX;
 
@@ -790,30 +793,47 @@
                 tissueExpressionText(tissue, expScore, extras->doLogTransform, qualifier));
     // add map box to comparison graph
     if (geneInfo->medians2)
         {
         double expScore = geneInfo->medians2[i];
         int height = valToClippedHeight(expScore, maxMedian, viewMax, 
                                         gtexMaxGraphHeight(), extras->doLogTransform);
         int y = yZero + gtexGeneModelHeight(extras) + gtexGeneMargin();  // y is top of bottom graph
         if (extras->isComparison && extras->isDifference)
             qualifier = "M-F";
         mapBoxHc(hvg, start, end, x1, y, barWidth, height, tg->track, mapItemName,
                 tissueExpressionText(tissue, expScore, extras->doLogTransform, qualifier));
         }
     x1 = x1 + barWidth + padding;
     }
+
+// add map box with description to gene model
+// NOTE: this is "under" the tissue map boxes
+if (geneInfo->geneModel && geneInfo->description)
+    {
+    double scale = scaleForWindow(insideWidth, winStart, winEnd);
+    int geneStart = max(geneInfo->geneModel->txStart, winStart);
+    int geneEnd = min(geneInfo->geneModel->txEnd, winEnd);
+    int geneX = round((geneStart-winStart)*scale);
+    int w = round((geneEnd-winStart)*scale) - geneX;
+    x1 = insideX + geneX;
+    int labelWidth = mgFontStringWidth(tl.font, itemName);
+    if (x1-labelWidth <= insideX)
+        labelWidth = 0;
+    mapBoxHc(hvg, start, end, x1-labelWidth, y, w+labelWidth, geneInfo->height, tg->track, 
+                    mapItemName, geneInfo->description);
+    }
 }
 
 static char *gtexGeneItemName(struct track *tg, void *item)
 /* Return gene name */
 {
 struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item;
 struct gtexGeneBed *geneBed = geneInfo->geneBed;
 return geneBed->name;
 }
 
 static int gtexGeneHeight(void *item)
 {
 struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item;
 assert(geneInfo->height != 0);
 return geneInfo->height;