69ed2f332551b505c78b081306d834224e70e5da
kate
  Tue Mar 20 23:24:08 2018 -0700
Code cleanup.  Fix mouseover on curves. refs #17512

diff --git src/hg/hgTracks/interactTrack.c src/hg/hgTracks/interactTrack.c
index 45b7026..7f952bd 100644
--- src/hg/hgTracks/interactTrack.c
+++ src/hg/hgTracks/interactTrack.c
@@ -69,341 +69,390 @@
         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)
 if (slCount(filteredItems) != count)
     labelTrackAsFiltered(tg);
 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. */
+char *interactMouseover(struct interact *inter, char *otherChrom)
+/* Make mouseover text for an interaction */
 {
-#define DRAW_LINE       0
-#define DRAW_CURVE      1
-#define DRAW_ELLIPSE    2
+struct dyString *ds = dyStringNew(0);
+if (isEmptyTextField(inter->name))
+    {
+    if (!isEmptyTextField(inter->exp))
+        dyStringPrintf(ds, "%s ", inter->exp);
+    if (otherChrom)
+        dyStringPrintf(ds, "%s", otherChrom);
+    else
+        {
+        char buf[4096];
+        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);
+return dyStringCannibalize(&ds);
+}
 
-int draw = DRAW_LINE;
-if (vis != tvDense)
+int regionCenter(int start, int end)
+/* Return center of genomic region */
 {
-    char *drawMode = cartUsualStringClosestToHome(cart, tg->tdb, FALSE,
-                                INTERACT_DRAW, INTERACT_DRAW_DEFAULT);
-    if (sameString(drawMode, INTERACT_DRAW_CURVE))
-        draw = DRAW_CURVE;
-    else if (sameString(drawMode, INTERACT_DRAW_ELLIPSE))
-        draw = DRAW_ELLIPSE;
+return round((double)(end - start + .5) / 2) + start;
 }
-boolean isDirectional = interactUiDirectional(tg->tdb);
 
-double scale = scaleForWindow(width, seqStart, seqEnd);
-struct interact *inters = tg->items;
-unsigned int maxWidth = 0;
-struct interact *inter;
-char buffer[1024];
-char itemBuf[2048];
+int regionFootWidth(int start, int end, double scale)
+/* Return half foot width in pixels */
+{
+    unsigned size = end - start;
+    int width = scale * (double)size / 2;
+    if (width == 0)
+        width = 1;
+    return width;
+}
 
-// 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;
-char *otherChrom = NULL;
-for (inter=inters; inter; inter=inter->next)
+void interactRegionCenters(struct interact *inter, int *sourceCenter, int *targetCenter)
+/* Return genomic position of endpoint centers */
+{
+assert(sourceCenter);
+assert(targetCenter);
+*sourceCenter = regionCenter(inter->sourceStart, inter->sourceEnd);
+*targetCenter = regionCenter(inter->targetStart, inter->targetEnd);
+}
+
+int interactSize(struct interact *inter)
+/* Compute length of interaction (distance between middle of each region) in bp */
 {
-    int width = inter->chromEnd - inter->chromStart;
-    if (width > maxWidth)
-        maxWidth = width;
+int sourceCenter = 0, targetCenter = 0;
+interactRegionCenters(inter, &sourceCenter, &targetCenter);
+return abs(targetCenter - sourceCenter);
 }
-for (inter=inters; inter; inter=inter->next)
+
+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 round((double)(pos - seqStart + .5) * scale) + xOff;
+}
+
+struct interactTrackInfo {
+    boolean isDirectional;
+    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);
+
+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)
-        nSame++;
+        {
+        tInfo->sameCount++;
+        // determine maximum interaction size, for later use laying out 'peaks'
+        int size = interactSize(inter);
+        if (size > tInfo->maxSize)
+            tInfo->maxSize = size;
+        }
     else
         {
-        nOther++;
-        if (!doOtherLabels)
+        tInfo->otherCount++;
+        // suppress interchromosomal labels if they overlap
+        if (!tInfo->doOtherLabels)
             continue;
         int labelWidth = vgGetFontStringWidth(hvg->vg, font, otherChrom);
-        // 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 x = getX(inter->chromStart, seqStart, scale, xOff);
+        assert(x > 0);
+        int labelStart = round((double)(x - labelWidth)/2);
         int labelEnd = labelStart + labelWidth - 1;
         if (labelStart <= prevLabelEnd && 
                 !(labelStart == prevLabelStart && labelEnd == prevLabelEnd && 
                     sameString(otherChrom, prevLabel)))
-            doOtherLabels = FALSE;
+            tInfo->doOtherLabels = FALSE;
         prevLabelStart = labelStart;
         prevLabelEnd = labelEnd;
         prevLabel = otherChrom;
         }
     }
