112e6092522e4eed411c8b64c225e792bbb640a0 kate Mon Jan 29 09:08:28 2018 -0800 Tweak height of curves to maintain shape while remaining comparability to off-screen endpoint lines. refs #117512 diff --git src/hg/hgTracks/interactTrack.c src/hg/hgTracks/interactTrack.c index 0108dbf..9650397 100644 --- src/hg/hgTracks/interactTrack.c +++ src/hg/hgTracks/interactTrack.c @@ -1,342 +1,342 @@ /* interactTrack -- draw interaction between two genomic regions */ /* Copyright (C) 2018 The Regents of the University of California * See README in this or parent directory for licensing information. */ #include "common.h" #include "hgTracks.h" #include "interact.h" #include "interactUi.h" static int interactTotalHeight(struct track *tg, enum trackVisibility vis) /* 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); //uglyf("IN totalHeight=%d. ", current); // FIXME DEBUG //return 300; 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; 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; //uglyf("IN color=%X", hvGfxFindColorIx(hvg, itemRgb.r, itemRgb.g, itemRgb.b)); return hvGfxFindColorIx(hvg, itemRgb.r, itemRgb.g, itemRgb.b); } void interactLoadItems(struct track *tg) /* Load all interact items in region */ { loadSimpleBedWithLoader(tg, (bedItemLoader)interactLoad); } 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 char *drawMode = cartUsualStringClosestToHome(cart, tg->tdb, FALSE, INTERACT_DRAW, INTERACT_DRAW_DEFAULT); int draw = DRAW_LINE; -if (sameString(drawMode, "curve")) +if (sameString(drawMode, INTERACT_DRAW_CURVE)) draw = DRAW_CURVE; -else if (sameString(drawMode, "ellipse")) +else if (sameString(drawMode, INTERACT_DRAW_ELLIPSE)) draw = DRAW_ELLIPSE; double scale = scaleForWindow(width, seqStart, seqEnd); struct interact *inters = tg->items; //uglyf("Found %d items. ", slCount(inters)); unsigned int maxWidth = 0; struct interact *inter; char buffer[1024]; char itemBuf[2048]; safef(buffer, sizeof buffer, "%s.%s", tg->tdb->track, INTERACT_MINSCORE); //double minScore = sqlDouble(cartUsualString(cart, buffer, INTERACT_DEFMINSCORE)); // Determine if there are mixed inter and intra-chromosomal // Suppress interchromosomal labels if they overlap int nSame = 0, nOther = 0; int prevLabelEnd = 0, prevLabelStart = 0; char *prevLabel = 0; boolean doOtherLabels = TRUE; for (inter=inters; inter; inter=inter->next) { int width = inter->chromEnd - inter->chromStart; if (width > maxWidth) maxWidth = width; } //uglyf("Max width is %d. ", maxWidth); for (inter=inters; inter; inter=inter->next) { if (sameString(inter->chrom1, inter->chrom2)) nSame++; else { nOther++; if (!doOtherLabels) continue; int labelWidth = vgGetFontStringWidth(hvg->vg, font, inter->chrom2); // TODO: simplify now that center approach is abandoned int sx = ((inter->chromStart - seqStart) + .5) * scale + xOff; // x coord of center int labelStart = (double)sx - labelWidth/2; int labelEnd = labelStart + labelWidth - 1; char *otherChrom = (inter->strand[0] == '+') ? inter->chrom2 : inter->chrom1; if (labelStart <= prevLabelEnd && !(labelStart == prevLabelStart && labelEnd == prevLabelEnd && sameString(otherChrom, prevLabel))) doOtherLabels = FALSE; prevLabelStart = labelStart; prevLabelEnd = labelEnd; prevLabel = inter->chrom2; } } int fontHeight = vgGetFontPixelHeight(hvg->vg, font); int otherHeight = (nOther) ? 3 * fontHeight : 0; int sameHeight = (nSame) ? tg->height - otherHeight: 0; // Draw items //uglyf("IN seqStart=%d", seqStart); for (inter=inters; inter; inter=inter->next) { safef(itemBuf, sizeof itemBuf, "%s", inter->name); struct dyString *ds = dyStringNew(0); dyStringPrintf(ds, "%s", inter->name); if (inter->score) dyStringPrintf(ds, " %d", inter->score); char *statusBuf = dyStringCannibalize(&ds); //uglyf("statusBuf: %s. ", statusBuf); color = interactItemColor(tg, inter, hvg); // TODO: simplify by using start/end instead of center and width // This is a holdover from longRange track implementation // set lower and upper regions from item1 and item2, which may be ordered by type rather // than genomic position (e.g. item1 are snp's, item2 are genes) unsigned lowStart, lowEnd, highStart, highEnd; if (inter->chromStart1 < inter->chromStart2) { lowStart = inter->chromStart1; lowEnd = inter->chromEnd1; highStart = inter->chromStart2; highEnd = inter->chromEnd2; } else { lowStart = inter->chromStart2; lowEnd = inter->chromEnd2; highStart = inter->chromStart1; highEnd = inter->chromEnd1; } // TODO: cleanup if (differentString(inter->chrom1, inter->chrom2)) { lowStart = inter->chromStart; lowEnd = inter->chromEnd; } unsigned s = lowStart + ((double)(lowEnd - lowStart + .5) / 2); int sx = ((s - seqStart) + .5) * scale + xOff; // x coord of center (lower region) //uglyf("
IN seqStart=%d, start=%d, start1=%d, end1=%d, start2=%d, end2=%d, end=%d, s=%d, sx=%d. ", //seqStart, inter->chromStart, inter->chromStart1, inter->chromEnd1, //inter->chromStart2, inter->chromEnd2, inter->chromEnd, s, sx); unsigned sw = lowEnd - lowStart; int sFootWidth = scale * (double)sw / 2; // width in pixels of half foot (lower) if (sFootWidth == 0) sFootWidth = 1; unsigned e = highStart + (double)(highEnd - highStart + .5) / 2; int ex = ((e - seqStart) + .5) * scale + xOff; unsigned ew = highEnd - highStart; int eFootWidth = scale * (double)ew / 2; if (eFootWidth == 0) eFootWidth = 1; //uglyf("
IN s=%d, sx=%d, sw=%d, sFootWidth=%d. e=%d, ex=%d, ew=%d, eFootWidth=%d, chromStart=%d", //s, sx, sw, sFootWidth, e, ex, ew, eFootWidth, inter->chromStart); //uglyf("
  IN start1=%d, end1=%d, start2=%d, end2=%d.", //inter->chromStart1, inter->chromEnd1, inter->chromStart2, inter->chromEnd2); if (differentString(inter->chrom1, inter->chrom2)) { // different chromosomes // draw below same chrom items, if any unsigned yPos = 0; int height = 0; int yOffOther = yOff; if (tg->visibility == tvDense) { height = tg->height; } else { height = otherHeight/2; yOffOther = yOff + sameHeight; } yPos = yOffOther + height; // draw the foot int footWidth = sFootWidth; hvGfxLine(hvg, sx - footWidth, yOffOther, sx + footWidth, yOffOther, color); // draw the vertical if (inter->strand[0] == '+') hvGfxLine(hvg, sx, yOffOther, sx, yPos, color); else hvGfxDottedLine(hvg, sx, yOffOther, sx, yPos, color); if (tg->visibility == tvFull) { mapBoxHgcOrHgGene(hvg, s, s, sx - 2, yOffOther, 4, height, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); safef(buffer, sizeof buffer, "%s", inter->strand[0] == '+' ? inter->chrom2 : inter->chrom1); if (doOtherLabels) { hvGfxTextCentered(hvg, sx, yPos + 2, 4, 4, MG_BLUE, font, buffer); int width = vgGetFontStringWidth(hvg->vg, font, buffer); mapBoxHgcOrHgGene(hvg, s, s, sx - width/2, yPos, width, fontHeight, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); } } continue; } // draw same chromosome interaction boolean sOnScreen = (s >= seqStart) && (s < seqEnd); boolean eOnScreen = (e >= seqStart) && (e < seqEnd); //uglyf("
