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;