-int fontHeight = vgGetFontPixelHeight(hvg->vg, font);
-int otherHeight = (nOther) ? 3 * fontHeight : 0;
-int sameHeight = (nSame) ? tg->height - otherHeight: 0;
+tInfo->fontHeight = vgGetFontPixelHeight(hvg->vg, font);
+tInfo->otherHeight = (tInfo->otherCount) ? 3 * tInfo->fontHeight : 0;
+tInfo->sameHeight = (tInfo->sameCount) ? tg->height - tInfo->otherHeight : 0;
+return tInfo;
+}
+
+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
+
+// Determine drawing mode
+int draw = DRAW_LINE;
+if (vis != tvDense)
+    {
+    char *drawMode = cartUsualStringClosestToHome(cart, tg->tdb, FALSE,
+                                INTERACT_DRAW, INTERACT_DRAW_DEFAULT);
+    if (sameString(drawMode, INTERACT_DRAW_CURVE))
+        draw = DRAW_CURVE;
+    else if (sameString(drawMode, INTERACT_DRAW_ELLIPSE))
+        draw = DRAW_ELLIPSE;
+    }
+
+double scale = scaleForWindow(width, seqStart, seqEnd);
+struct interact *inter = NULL;
+char buffer[1024];
+char itemBuf[2048];
+
+// Gather info for layout
+struct interactTrackInfo *tInfo = interactGetTrackInfo(tg, seqStart, hvg, xOff, font, scale);
 
 // Draw items
-for (inter=inters; inter; inter=inter->next)
+for (inter = (struct interact *)tg->items; inter; inter = inter->next)
     {
     char *otherChrom = interactOtherChrom(inter);
     safef(itemBuf, sizeof itemBuf, "%s", inter->name);
-    struct dyString *ds = dyStringNew(0);
-    if (isEmptyTextField(inter->name))
-        {
-        if (!isEmptyTextField(inter->exp))
-            dyStringPrintf(ds, "%s ", inter->exp);
-        if (otherChrom)
-            dyStringPrintf(ds, "%s", otherChrom);
-        else
-            {
-            char buf[4096];
-            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);
+    char *statusBuf = interactMouseover(inter, otherChrom);
 
+    // Pick colors
     color = interactItemColor(tg, inter, hvg);
-    if (vis == tvDense && interactOtherChrom(inter) && color == MG_BLACK)
+    if (vis == tvDense && otherChrom && color == MG_BLACK)
+        // use highlight color for other chrom items in dense mode
         color = MG_MAGENTA;
     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;
-        }
-    else
-        {
-        lowStart = inter->targetStart;
-        lowEnd = inter->targetEnd;
-        highStart = inter->sourceStart;
-        highEnd = inter->sourceEnd;
-        } 
-    unsigned s = lowStart + ((double)(lowEnd - lowStart + .5) / 2);
-    int sx = ((s - seqStart) + .5) * scale + xOff; // x coord of center (lower region)
-    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;
-
     if (otherChrom)
         {
         // different chromosomes
         //      draw below same chrom items, if any
-        unsigned yPos = 0;
         int height = 0;
         int yOffOther = yOff;
-        if (tg->visibility == tvDense)
+        if (vis == tvDense)
             {
             height = tg->height;
             }
         else
             {
-            height = otherHeight/2;
-            yOffOther = yOff + sameHeight;
+            height = tInfo->otherHeight/2;
+            yOffOther = yOff + tInfo->sameHeight;
             }
-        yPos = yOffOther + height;
+        unsigned r = regionCenter(inter->chromStart, inter->chromEnd);
+        int x = getX(r, seqStart, scale, xOff); 
+        int footWidth = regionFootWidth(inter->chromStart, inter->chromEnd, scale);
+        unsigned yPos = yOffOther + height;
 
         // draw the foot
-        hvGfxLine(hvg, sx - sFootWidth, yOffOther, sx + sFootWidth, yOffOther, color);
+        hvGfxLine(hvg, x - footWidth, yOffOther, x + footWidth, yOffOther, color);
 
         // draw the vertical
-        // TODO: modularize directional/non-directional draws
-        if (differentString(inter->chrom, inter->sourceChrom) && isDirectional)
-            hvGfxDottedLine(hvg, sx, yOffOther, sx, yPos, color, TRUE);
+        if (tInfo->isDirectional && differentString(inter->chrom, inter->sourceChrom))
+            hvGfxDottedLine(hvg, x, yOffOther, x, yPos, color, TRUE);
         else
-            hvGfxLine(hvg, sx, yOffOther, sx, yPos, color);
+            hvGfxLine(hvg, x, yOffOther, x, yPos, color);
+        
+        if (vis == tvDense)
+            continue;
 
-        if (tg->visibility == tvFull)
-            {
         // add map box to foot
         char *nameBuf = (inter->chromStart == inter->sourceStart ?      
                         inter->sourceName : inter->targetName);
         if (isEmptyTextField(nameBuf))
             nameBuf = statusBuf;
         mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, 
-                            sx - sFootWidth, yOffOther, sFootWidth * 2, 4,
+                        x - footWidth, yOffOther, footWidth * 2, 4,
                         tg->track, itemBuf, nameBuf, NULL, TRUE, NULL);
 
         // add map box to vertical
-            mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, sx - 2, yOffOther, 4, height,
-                                   tg->track, itemBuf, statusBuf, NULL, TRUE, NULL);
-            if (doOtherLabels)
+        mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, x - 2, yOffOther, 4, 
+                            height, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL);
+        if (tInfo->doOtherLabels)
             {
+            // draw label
             safef(buffer, sizeof buffer, "%s", sameString(inter->chrom, inter->sourceChrom) ?
                                         inter->targetChrom : inter->sourceChrom);
-                hvGfxTextCentered(hvg, sx, yPos + 2, 4, 4, MG_BLUE, font, buffer);
-                int width = vgGetFontStringWidth(hvg->vg, font, buffer);
+            hvGfxTextCentered(hvg, x, yPos + 2, 4, 4, MG_BLUE, font, buffer);
+            int labelWidth = vgGetFontStringWidth(hvg->vg, font, buffer);
 
-                // add mapBox to label
-                mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, sx - width/2, yPos, 
-                                width, fontHeight, tg->track, itemBuf, statusBuf, NULL, TRUE, NULL);
-                }
+            // add map box to label
+            mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, x - labelWidth/2, 
+                    yPos, labelWidth, tInfo->fontHeight, tg->track, itemBuf, statusBuf, 
+                    NULL, TRUE, NULL);
             }
         continue;
         }
 