IN s=%d, e=%d, sOn: %d, eOn: %d. ", s, e, sOnScreen, eOnScreen); //if (s>e) //uglyf("
IN s>e start=%d, start1=%d, end1=%d, start2=%d, end2=%d, end=%d, s=%d, sx=%d. ", //inter->chromStart, inter->chromStart1, inter->chromEnd1, //inter->chromStart2, inter->chromEnd2, inter->chromEnd, s, sx); double interWidth = e - s; int peakHeight = (sameHeight - 15) * ((double)interWidth / maxWidth) + 10; int peak = yOff + peakHeight; if (tg->visibility == tvDense) peak = yOff + tg->height; if (sOnScreen) { // draw foot of first region and mapbox hvGfxLine(hvg, sx - sFootWidth, yOff, sx + sFootWidth, yOff, color); mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, sx - sFootWidth - 2, yOff, sx + sFootWidth + 2, 4, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); // draw vertical if (!eOnScreen || draw == DRAW_LINE) { if (inter->strand[0] == '-') hvGfxDottedLine(hvg, sx, yOff, sx, peak, color); else hvGfxLine(hvg, sx, yOff, sx, peak, color); } } if (eOnScreen) { // draw foot and mapbox of second region hvGfxLine(hvg, ex - eFootWidth, yOff, ex + eFootWidth, yOff, color); mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, ex - eFootWidth - 2, yOff, ex + eFootWidth + 2, 4, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); // draw vertical if (!sOnScreen || draw == DRAW_LINE) { if (inter->strand[0] == '-') hvGfxDottedLine(hvg, ex, yOff, ex, peak, color); //OLD else hvGfxLine(hvg, ex, yOff, ex, peak, color); //OLD } } if (tg->visibility == tvFull) { if (sOnScreen && eOnScreen && draw != DRAW_LINE) { boolean isDotted = (inter->strand[0] == '-'); if (draw == DRAW_CURVE) { int peakX = ((ex - sx + 1) / 2) + sx; - int peakY = peak + 60; + int peakY = peak + 30; hvGfxCurve(hvg, sx, yOff, peakX, peakY, ex, yOff, color, isDotted); // map box on peak // FIXME: not working /*mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, peakX - 2, peakY - 2, 4, 4, tg->track, itemBuf, statusBuf, 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, isDotted); // map box on peak // FIXME: not working /*mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, sx - sFootWidth - 2, yOff + peakHeight, 4, 4, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); */ } } else { // draw link horizontal line between regions (dense mode just shows feet ??) unsigned ePeak = eOnScreen ? ex : xOff + width; unsigned sPeak = sOnScreen ? sx : xOff; if (inter->strand[0] == '-') hvGfxDottedLine(hvg, sPeak, peak, ePeak, peak, color); else hvGfxLine(hvg, sPeak, peak, ePeak, peak, color); // map box on horizontal line mapBoxHgcOrHgGene(hvg, s, e, sPeak, peak-2, ePeak - sPeak, 4, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); // map boxes on verticals if (sOnScreen) mapBoxHgcOrHgGene(hvg, s, e, sx - 2, yOff, 4, peak - yOff, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); if (eOnScreen) mapBoxHgcOrHgGene(hvg, s, e, ex - 2, yOff, 4, peak - yOff, 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) /* Interact track type methods */ { //tg->bedSize = 6; //bedMethods(tg); tg->loadItems = interactLoadItems; tg->drawItems = interactDrawItems; tg->drawLeftLabels = interactDrawLeftLabels; tg->totalHeight = interactTotalHeight; tg->mapsSelf = TRUE; }