3fd4131517e0d224eb271e312c9fda6419e1872d kate Tue Mar 13 15:51:59 2018 -0700 1. Add support for spectrum setting. 2. Allow dot for empty field. 3. Show multiple items on details page if they overlap. 4. Some cleanup of map boxes. refs #17512 diff --git src/hg/hgTracks/interactTrack.c src/hg/hgTracks/interactTrack.c index 23c2982..cda8b05 100644 --- src/hg/hgTracks/interactTrack.c +++ src/hg/hgTracks/interactTrack.c @@ -14,69 +14,79 @@ /* calculate height of all the interactions being displayed */ { if ( tg->visibility == tvDense) return tl.fontHeight; int min, max, deflt, current; cartTdbFetchMinMaxPixels(cart, tg->tdb, INTERACT_MINHEIGHT, INTERACT_MAXHEIGHT, atoi(INTERACT_DEFHEIGHT), &min, &max, &deflt, ¤t); return tg->height = current; } static Color interactItemColor(struct track *tg, void *item, struct hvGfx *hvg) /* Return color to draw an interaction */ { struct interact *inter = item; +if (tg->colorShades) + return tg->colorShades[grayInRange(inter->score, 0, 1000)]; struct rgbColor itemRgb; // There must be a better way... itemRgb.r = (inter->color & 0xff0000) >> 16; itemRgb.g = (inter->color & 0xff00) >> 8; itemRgb.b = inter->color & 0xff; return hvGfxFindColorIx(hvg, itemRgb.r, itemRgb.g, itemRgb.b); } void interactLoadItems(struct track *tg) /* Load all interact items in region */ { loadSimpleBedWithLoader(tg, (bedItemLoader)interactLoad); if (tg->limitedVisSet) { // too many items to display // borrowed behaviors in bamTrack and vcfTrack // TODO BRANEY: make this behavior generic for bigBeds // (bigBedSelectRange) tg->drawItems = bigDrawWarning; tg->networkErrMsg = "Too many items in display (zoom in)"; tg->totalHeight = bigWarnTotalHeight; return; } -// filters +// filter and grayscale adjustment on score char buf[1024]; safef(buf, sizeof buf, "%s.%s", tg->tdb->track, INTERACT_MINSCORE); int minScore = cartUsualInt(cart, buf, INTERACT_DEFMINSCORE); +int scoreMin = atoi(trackDbSettingClosestToHomeOrDefault(tg->tdb, "scoreMin", "0")); +int scoreMax = atoi(trackDbSettingClosestToHomeOrDefault(tg->tdb, "scoreMax", "1000")); struct interact *inter, *next, *filteredItems = NULL; for (inter = tg->items; inter; inter = next) { next = inter->next; if (inter->score < minScore) continue; + if (tg->colorShades) + { + struct bed *bed = (struct bed *)inter; + adjustBedScoreGrayLevel(tg->tdb, bed, scoreMin, scoreMax); + } slAddHead(&filteredItems, inter); } slReverse(&filteredItems); +// consider sorting by score/value so highest scored items draw last (on top) tg->items = filteredItems; } static void interactDrawItems(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw a list of interact structures. */ { #define DRAW_LINE 0 #define DRAW_CURVE 1 #define DRAW_ELLIPSE 2 int draw = DRAW_LINE; if (vis != tvDense) { @@ -155,31 +165,31 @@ sprintLongWithCommas(buf, inter->chromEnd - inter->chromStart); dyStringPrintf(ds, "%s bp", buf); } } else dyStringPrintf(ds, "%s", inter->name); if (inter->score) dyStringPrintf(ds, " %d", inter->score); if (inter->value != 0.0) dyStringPrintf(ds, " %0.2f", inter->value); char *statusBuf = dyStringCannibalize(&ds); color = interactItemColor(tg, inter, hvg); if (vis == tvDense && interactOtherChrom(inter) && color == MG_BLACK) color = MG_MAGENTA; - int peakColor = (color == MG_BLACK) ? MG_MAGENTA : MG_GRAY; + int peakColor = (color == MG_BLACK || tg->colorShades) ? MG_MAGENTA : MG_GRAY; // TODO: simplify by using start/end instead of center and width // This is a holdover from longRange track implementation unsigned lowStart, lowEnd, highStart, highEnd; if (otherChrom) { lowStart = highStart = inter->chromStart; lowEnd = highEnd = inter->chromEnd; } else if (inter->sourceStart < inter->targetStart) { lowStart = inter->sourceStart; lowEnd = inter->sourceEnd; highStart = inter->targetStart; highEnd = inter->targetEnd; @@ -297,109 +307,95 @@ hvGfxDottedLine(hvg, ex, yOff, ex, peak, color, TRUE); else hvGfxLine(hvg, ex, yOff, ex, peak, color); } } if (tg->visibility == tvFull) { char *nameBuf = NULL; if (sOnScreen) { /* add mapbox to lower region */ nameBuf = (inter->chromStart == inter->sourceStart ? inter->sourceName : inter->targetName); if (isEmptyTextField(nameBuf)) nameBuf = statusBuf; - int xMap = sx-1; - int yMap = yOff; - int w = 3; - int h = 1; - hvGfxBox(hvg, xMap, yMap, w, h, peakColor); - hvGfxBox(hvg, xMap, yMap+1, w, h-2, MG_WHITE); + hvGfxBox(hvg, sx-1, yOff, 3, 1, peakColor); + hvGfxBox(hvg, sx, yOff, 1, 1, MG_WHITE); mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, - sx + sFootWidth, yOff, sFootWidth * 2, 4, + sx - sFootWidth, yOff, sFootWidth * 2, 3, tg->track, itemBuf, nameBuf, NULL, TRUE, NULL); } if (eOnScreen) { /* add mapbox to upper region */ nameBuf = (inter->chromEnd == inter->targetEnd ? inter->targetName : inter->sourceName); if (isEmptyTextField(nameBuf)) nameBuf = statusBuf; - int xMap = ex-1; - int yMap = yOff; - int w = 3; - int h = 1; - hvGfxBox(hvg, xMap, yMap, w, h, peakColor); - hvGfxBox(hvg, xMap, yMap+1, w, h-2, MG_WHITE); + hvGfxBox(hvg, ex-1, yOff, 3, 1, peakColor); + hvGfxBox(hvg, ex, yOff, 1, 1, MG_WHITE); mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, - ex + eFootWidth, yOff, eFootWidth * 2, 4, + ex - eFootWidth, yOff, eFootWidth * 2, 3, tg->track, itemBuf, nameBuf, NULL, TRUE, NULL); } if (sOnScreen && eOnScreen && draw != DRAW_LINE) { boolean isDashed = (inter->sourceStart > inter->targetStart); if (draw == DRAW_CURVE) { int peakX = ((ex - sx + 1) / 2) + sx; - int peakY = peak + 30; + int peakY = peak + 30; // admittedly a hack (obscure how to define ypeak of curve) int maxY = hvGfxCurve(hvg, sx, yOff, peakX, peakY, ex, yOff, color, isDashed); // curve drawer does not use peakY as expected, so it returns actual max Y used // draw map box on peak - int w = 3; - int h = 1; - hvGfxBox(hvg, peakX-1, maxY, w, h, peakColor); - hvGfxBox(hvg, peakX, maxY, w-2, h, MG_WHITE); - mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, peakX, maxY, w, h, + hvGfxBox(hvg, peakX-1, maxY, 3, 1, peakColor); + hvGfxBox(hvg, peakX, maxY, 1, 1, MG_WHITE); + mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, peakX, maxY, 3, 1, tg->track, itemBuf, nameBuf, NULL, TRUE, NULL); } else if (draw == DRAW_ELLIPSE) { int yLeft = yOff + peakHeight; int yTop = yOff - peakHeight; hvGfxEllipseDraw(hvg, sx, yLeft, ex, yTop, color, ELLIPSE_BOTTOM, isDashed); // draw map box on peak int maxY = peakHeight + yOff; int peakX = ((ex - sx + 1) / 2) + sx; - int w = 3; - int h = 1; - hvGfxBox(hvg, peakX-1, maxY, w, h, peakColor); - hvGfxBox(hvg, peakX, maxY, w-2, h, MG_WHITE); - mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, peakX, maxY, w, h, + hvGfxBox(hvg, peakX-1, maxY, 3, 1, peakColor); + hvGfxBox(hvg, peakX, maxY, 1, 1, MG_WHITE); + mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, peakX, maxY, 3, 1, tg->track, itemBuf, nameBuf, NULL, TRUE, NULL); } } else { // draw link horizontal line between regions unsigned ePeak = eOnScreen ? ex : xOff + width; unsigned sPeak = sOnScreen ? sx : xOff; if (inter->sourceStart > inter->targetStart && isDirectional) hvGfxDottedLine(hvg, sPeak, peak, ePeak, peak, color, TRUE); else hvGfxLine(hvg, sPeak, peak, ePeak, peak, color); // map box on mid-point of horizontal line int xMap = sPeak + (double)(ePeak-sPeak)/2; int yMap = peak-1; - int w = 1; - int h = 3; - hvGfxBox(hvg, xMap, yMap, w, h, peakColor); - hvGfxBox(hvg, xMap, yMap+1, w, h-2, MG_WHITE); - mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, xMap, yMap, w, h, + hvGfxBox(hvg, xMap, peak-1, 1, 3, peakColor); + hvGfxBox(hvg, xMap, peak, 1, 1, MG_WHITE); + mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, xMap-1, yMap, 3, 3, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); } } } } void interactDrawLeftLabels(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, int height, boolean withCenterLabels, MgFont *font, Color color, enum trackVisibility vis) /* Override default */ { } void interactMethods(struct track *tg)