-    // draw same chromosome interaction
+    // Draw same chromosome interaction
+
+    // source region
+    unsigned s = regionCenter(inter->sourceStart, inter->sourceEnd);
+    int sX = getX(s, seqStart, scale, xOff); 
+    int sWidth = regionFootWidth(inter->sourceStart, inter->sourceEnd, scale);
     boolean sOnScreen = (s >= seqStart) && (s< seqEnd);
-    boolean eOnScreen = (e >= seqStart) && (e < seqEnd);
 
-    double interWidth = e - s;
-    int peakHeight = (sameHeight - 15) * ((double)interWidth / maxWidth) + 10;
+    // target region
+    unsigned t = regionCenter(inter->targetStart, inter->targetEnd);
+    int tX = getX(t, seqStart, scale, xOff);
+    int tWidth = regionFootWidth(inter->targetStart,inter->targetEnd, scale);
+    boolean tOnScreen = (t >= seqStart) && (t< seqEnd);
+
+    boolean isReversed = (tInfo->isDirectional && t < s);
+    int interSize = abs(t - s);
+    int peakHeight = (tInfo->sameHeight - 15) * ((double)interSize / tInfo->maxSize) + 10;
     int peak = yOff + peakHeight;
-    if (tg->visibility == tvDense)
+    if (vis == tvDense)
         peak = yOff + tg->height;
 
     if (sOnScreen)
         {
-        // draw foot of lower region
-        hvGfxLine(hvg, sx - sFootWidth, yOff, sx + sFootWidth, yOff, color);
-        // draw vertical
-        if (!eOnScreen || draw == DRAW_LINE)
+        // draw foot of source region
+        hvGfxLine(hvg, sX - sWidth, yOff, sX + sWidth, yOff, color);
+        if (vis == tvDense || !tOnScreen || draw == DRAW_LINE)
             {
-            if (inter->chromStart == inter->targetStart && isDirectional)
-                hvGfxDottedLine(hvg, sx, yOff, sx, peak, color, TRUE);
+            // draw vertical
+            if (isReversed)
+                hvGfxDottedLine(hvg, sX, yOff, sX, peak, color, TRUE);
             else
-                hvGfxLine(hvg, sx, yOff, sx, peak, color);
+                hvGfxLine(hvg, sX, yOff, sX, peak, color);
             }
         }
