82b5f25235a46f41c6bf0d9925a12dd1da742af8 kate Wed Aug 26 11:12:34 2015 -0700 Ifdef'ed in Galt's support for multi-region display, so continuing development can consider it. refs #15645 diff --git src/hg/hgTracks/gtexTracks.c src/hg/hgTracks/gtexTracks.c index 4bbeda5..9cabf3a 100644 --- src/hg/hgTracks/gtexTracks.c +++ src/hg/hgTracks/gtexTracks.c @@ -90,53 +90,66 @@ { initGeneColors(hvg); if (geneBed->transcriptClass == NULL) return statusColors.unknown; if (sameString(geneBed->transcriptClass, "coding")) return statusColors.coding; if (sameString(geneBed->transcriptClass, "nonCoding")) return statusColors.nonCoding; if (sameString(geneBed->transcriptClass, "problem")) return statusColors.problem; return statusColors.unknown; } static int gtexBarWidth() { +#ifdef MULTI_REGION +int winSize = virtWinBaseCount; // GALT CHANGED OLD winEnd - winStart; +#else int winSize = winEnd - winStart; +#endif if (winSize < WIN_MAX_GRAPH) return MAX_BAR_WIDTH; else if (winSize < WIN_MED_GRAPH) return MED_BAR_WIDTH; else return MIN_BAR_WIDTH; } static int gtexGraphPadding() { +#ifdef MULTI_REGION +int winSize = virtWinBaseCount; // GALT CHANGED OLD winEnd - winStart; +#else int winSize = winEnd - winStart; +#endif + if (winSize < WIN_MAX_GRAPH) return MAX_GRAPH_PADDING; else if (winSize < WIN_MED_GRAPH) return MED_GRAPH_PADDING; else return MIN_GRAPH_PADDING; } static int gtexGraphHeight() { +#ifdef MULTI_REGION +int winSize = virtWinBaseCount; // GALT CHANGED OLD winEnd - winStart; +#else int winSize = winEnd - winStart; +#endif 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 gtexGeneInfo *geneInfo) /* Width of GTEx graph in pixels */ { int barWidth = gtexBarWidth(); int padding = gtexGraphPadding(); struct gtexGeneBed *geneBed = geneInfo->geneBed; int count = geneBed->expCount; @@ -270,31 +283,31 @@ 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]; char **row; - sqlSafef(query, sizeof(query), "select gtexSampleData.sample, gtexDonor.gender, gtexSampleData.tissue, gtexSampleData.score from gtexSampleData, gtexSample, gtexDonor where gtexSampleData.geneId='%s' and gtexSampleData.sample=gtexSample.name and gtexSample.donor=gtexDonor.name", geneBed->geneId); + sqlSafef(query, sizeof(query), "select gtexSampleData.sample, gtexDonor.gender, gtexSampleData.tissue, gtexSampleData.score from gtexSampleData, gtexSample, gtexDonor where gtexSampleData.geneId='%s' and gtexSampleData.sample=gtexSample.sampleId and gtexSample.donor=gtexDonor.name", geneBed->geneId); struct sqlResult *sr = sqlGetResult(conn, query); while ((row = sqlNextRow(sr)) != NULL) { char gender = *row[1]; struct hash *scoreHash = ((gender == 'F') ? scoreHash1 : scoreHash2); char *tissue = cloneString(row[2]); struct slDouble *score = slDoubleNew(sqlDouble(row[3])); // create hash of lists of scores, keyed by tissue name double *tissueScores = hashFindVal(scoreHash, tissue); if (tissueScores) slAddHead(tissueScores, score); else hashAdd(scoreHash, tissue, score); } @@ -357,30 +370,31 @@ extras->graphType = cloneString(graphType); if (sameString(graphType, GTEX_GRAPH_AGE) || sameString(graphType, GTEX_GRAPH_SEX)) extras->isComparison = TRUE; extras->maxMedian = gtexMaxMedianScore(NULL); // Construct track items // Get geneModels in range //TODO: version the table name ? char *modelTable = "gtexGeneModel"; struct hash *modelHash = loadGeneModels(modelTable); // Get geneBeds (names and all-sample tissue median scores) in range bedLoadItem(tg, tg->table, (ItemLoader)gtexGeneBedLoad); +uglyf("Loaded %d gtexGene items<BR>\n", slCount(tg->items)); // Create geneInfo items with BED and geneModels attached struct gtexGeneInfo *geneInfo = NULL, *list = NULL; struct gtexGeneBed *geneBed = (struct gtexGeneBed *)tg->items; char *colorScheme = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, GTEX_COLORS, GTEX_COLORS_DEFAULT); if (sameString(colorScheme, GTEX_COLORS_GTEX)) { // retrieve from table extras->colors = getGtexTissueColors(); } else { // currently the only other choice @@ -412,113 +426,275 @@ Color statusColor = getTranscriptStatusColor(hvg, geneBed); if (vis != tvFull && vis != tvPack) { bedDrawSimpleAt(tg, geneBed, hvg, xOff, y, scale, font, statusColor, vis); return; } struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData; if ((extras->isComparison) && (tg->visibility == tvFull || tg->visibility == tvPack)) //&& gtexGraphHeight() != MIN_GRAPH_HEIGHT) { // compute medians based on configuration (comparisons, and later, filters) loadComputedMedians(geneInfo, extras); } +int heightPer = tg->heightPer; + +int graphX = gtexGraphX(geneBed); +if (graphX < 0) + return; + +// 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) + +//uglyf("DRAW: xOff=%d, x1=%d, y=%d, yZero=%d<br>", xOff, x1, y, yZero); + +#ifndef MULTI_REGION +// x1 is at left of graph +int x1 = xOff + graphX; +int startX = x1; +Color lightGray = MAKECOLOR_32(0xD1, 0xD1, 0xD1); +int graphWidth = gtexGraphWidth(geneInfo); +hvGfxBox(hvg, x1, yZero+1, graphWidth, 1, lightGray); + + int i; int expCount = geneBed->expCount; double maxMedian = ((struct gtexGeneExtras *)tg->extraUiData)->maxMedian; + struct rgbColor lineColor = {.r=0}; int lineColorIx = hvGfxFindColorIx(hvg, lineColor.r, lineColor.g, lineColor.b); -int heightPer = tg->heightPer; + + +int barWidth = gtexBarWidth(); +int graphPadding = gtexGraphPadding(); + +char *colorScheme = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, GTEX_COLORS, + GTEX_COLORS_DEFAULT); + +Color labelColor = MG_GRAY; + +// TODO: 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; + */ + int height = valToHeight(expScore, maxMedian, gtexGraphHeight()); + // TODO: adjust yGene to get gene track distance as desired + //if (i ==0) uglyf("DRAW: expScore=%.2f, maxMedian=%.2f, graphHeight=%d, y=%d<br>", expScore, maxMedian, gtexGraphHeight(), y); + //if (i ==0) uglyf("DRAW: yZero=%d, yMedian=%d, height=%d<br>", yZero, yMedian, height); + if (graphPadding == 0 || sameString(colorScheme, GTEX_COLORS_GTEX)) + hvGfxBox(hvg, x1, yZero-height, barWidth, height, fillColorIx); + else + hvGfxOutlinedBox(hvg, x1, yZero-height, barWidth, height, fillColorIx, lineColorIx); + x1 = x1 + barWidth + graphPadding; + } +#endif + +// mark gene extent +int yGene = yZero + gtexGeneMargin() - 1; + +// draw gene model +tg->heightPer = gtexGeneHeight()+1; +struct linkedFeatures *lf = linkedFeaturesFromGenePred(tg, geneInfo->geneModel, FALSE); +lf->filterColor = statusColor; +linkedFeaturesDrawAt(tg, lf, hvg, xOff, yGene, scale, font, color, tvSquish); +tg->heightPer = heightPer; + +if (!geneInfo->medians2) + return; + +#ifndef MULTI_REGION +// draw comparison graph (upside down) + +x1 = startX; +// yZero is at top of graph +yZero = yGene + gtexGeneHeight(); +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 + struct hslColor hsl = mgRgbToHsl(fillColor); + hsl.s = min(1000, hsl.s + 300); + fillColor = mgHslToRgb(hsl); + } + int fillColorIx = hvGfxFindColorIx(hvg, fillColor.r, fillColor.g, fillColor.b); + //double expScore = geneBed->expScores[i]; + double expScore = geneInfo->medians2[i]; + //if (expScore < 1) + //expScore = 0.0; + int height = valToHeight(expScore, maxMedian, gtexGraphHeight()); + // TODO: adjust yGene instead of yMedian+1 to get gene track distance as desired + //if (i ==0) uglyf("DRAW2: expScore=%.2f, maxMedian=%.2f, graphHeight=%d, y=%d<br>", expScore, maxMedian, gtexGraphHeight(), y); + //if (i ==0) uglyf("DRAW2: yZero=%d, height=%d<br>", yZero, height); + if (graphPadding == 0 || sameString(colorScheme, GTEX_COLORS_GTEX)) + hvGfxBox(hvg, x1, yZero, barWidth, height, fillColorIx); + else + hvGfxOutlinedBox(hvg, x1, yZero, barWidth, height, fillColorIx, lineColorIx); + x1 = x1 + barWidth + graphPadding; + } +#endif +} + +#ifdef MULTI_REGION +static int gtexGeneNonPropPixelWidth(struct track *tg, void *item) +/* Return end chromosome coordinate of item, including graph */ +{ +struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item; +int graphWidth = gtexGraphWidth(geneInfo); +return graphWidth; +} +#endif + +#ifdef MULTI_REGION +static void gtexGeneNonPropDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, + double scale, MgFont *font, Color color, enum trackVisibility vis) +{ +struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item; +struct gtexGeneBed *geneBed = geneInfo->geneBed; + +// Color in dense mode using transcriptClass +// GALT REMOVE Color statusColor = getTranscriptStatusColor(hvg, geneBed); +if (vis != tvFull && vis != tvPack) + { + //GALT bedDrawSimpleAt(tg, geneBed, hvg, xOff, y, scale, font, statusColor, vis); + return; + } + +struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData; +if ((extras->isComparison) && + (tg->visibility == tvFull || tg->visibility == tvPack)) + //&& gtexGraphHeight() != MIN_GRAPH_HEIGHT) + { + // compute medians based on configuration (comparisons, and later, filters) + loadComputedMedians(geneInfo, extras); + } +int i; +int expCount = geneBed->expCount; +double maxMedian = ((struct gtexGeneExtras *)tg->extraUiData)->maxMedian; +struct rgbColor lineColor = {.r=0}; +int lineColorIx = hvGfxFindColorIx(hvg, lineColor.r, lineColor.g, lineColor.b); +// GALT REMOVE 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(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(); char *colorScheme = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, GTEX_COLORS, GTEX_COLORS_DEFAULT); Color labelColor = MG_GRAY; -// TOD: generalize +// TODO: 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; */ int height = valToHeight(expScore, maxMedian, gtexGraphHeight()); // TODO: adjust yGene to get gene track distance as desired //if (i ==0) uglyf("DRAW: expScore=%.2f, maxMedian=%.2f, graphHeight=%d, y=%d<br>", expScore, maxMedian, gtexGraphHeight(), y); //if (i ==0) uglyf("DRAW: yZero=%d, yMedian=%d, height=%d<br>", yZero, yMedian, height); if (graphPadding == 0 || sameString(colorScheme, GTEX_COLORS_GTEX)) hvGfxBox(hvg, x1, yZero-height, barWidth, height, fillColorIx); else hvGfxOutlinedBox(hvg, x1, yZero-height, barWidth, height, fillColorIx, lineColorIx); x1 = x1 + barWidth + graphPadding; } // mark gene extent int yGene = yZero + gtexGeneMargin() - 1; - +/* GALT NOT DONE HERE NOW // draw gene model tg->heightPer = gtexGeneHeight()+1; struct linkedFeatures *lf = linkedFeaturesFromGenePred(tg, geneInfo->geneModel, FALSE); lf->filterColor = statusColor; -linkedFeaturesDrawAt(tg, lf, hvg, xOff, yGene, scale, font, color, tvSquish); +// GALT linkedFeaturesDrawAt(tg, lf, hvg, xOff, yGene, scale, font, color, tvSquish); tg->heightPer = heightPer; +*/ if (!geneInfo->medians2) return; // draw comparison graph (upside down) x1 = startX; // yZero is at top of graph yZero = yGene + gtexGeneHeight(); 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 @@ -529,31 +705,35 @@ int fillColorIx = hvGfxFindColorIx(hvg, fillColor.r, fillColor.g, fillColor.b); //double expScore = geneBed->expScores[i]; double expScore = geneInfo->medians2[i]; //if (expScore < 1) //expScore = 0.0; int height = valToHeight(expScore, maxMedian, gtexGraphHeight()); // TODO: adjust yGene instead of yMedian+1 to get gene track distance as desired //if (i ==0) uglyf("DRAW2: expScore=%.2f, maxMedian=%.2f, graphHeight=%d, y=%d<br>", expScore, maxMedian, gtexGraphHeight(), y); //if (i ==0) uglyf("DRAW2: yZero=%d, height=%d<br>", yZero, height); if (graphPadding == 0 || sameString(colorScheme, GTEX_COLORS_GTEX)) hvGfxBox(hvg, x1, yZero, barWidth, height, fillColorIx); else hvGfxOutlinedBox(hvg, x1, yZero, barWidth, height, fillColorIx, lineColorIx); x1 = x1 + barWidth + graphPadding; } + } +#endif + + 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 for each tissue (bar in the graph) or a single map for squish/dense modes */ { //uglyf("map item: itemName=%s, mapItemName=%s, start=%d, end=%d, x=%d, y=%d, width=%d, height=%d, insideX=%d<br>", //itemName, mapItemName, start, end, x, y, width, height, insideX); if (tg->visibility == tvDense || tg->visibility == tvSquish) { genericMapItem(tg, hvg, item, itemName, itemName, start, end, x, y, width, height); return; } struct gtexTissue *tissues = getTissues(); @@ -673,19 +853,24 @@ } 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; tg->totalHeight = gtexTotalHeight; + +#ifdef MULTI_REGION +tg->nonPropDrawItemAt = gtexGeneNonPropDrawAt; +tg->nonPropPixelWidth = gtexGeneNonPropPixelWidth; +#endif }