a967b2c1ba57376fa4b4a9587839e2c7e90801fe kate Thu Aug 6 09:52:33 2015 -0700 Add labels (e.g. M/F) to comparison graphs. refs #15645 diff --git src/hg/hgTracks/gtexTracks.c src/hg/hgTracks/gtexTracks.c index db78a5f..4bbeda5 100644 --- src/hg/hgTracks/gtexTracks.c +++ src/hg/hgTracks/gtexTracks.c @@ -35,30 +35,50 @@ #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}; +struct gtexGeneExtras +/* Track info */ + { + double maxMedian; + char *graphType; + boolean isComparison; + struct rgbColor *colors; + }; + +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 */ + double *medians1; /* Computed medians */ + double *medians2; /* Computed medians for comparison (inverse) graph */ + }; + 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); @@ -101,37 +121,41 @@ else return MIN_GRAPH_PADDING; } static int gtexGraphHeight() { int winSize = winEnd - winStart; if (winSize < WIN_MAX_GRAPH) return MAX_GRAPH_HEIGHT; else if (winSize < WIN_MED_GRAPH) return MED_GRAPH_HEIGHT; else return MIN_GRAPH_HEIGHT; } -static int gtexGraphWidth(struct gtexGeneBed *gtex) +static int gtexGraphWidth(struct gtexGeneInfo *geneInfo) /* Width of GTEx graph in pixels */ { int barWidth = gtexBarWidth(); int padding = gtexGraphPadding(); -int count = gtex->expCount; -return (barWidth * count) + (padding * (count-1)); +struct gtexGeneBed *geneBed = geneInfo->geneBed; +int count = geneBed->expCount; +// TODO: save labels in extras +int labelWidth = geneInfo->medians2 ? 5 : 0; +return (barWidth * count) + (padding * (count-1)) + labelWidth + 2; +; } static int valToHeight(double val, double maxVal, int maxHeight) /* Log-scale and Convert a value from 0 to maxVal to 0 to maxHeight-1 */ // TODO: support linear or log scale { if (val == 0.0) return 0; // smallest counts are 1x10e-3, translate to counter negativity //double scaled = (log10(val) + 3.001)/(log10(maxVal) + 3.001); double scaled = log10(val+1.0) / log10(maxVal+1.0); if (scaled < 0) warn("scaled=%f\n", scaled); //uglyf("%.2f -> %.2f height %d", val, scaled, (int)scaled * (maxHeight-1)); @@ -230,50 +254,30 @@ return x1; } static int gtexGeneHeight() { return 8; } static int gtexGeneMargin() { return 1; } /* Track info generated during load, used by draw */ -struct gtexGeneExtras -/* Track info */ - { - double maxMedian; - char *graphType; - boolean isComparison; - struct rgbColor *colors; - }; - -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 */ - double *medians1; /* Computed medians */ - double *medians2; /* Computed medians for comparison (inverse) graph */ - }; - static void loadComputedMedians(struct gtexGeneInfo *geneInfo, struct gtexGeneExtras *extras) /* Compute medians based on graph type. Returns a list of 2 for comparison graph types */ /* TODO: add support for filter function */ { struct gtexGeneBed *geneBed = geneInfo->geneBed; int expCount = geneBed->expCount; //char *graphType = extras->graphType; if (extras->isComparison) { // create two score hashes, one for each sample subset struct hash *scoreHash1 = hashNew(0), *scoreHash2 = hashNew(0); struct sqlConnection *conn = hAllocConn("hgFixed"); char query[1024]; @@ -428,41 +432,56 @@ int heightPer = tg->heightPer; int graphX = gtexGraphX(geneBed); if (graphX < 0) return; // x1 is at left of graph int x1 = xOff + graphX; int startX = x1; // yZero is at bottom of graph int yZero = gtexGraphHeight() + y - 1; // draw faint line under graph to delineate extent when bars are missing (tissue w/ 0 expression) // TODO: skip missing bars -- then we can lose the gray line (at least for non-comparison mode) Color lightGray = MAKECOLOR_32(0xD1, 0xD1, 0xD1); -int graphWidth = gtexGraphWidth(geneBed); +int graphWidth = gtexGraphWidth(geneInfo); hvGfxBox(hvg, x1, yZero+1, graphWidth, 1, lightGray); //uglyf("DRAW: xOff=%d, x1=%d, y=%d, yZero=%d<br>", xOff, x1, y, yZero); int barWidth = gtexBarWidth(); int graphPadding = gtexGraphPadding(); -// Move to loader char *colorScheme = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, GTEX_COLORS, GTEX_COLORS_DEFAULT); + +Color labelColor = MG_GRAY; + +// TOD: generalize +if (geneInfo->medians2) + { + // add labels to comparison graphs + //FIXME: compute these + int charHeight = 5; + int labelWidth = 5; + hvGfxText(hvg, x1, yZero-charHeight, labelColor, font, "F"); + hvGfxText(hvg, x1, yZero + gtexGeneHeight() + gtexGeneMargin(), labelColor, font, "M"); + startX = startX + labelWidth + 2; + x1 = startX; + } + for (i=0; i<expCount; i++) { struct rgbColor fillColor = extras->colors[i]; if (barWidth == 1 && sameString(colorScheme, GTEX_COLORS_GTEX)) { // brighten colors a bit so they'll be more visible at this scale fillColor = gtexTissueBrightenColor(fillColor); } int fillColorIx = hvGfxFindColorIx(hvg, fillColor.r, fillColor.g, fillColor.b); double expScore = (geneInfo->medians1 ? geneInfo->medians1[i] : geneBed->expScores[i]); //double expScore = geneBed->expScores[i]; /* if (expScore < 1) expScore = 0.0; @@ -539,30 +558,38 @@ struct gtexTissue *tissues = getTissues(); struct gtexTissue *tissue = NULL; struct gtexGeneInfo *geneInfo = item; struct gtexGeneBed *geneBed = geneInfo->geneBed; 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 int x1 = insideX + graphX; +if (geneInfo->medians2) + { + // add labels to comparison graphs + //FIXME: compute these + int labelWidth = 5; + x1 = x1 + labelWidth + 2; + } + int i = 0; int yZero = gtexGraphHeight() + y - 1; for (tissue = tissues; tissue != NULL; tissue = tissue->next, i++) { double expScore = geneBed->expScores[i]; //TODO: use valToHeight int yMedian = valToY(expScore, maxMedian, gtexGraphHeight()) + y; int height = yZero - yMedian; // TODO: call genericMapItem //genericMapItem(tg, hvg, item, itemName, tissue->description, start, end, x1, y, barWidth, height); mapBoxHc(hvg, start, end, x1, yMedian+1, barWidth, height, tg->track, mapItemName, tissue->description); //if (i==0) uglyf("MAP: expScore=%.2f, maxMedian=%.2f, graphHeight=%d, y=%d<br>", expScore, maxMedian, gtexGraphHeight(), y); //if (i==0) uglyf("MAP: x=%d, x1=%d, y=%d, yZero=%d<br>", x, x1, y, yZero); //if (i==0) uglyf("MAP: yZero=%d, yMedian=%d, height=%d<br>", yZero, yMedian, height); x1 = x1 + barWidth + padding; @@ -629,31 +656,31 @@ static int gtexGeneItemStart(struct track *tg, void *item) /* Return end chromosome coordinate of item, including graph */ { struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item; struct gtexGeneBed *geneBed = geneInfo->geneBed; return geneBed->chromStart; } static int gtexGeneItemEnd(struct track *tg, void *item) /* Return end chromosome coordinate of item, including graph */ { struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item; struct gtexGeneBed *geneBed = geneInfo->geneBed; double scale = scaleForWindow(insideWidth, winStart, winEnd); -int graphWidth = gtexGraphWidth(geneBed); +int graphWidth = gtexGraphWidth(geneInfo); return max(geneBed->chromEnd, max(winStart, geneBed->chromStart) + graphWidth/scale); } void gtexGeneMethods(struct track *tg) { tg->drawItemAt = gtexGeneDrawAt; tg->loadItems = gtexGeneLoadItems; //tg->freeItems = gtexGeneFreeItems; tg->mapItem = gtexGeneMapItem; tg->itemName = gtexGeneItemName; tg->mapItemName = gtexGeneItemName; tg->itemHeight = gtexGeneItemHeight; tg->itemStart = gtexGeneItemStart; tg->itemEnd = gtexGeneItemEnd;