b6423d340bcb5cba9d614545354c6775a680a983 kate Mon Apr 4 12:39:36 2016 -0700 Fine-tuning map boxes for gene models. Now there is one for the label and one for the gene model, which extends to the end of the item (JK request for this latter). refs #15645 diff --git src/hg/hgTracks/gtexTracks.c src/hg/hgTracks/gtexTracks.c index 9a31a53..05ea801 100644 --- src/hg/hgTracks/gtexTracks.c +++ src/hg/hgTracks/gtexTracks.c @@ -452,30 +452,32 @@ hFreeConn(&conn); if (desc) { // hg38 known genes has extra detail about source; strip it char *fromDetail = strstrNoCase(desc, "(from"); if (fromDetail) *fromDetail = 0; if (strlen(desc) > MAX_DESC) strcpy(desc+MAX_DESC, "..."); // also strip 'homo sapiens' prefix #define SPECIES_PREFIX "Homo sapiens " if (startsWith(SPECIES_PREFIX, desc)) desc += strlen(SPECIES_PREFIX); geneInfo->description = desc; } + else + geneInfo->description = geneInfo->geneBed->name; 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 */ @@ -636,86 +638,73 @@ { Color lighterGray = MAKECOLOR_32(0xF3, 0xF3, 0xF3); int width = gtexGraphWidth(tg, geneInfo); int height = gtexGeneGraphHeight(tg, geneInfo, TRUE); hvGfxOutlinedBox(hvg, x, y-height, width, height, MG_WHITE, lighterGray); } static void drawGraphBase(struct track *tg, struct gtexGeneInfo *geneInfo, struct hvGfx *hvg, int x, int y) /* Draw faint line under graph to delineate extent when bars are missing (tissue w/ 0 expression) */ { Color lightGray = MAKECOLOR_32(0xD1, 0xD1, 0xD1); int graphWidth = gtexGraphWidth(tg, geneInfo); hvGfxBox(hvg, x, y, graphWidth, 1, lightGray); } -static void getItemX(int start, int end, int *x1, int *x2) -/* Return startX, endX based on item coordinates and current window */ -// TODO: Should be using simpleTracks.c scaledBoxToPixelCoords -{ -int s = max(start, winStart); -int e = min(end, winEnd); -double scale = scaleForWindow(insideWidth, winStart, winEnd); -assert(x1); -*x1 = round((double)((int)s-winStart)*scale + insideX); -assert(x2); -*x2 = round((double)((int)e-winStart)*scale + insideX); -} - static void gtexGeneDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) /* Draw tissue expression bar graph over gene model. Optionally, draw a second graph under gene, to compare sample sets */ { struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData; struct gtexGeneInfo *geneInfo = (struct gtexGeneInfo *)item; struct gtexGeneBed *geneBed = geneInfo->geneBed; if (vis == tvDense) { bedDrawSimpleAt(tg, geneBed, hvg, xOff, y, scale, font, MG_WHITE, vis); // color ignored (using grayscale) return; } if (vis == tvSquish) { Color color = gtexGeneItemColor(tg, geneBed, hvg); int height = gtexSquishItemHeight(); drawScaledBox(hvg, geneBed->chromStart, geneBed->chromEnd, scale, xOff, y, height, color); return; } int graphX = gtexGraphX(geneBed); if (graphX < 0) return; // draw gene model int topGraphHeight = gtexGeneGraphHeight(tg, geneInfo, TRUE); topGraphHeight = max(topGraphHeight, tl.fontHeight); int yZero = topGraphHeight + y - 1; // yZero is bottom of graph -int yGene = yZero + gtexGeneMargin() - 1; +int yGene = yZero + gtexGeneMargin(); int heightPer = tg->heightPer; -tg->heightPer = gtexGeneModelHeight(extras) + 1; +tg->heightPer = gtexGeneModelHeight(extras); Color statusColor = getGeneClassColor(hvg, geneBed); if (geneInfo->geneModel && extras->showExons) { struct linkedFeatures *lf = linkedFeaturesFromGenePred(tg, geneInfo->geneModel, FALSE); lf->filterColor = statusColor; - linkedFeaturesDrawAt(tg, lf, hvg, xOff, yGene, scale, font, color, gtexGeneModelVis(extras)); + linkedFeaturesDrawAt(tg, lf, hvg, xOff, yGene-1, scale, font, color, gtexGeneModelVis(extras)); } else { int height = gtexGeneBoxModelHeight(); - drawScaledBox(hvg, geneBed->chromStart, geneBed->chromEnd, scale, xOff, yGene+2, height, statusColor); + drawScaledBox(hvg, geneBed->chromStart, geneBed->chromEnd, scale, xOff, yGene+1, height, statusColor); } tg->heightPer = heightPer; } 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(tg, geneInfo); return graphWidth; } static void gtexGeneNonPropDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) { @@ -878,62 +867,90 @@ } static char *tissueExpressionText(struct gtexTissue *tissue, double expScore, 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 getItemX(int start, int end, int *x1, int *x2) +/* Return startX, endX based on item coordinates and current window */ +// Residual (largely replaced by drawScaledBox -- still used by gene model bmap box +{ +int s = max(start, winStart); +int e = min(end, winEnd); +double scale = scaleForWindow(insideWidth, winStart, winEnd); +assert(x1); +*x1 = round((double)((int)s-winStart)*scale + insideX); +assert(x2); +*x2 = round((double)((int)e-winStart)*scale + insideX); +} + +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(tg, geneInfo); +return max(geneBed->chromEnd, max(winStart, geneBed->chromStart) + graphWidth/scale); +} + 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 full mode. Just single map for squish/dense modes */ { if (tg->visibility == tvDense) { genericMapItem(tg, hvg, item, itemName, itemName, start, end, x, y, width, height); return; } struct gtexGeneInfo *geneInfo = item; struct gtexGeneBed *geneBed = geneInfo->geneBed; struct gtexGeneExtras *extras = (struct gtexGeneExtras *)tg->extraUiData; +double scale = scaleForWindow(insideWidth, winStart, winEnd); if (tg->visibility == tvSquish) { int tisId = maxTissueForGene(geneBed); char *maxTissue = ""; if (tisId > 1) maxTissue = getTissueDescription(tisId, extras->version); char buf[128]; safef(buf, sizeof buf, "%s %s", geneBed->name, maxTissue); - int x1, x2; - getItemX(geneBed->chromStart, geneBed->chromEnd, &x1, &x2); - int width = x2-x1; - mapBoxHc(hvg, geneBed->chromStart, geneBed->chromEnd, x1, y, width, height, + mapScaledBoxHc(hvg, geneBed->chromStart, geneBed->chromEnd, scale, x, y, height, tg->track, mapItemName, buf); return; } 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; int x1 = insideX; // add maps to tissue bars in expresion graph struct gtexTissue *tissues = getTissues(extras->version); 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 @@ -963,42 +980,49 @@ // 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 +// add map boxes with description to gene model if (geneInfo->geneModel && geneInfo->description) { int x1, x2; - getItemX(geneInfo->geneModel->txStart, geneInfo->geneModel->txEnd, &x1, &x2); + int s = geneInfo->geneModel->txStart; + int e = gtexGeneItemEnd(tg, item); + getItemX(s, e, &x1, &x2); int w = x2-x1; int labelWidth = mgFontStringWidth(tl.font, itemName); if (x1-labelWidth <= insideX) labelWidth = 0; - mapBoxHc(hvg, start, end, x1-labelWidth, y, w+labelWidth, geneInfo->height-3, tg->track, - mapItemName, geneInfo->description); + // map over label + int itemHeight = geneInfo->height; + mapBoxHc(hvg, start, end, x1-labelWidth, y, labelWidth, itemHeight-3, + tg->track, mapItemName, geneInfo->description); + // map over gene model (extending to end of item) + int geneModelHeight = gtexGeneModelHeight(extras); + mapBoxHc(hvg, start, end, x1, y+itemHeight-geneModelHeight-3, w, geneModelHeight, + 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); @@ -1047,48 +1071,30 @@ // share the rowSizes data across all windows for(tg=tgSave; tg; tg=tg->nextWindow) { tg->ss->rowSizes = ssHold->rowSizes; } tg = tgSave; } height = spaceSaverGetRowHeightsTotal(tg->ss); } } tg->height = height; return height; } -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(tg, geneInfo); -return max(geneBed->chromEnd, max(winStart, geneBed->chromStart) + graphWidth/scale); -} - static void gtexGenePreDrawItems(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) { if (vis == tvSquish || vis == tvDense) { // NonProp routines not relevant to these modes, and they interfere // NOTE: they must be installed by gtexGeneMethods() for pack mode tg->nonPropDrawItemAt = NULL; tg->nonPropPixelWidth = NULL; } } void gtexGeneMethods(struct track *tg) {