-    if (eOnScreen)
+    if (tOnScreen)
         {
-        // draw foot of upper region
-        hvGfxLine(hvg, ex - eFootWidth, yOff, ex + eFootWidth, yOff, color);
-
-        // draw vertical
-        if (!sOnScreen || draw == DRAW_LINE)
+        // draw foot of target region
+        hvGfxLine(hvg, tX - tWidth, yOff, tX + tWidth, yOff, color);
+        if (vis == tvDense || !sOnScreen || draw == DRAW_LINE)
             {
-            if (inter->chromStart == inter->targetStart && isDirectional)
-                hvGfxDottedLine(hvg, ex, yOff, ex, peak, color, TRUE);
+            // draw vertical
+            if (isReversed)
+                hvGfxDottedLine(hvg, tX, yOff, tX, peak, color, TRUE);
             else
-                hvGfxLine(hvg, ex, yOff, ex, peak, color);
+                hvGfxLine(hvg, tX, yOff, tX, peak, color);
             }
         }
-    if (tg->visibility == tvFull)
-        {
+    if (vis == tvDense)
+        continue;
+
+    // Full mode: add map boxes and draw interaction
     char *nameBuf = NULL;
     if (sOnScreen)
         {
-            /* add mapbox to lower region */
-            nameBuf = (inter->chromStart == inter->sourceStart ?      
-                            inter->sourceName : inter->targetName);
-            if (isEmptyTextField(nameBuf))
-                nameBuf = statusBuf;
-            hvGfxBox(hvg, sx-1, yOff, 3, 1, peakColor);
-            hvGfxBox(hvg, sx, yOff, 1, 1, MG_WHITE);
+        // add map box to source region
+        nameBuf = isEmptyTextField(inter->sourceName) ? statusBuf : inter->sourceName;
+        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, 3,
+                           sX - sWidth, yOff, sWidth * 2, 3,
                            tg->track, itemBuf, nameBuf, NULL, TRUE, NULL);
-
         }
-        if (eOnScreen)
+    if (tOnScreen)
         {
-            /* add mapbox to upper region */
-            nameBuf = (inter->chromEnd == inter->targetEnd ?      
-                            inter->targetName : inter->sourceName);
-            if (isEmptyTextField(nameBuf))
-                nameBuf = statusBuf;
-            hvGfxBox(hvg, ex-1, yOff, 3, 1, peakColor);
-            hvGfxBox(hvg, ex, yOff, 1, 1, MG_WHITE);
+        // add map box to target region
+        nameBuf = isEmptyTextField(inter->targetName) ? statusBuf : inter->targetName;
+        hvGfxBox(hvg, tX-1, yOff, 3, 1, peakColor);
+        hvGfxBox(hvg, tX, yOff, 1, 1, MG_WHITE);
         mapBoxHgcOrHgGene(hvg, inter->chromStart, inter->chromEnd, 
-                            ex - eFootWidth, yOff, eFootWidth * 2, 3,
+                        tX - tWidth, yOff, tWidth * 2, 3,
                         tg->track, itemBuf, nameBuf, NULL, TRUE, NULL);
         }
-        if (sOnScreen && eOnScreen && draw != DRAW_LINE)
+    // 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)
         {
-            boolean isDashed = (inter->sourceStart > inter->targetStart);
+        // 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, 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);
+        continue;
+        }
+    // Draw curves
     if (draw == DRAW_CURVE)
         {
-                int peakX = ((ex - sx + 1) / 2) + sx;
+        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, sx, yOff, peakX, peakY, ex, yOff, color, isDashed);
+        int maxY = hvGfxCurve(hvg, lowerX, yOff, peakX, peakY, upperX, yOff, 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, 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);
+                       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, isDashed);
+        hvGfxEllipseDraw(hvg, lowerX, yLeft, upperX, yTop, color, ELLIPSE_BOTTOM, isReversed);
         // draw map box on peak
         int maxY = peakHeight + yOff;
-                int peakX = ((ex - sx + 1) / 2) + sx;
+        int peakX = ((upperX - lowerX + 1) / 2) + lowerX;
         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;
-            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)
 /* Interact track type methods */
 {
 tg->loadItems = interactLoadItems;
 tg->drawItems = interactDrawItems;
 tg->drawLeftLabels = interactDrawLeftLabels;