d55f8036a2a03c72c31b2e70d6adb22d8d0301cb kate Thu Aug 9 15:52:05 2018 -0700 Add setting to offset target endpoints from source endpoints. refs #21109 diff --git src/hg/hgTracks/interactTrack.c src/hg/hgTracks/interactTrack.c index b19dba2..688a982 100644 --- src/hg/hgTracks/interactTrack.c +++ src/hg/hgTracks/interactTrack.c @@ -168,47 +168,49 @@ { int sourceCenter = 0, targetCenter = 0; interactRegionCenters(inter, &sourceCenter, &targetCenter); return abs(targetCenter - sourceCenter); } int getX(int pos, int seqStart, double scale, int xOff) /* Get x coordinate of a genomic location. Return -1 if off-screen */ { if (pos < seqStart) return -1; return ((double)(pos - seqStart + .5) * scale) + xOff; } struct interactTrackInfo { - boolean isDirectional; + boolean isDirectional; // source and target are distinct item types + boolean isOffset; // source and target ends are on different horizontals boolean doOtherLabels; // true to suppress labels on other chrom items (prevent overlap) int maxSize; // longest interaction (midpoint to midpoint) in bp int fontHeight; int sameCount; // number of same chromosome interactions in window int sameHeight; // vertical space for same chromosome interactions int otherCount; // number of other chromosome interactions in window int otherHeight; // vertical space for other chromosome interactions } interactTrackInfo; struct interactTrackInfo *interactGetTrackInfo(struct track *tg, int seqStart, struct hvGfx *hvg, int xOff, MgFont *font, double scale) /* Get layout info from interact items in window */ { struct interactTrackInfo *tInfo = NULL; AllocVar(tInfo); tInfo->doOtherLabels = TRUE; tInfo->isDirectional = interactUiDirectional(tg->tdb); +tInfo->isOffset = interactUiOffset(tg->tdb); char *otherChrom = NULL; int prevLabelEnd = 0, prevLabelStart = 0; char *prevLabel = 0; struct interact *inter; for (inter = (struct interact *)tg->items; inter; inter = inter->next) { otherChrom = interactOtherChrom(inter); if (otherChrom == NULL) { tInfo->sameCount++; // determine maximum interaction size, for later use laying out 'peaks' int size = interactSize(inter); if (size > tInfo->maxSize) @@ -376,125 +378,132 @@ // NOTE: until time permits, force to rectangle when in reversed strand mode. if (sOnScreen) { // draw foot of source region (2 pixels high) hvGfxBox(hvg, sX - sWidth, yOff, sWidth + sWidth + 1, 2, color); if (vis == tvDense || !tOnScreen || draw == DRAW_LINE || hvg->rc) { // draw vertical if (isReversed) hvGfxDottedLine(hvg, sX, yOff, sX, peak, color, TRUE); else hvGfxLine(hvg, sX, yOff, sX, peak, color); } } + int yOffTarget = (tInfo->isOffset ? yOff + tg->height/20 + 1 : yOff); if (tOnScreen) { // draw foot of target region (2 pixels high) - hvGfxBox(hvg, tX - tWidth, yOff, tWidth + tWidth + 1, 2, color); + hvGfxBox(hvg, tX - tWidth, yOffTarget, tWidth + tWidth + 1, 2, color); if (vis == tvDense || !sOnScreen || draw == DRAW_LINE || hvg->rc) { // draw vertical if (isReversed) - hvGfxDottedLine(hvg, tX, yOff, tX, peak, color, TRUE); + hvGfxDottedLine(hvg, tX, yOffTarget, tX, peak, color, TRUE); else - hvGfxLine(hvg, tX, yOff, tX, peak, color); + hvGfxLine(hvg, tX, yOffTarget, tX, peak, color); } } if (vis == tvDense) continue; // Full mode: add map boxes and draw interaction + int highlightColor = MG_WHITE; int chromStart = inter->chromStart; int chromEnd = inter->chromEnd; char *nameBuf = NULL; if (sOnScreen) { // add map box to source region nameBuf = isEmptyTextField(inter->sourceName) ? statusBuf : inter->sourceName; + //hvGfxBox(hvg, sX-1, yOff-1, 3, 3, peakColor); // needed ? hvGfxBox(hvg, sX-1, yOff, 3, 2, peakColor); - hvGfxBox(hvg, sX, yOff, 1, 1, MG_WHITE); + hvGfxBox(hvg, sX, yOff, 1, 1, highlightColor); mapBoxHgcOrHgGene(hvg, chromStart, chromEnd, sX - sWidth, yOff, sWidth * 2, 4, tg->track, itemBuf, nameBuf, NULL, TRUE, NULL); } if (tOnScreen) { // add map box to target region nameBuf = isEmptyTextField(inter->targetName) ? statusBuf : inter->targetName; - hvGfxBox(hvg, tX-1, yOff, 3, 2, peakColor); - hvGfxBox(hvg, tX, yOff, 1, 1, MG_WHITE); + //hvGfxBox(hvg, tX-1, yOffTarget-1, 3, 3, tInfo->isDirectional ? MG_MAGENTA : peakColor); + hvGfxBox(hvg, tX-1, yOffTarget, 3, 2, tInfo->isDirectional ? MG_MAGENTA : peakColor); + hvGfxBox(hvg, tX, yOffTarget, 1, 1, highlightColor); mapBoxHgcOrHgGene(hvg, chromStart, chromEnd, - tX - tWidth, yOff, tWidth * 2, 4, + //tX - tWidth, yOffTarget, tWidth * 2, 4, + tX - tWidth, yOffTarget, tWidth * 2, 3, tg->track, itemBuf, nameBuf, NULL, TRUE, NULL); } if ((s < seqStart && t < seqStart) || (s > seqEnd && t > seqEnd)) continue; // Draw interaction and map boxes int lowerX = 0, upperX = 0; if (s < t) { lowerX = sOnScreen ? sX : xOff; upperX = tOnScreen ? tX : xOff + width; } else { lowerX = tOnScreen ? tX : xOff; upperX = sOnScreen ? sX : xOff + width; } if (draw == DRAW_LINE || !sOnScreen || !tOnScreen || hvg->rc) { // draw horizontal line between region centers at 'peak' height if (isReversed) hvGfxDottedLine(hvg, lowerX, peak, upperX, peak, color, TRUE); else hvGfxLine(hvg, lowerX, peak, upperX, peak, color); // map box on mid-point of horizontal line int xMap = lowerX + (double)(upperX-lowerX)/2; int yMap = peak-1; hvGfxBox(hvg, xMap-1, peak-1, 3, 3, peakColor); - hvGfxBox(hvg, xMap, peak, 1, 1, MG_WHITE); + hvGfxBox(hvg, xMap, peak, 1, 1, highlightColor); mapBoxHgcOrHgGene(hvg, chromStart, chromEnd, xMap-1, yMap-1, 3, 3, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); continue; } // Draw curves if (draw == DRAW_CURVE) { int peakX = ((upperX - lowerX + 1) / 2) + lowerX; int peakY = peak + 30; // admittedly a hack (obscure how to define ypeak of curve) - int maxY = hvGfxCurve(hvg, lowerX, yOff, peakX, peakY, upperX, yOff, color, isReversed); + int maxY = hvGfxCurve(hvg, lowerX, + (isReversed ? yOffTarget : yOff), peakX, peakY, upperX, + (isReversed ? yOff : yOffTarget), color, isReversed); // curve drawer does not use peakY as expected, so it returns actual max Y used // draw map box on peak hvGfxBox(hvg, peakX-1, maxY-1, 3, 3, peakColor); - hvGfxBox(hvg, peakX, maxY, 1, 1, MG_WHITE); + hvGfxBox(hvg, peakX, maxY, 1, 1, highlightColor); mapBoxHgcOrHgGene(hvg, chromStart, chromEnd, peakX-1, maxY-1, 3, 3, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL); } else if (draw == DRAW_ELLIPSE) { - int yLeft = yOff + peakHeight; - int yTop = yOff - peakHeight; + int yLeft = yOffTarget + peakHeight; + int yTop = yOffTarget - peakHeight; hvGfxEllipseDraw(hvg, lowerX, yLeft, upperX, yTop, color, ELLIPSE_BOTTOM, isReversed); // draw map box on peak - int maxY = peakHeight + yOff; + int maxY = peakHeight + yOffTarget; int peakX = ((upperX - lowerX + 1) / 2) + lowerX; hvGfxBox(hvg, peakX-1, maxY-1, 3, 3, peakColor); - hvGfxBox(hvg, peakX, maxY, 1, 1, MG_WHITE); + hvGfxBox(hvg, peakX, maxY, 1, 1, highlightColor); mapBoxHgcOrHgGene(hvg, chromStart, chromEnd, peakX-1, maxY-1, 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)