6768623f4a07b2b790c6c091031174d348072df0
hiram
  Fri Aug 1 12:17:30 2014 -0700
rename file to be more consistent refs #13706
diff --git src/hg/hgTracks/joinedRmskTrack.c src/hg/hgTracks/joinedRmskTrack.c
deleted file mode 100644
index d1aead8..0000000
--- src/hg/hgTracks/joinedRmskTrack.c
+++ /dev/null
@@ -1,1182 +0,0 @@
-/* joinedRmskTrack - A comprehensive RepeatMasker visualization track
- *                   handler. This is an extension of the original
- *                   rmskTrack.c written by UCSC.
- *
- *  Written by Robert Hubley 10/2012
- *
- *  Modifications:
- *
- *  7/2014
- *     With the help of Jim Kent we modified the
- *     glyph design to more closely resemble the
- *     existing browser styles.
- */
-
-/* Copyright (C) 2014 The Regents of the University of California 
- * See README in this or parent directory for licensing information. */
-
-#include "common.h"
-#include "hash.h"
-#include "linefile.h"
-#include "jksql.h"
-#include "hdb.h"
-#include "hgTracks.h"
-#include "rmskJoined.h"
-
-
-/* DETAIL_VIEW_MAX_SCALE: The size ( max bp ) at which the
- * detailed view of repeats is turned on, otherwise it reverts
- * back to the original UCSC glyph.
- */
-#define DETAIL_VIEW_MAX_SCALE 30000
-
-/* MAX_UNALIGNED_PIXEL_LEN: The maximum size of unaligned sequence
- * to draw before switching to the unscaled view: ie. "----/###/---"
- * This is measured in pixels *not* base pairs due to the
- * mixture of scaled ( lines ) and unscaled ( text ) glyph
- * components.
- */
-#define MAX_UNALIGNED_PIXEL_LEN 150
-
-// TODO: Document
-#define LABEL_PADDING 5
-
-
-// TODO: Document
-static float pixelsPerBase = 1.0;
-
-/* Hash of the repeatItems ( tg->items ) for this track.
- *   This is used to hold display names for the lines of
- *   the track, the line heights, and class colors.
- */
-struct hash *classHash = NULL;
-static struct repeatItem *otherRepeatItem = NULL;
-
-/* Hash of subtracks
- *   The joinedRmskTrack is designed to be used as a composite track.
- *   When jRepeatLoad is called this hash is populated with the
- *   results of one or more table queries
- */
-struct hash *subTracksHash = NULL;
-
-struct subTrack
-{
-  // The number of display levels used in levels[]
-int levelCount;
-  // The rmskJoined records from table query
-struct rmskJoined *levels[30];
-};
-
-
-// Repeat Classes: Display names
-static char *rptClassNames[] = {
-"SINE", "LINE", "LTR", "DNA", "Simple", "Low Complexity", "Satellite",
-"RNA", "Other", "Unknown",
-};
-
-// Repeat Classes: Data names
-static char *rptClasses[] = {
-"SINE", "LINE", "LTR", "DNA", "Simple_repeat", "Low_complexity",
-"Satellite", "RNA", "Other", "Unknown",
-};
-
-
-/* Repeat class to color mappings. I took these from a
- * online color dictionary website:
- *
- *     http://people.csail.mit.edu/jaffer/Color/Dictionaries
- *
- *  I used the html4 catalog and tried to the 10 most distinct
- *  colors.
- *
- *  NOTE: If these are changed, do not forget to update the
- *        help table in joinedRmskTrack.html
- */
-static Color jRepeatClassColors[] = {
-0xff0000ff,			// SINE - red
-0xff00ff00,			// LINE - lime
-0xff000080,			// LTR - maroon
-0xffff00ff,			// DNA - fuchsia
-0xff00ffff,			// Simple - yellow
-0xff008080,			// LowComplex - olive
-0xffff0000,			// Satellite - blue
-0xff008000,			// RNA - green
-0xff808000,			// Other - teal
-0xffffff00,			// Unknown - aqua
-};
-
-// Basic range type
-struct Extents
-{
-int start;
-int end;
-};
-
-static struct Extents * getExtents (struct rmskJoined *rm)
-/* Calculate the glyph extents in genome coordinate
- * space ( ie. bp )
- *
- * It is not straightforward to determine the extent
- * of this track's glyph.  This is due to the mixture
- * of graphic and text elements within the glyph.
- *
- * TODO: Consider changing to graphics (ie. pixel) space.
- */
-{
-static struct Extents ex;
-char lenLabel[20];
-
-if (rm == NULL)
-    return NULL;
-
-ex.start = rm->alignStart
-    -
-    (int) ((mgFontStringWidth (tl.font, rm->name) +
-	    LABEL_PADDING) / pixelsPerBase);
-
-
-if ((rm->blockSizes[0] * pixelsPerBase) > MAX_UNALIGNED_PIXEL_LEN)
-    {
-    safef (lenLabel, sizeof (lenLabel), "%d", rm->blockSizes[0]);
-    ex.start -= (int) (MAX_UNALIGNED_PIXEL_LEN / pixelsPerBase) +
-	(int) ((mgFontStringWidth (tl.font, lenLabel) +
-		LABEL_PADDING) / pixelsPerBase);
-    }
-else
-    {
-    ex.start -= rm->blockSizes[0];
-    }
-
-ex.end = rm->alignEnd;
-
-if ((rm->blockSizes[rm->blockCount - 1] * pixelsPerBase) >
-    MAX_UNALIGNED_PIXEL_LEN)
-    {
-    safef (lenLabel, sizeof (lenLabel), "%d",
-	   rm->blockSizes[rm->blockCount - 1]);
-    ex.end +=
-	(int) (MAX_UNALIGNED_PIXEL_LEN / pixelsPerBase) +
-	(int) ((mgFontStringWidth (tl.font, lenLabel) +
-		LABEL_PADDING) / pixelsPerBase);
-    }
-else
-    {
-    ex.end += rm->blockSizes[rm->blockCount - 1];
-    }
-
-return &ex;
-}
-
-static int cmpRepeatVisStart (const void *va, const void *vb)
-/* Sort repeats by display start position.  Note: We
- * account for the fact we may not start the visual
- * display at chromStart.  See MAX_UNALIGNED_PIXEL_LEN.
- */
-{
-struct rmskJoined *a = *((struct rmskJoined **) va);
-struct rmskJoined *b = *((struct rmskJoined **) vb);
-
-struct Extents *ext = NULL;
-ext = getExtents (a);
-int aStart = ext->start;
-ext = getExtents (b);
-int bStart = ext->start;
-
-return (aStart - bStart);
-}
-
-static struct repeatItem * makeJRepeatItems ()
-/* Initialize the track */
-{
-classHash = newHash (6);
-struct repeatItem *ri, *riList = NULL;
-int i;
-int numClasses = ArraySize (rptClasses);
-for (i = 0; i < numClasses; ++i)
-    {
-    AllocVar (ri);
-    ri->class = rptClasses[i];
-    ri->className = rptClassNames[i];
-    // New color attribute
-    ri->color = jRepeatClassColors[i];
-    slAddHead (&riList, ri);
-    // Hash now prebuilt to hold color attributes
-    hashAdd (classHash, ri->class, ri);
-    if (sameString (rptClassNames[i], "Other"))
-        otherRepeatItem = ri;
-    }
-slReverse (&riList);
-return riList;
-}
-
-static void jRepeatLoad (struct track *tg)
-/* We do the query(ies) here so we can report how deep the track(s)
- * will be when jRepeatTotalHeight() is called later on.
- */
-{
-  /*
-   * Initialize the subtracks hash - This will eventually contain
-   * all the repeat data for each displayed subtrack.
-   */
-if (!subTracksHash)
-    subTracksHash = newHash (20);
-
-tg->items = makeJRepeatItems ();
-
-int baseWidth = winEnd - winStart;
-pixelsPerBase = (float) insideWidth / (float) baseWidth;
-if (tg->visibility == tvFull && baseWidth <= DETAIL_VIEW_MAX_SCALE)
-    {
-    struct subTrack *st = NULL;
-    AllocVar (st);
-    if (st)
-	{
-	st->levels[0] = NULL;
-	st->levelCount = 0;
-	struct rmskJoined *rm = NULL;
-	char **row;
-	int rowOffset;
-	struct sqlConnection *conn = hAllocConn (database);
-	struct sqlResult *sr = hRangeQuery (conn, tg->table, chromName,
-					    winStart, winEnd, NULL,
-					    &rowOffset);
-	struct rmskJoined *detailList = NULL;
-	while ((row = sqlNextRow (sr)) != NULL)
-	    {
-	    rm = rmskJoinedLoad (row + rowOffset);
-	    slAddHead (&detailList, rm);
-	    }
-	slSort (&detailList, cmpRepeatVisStart);
-
-	sqlFreeResult (&sr);
-	hFreeConn (&conn);
-
-	int crChromStart, crChromEnd;
-	while (detailList)
-	    {
-	    st->levels[st->levelCount++] = detailList;
-
-	    struct rmskJoined *cr = detailList;
-	    detailList = detailList->next;
-	    cr->next = NULL;
-	    int rmChromStart, rmChromEnd;
-	    struct rmskJoined *prev = NULL;
-	    rm = detailList;
-
-	    struct Extents *ext = NULL;
-	    ext = getExtents (cr);
-	    crChromStart = ext->start;
-	    crChromEnd = ext->end;
-
-	    while (rm)
-		{
-		ext = getExtents (rm);
-		rmChromStart = ext->start;
-		rmChromEnd = ext->end;
-
-		if (rmChromStart > crChromEnd)
-		    {
-		    cr->next = rm;
-		    cr = rm;
-		    crChromStart = rmChromStart;
-		    crChromEnd = rmChromEnd;
-		    if (prev)
-			prev->next = rm->next;
-		    else
-			detailList = rm->next;
-
-		    rm = rm->next;
-		    cr->next = NULL;
-		    }
-		else
-		    {
-		    // Save for a lower level
-		    prev = rm;
-		    rm = rm->next;
-		    }
-		}		// while ( rm )
-	    }			// while ( detailList )
-	// Create Hash Entry
-	hashReplace (subTracksHash, tg->table, st);
-	}			// if ( st )
-    }				// if ( tg->visibility == tvFull
-}
-
-static void jRepeatFree (struct track *tg)
-/* Free up jRepeatMasker items. */
-{
-slFreeList (&tg->items);
-}
-
-static char * jRepeatName (struct track *tg, void *item)
-/* Return name of jRepeat item track. */
-{
-static char empty = '\0';
-struct repeatItem *ri = item;
-  /*
-   * In detail view mode the items represent different packing
-   * levels.  No need to display a label at each level.  Instead
-   * Just return a label for the first level.
-   */
-if (tg->limitedVis == tvFull && winBaseCount <= DETAIL_VIEW_MAX_SCALE)
-    {
-    if (strcmp (ri->className, "SINE") == 0)
-	return ("Repeats");
-    else
-	return &empty;
-    }
-return ri->className;
-}
-
-int jRepeatTotalHeight (struct track *tg, enum trackVisibility vis)
-{
-  // Are we in full view mode and at the scale needed to display
-  // the detail view?
-if (tg->limitedVis == tvFull && winBaseCount <= DETAIL_VIEW_MAX_SCALE)
-    {
-    // Lookup the depth of this subTrack and report it
-    struct subTrack *st = hashFindVal (subTracksHash, tg->table);
-    if (st)
-        return ((st->levelCount + 1) * 24);
-    else
-        return (24);	// Just display one line
-    }
-else
-return tgFixedTotalHeightNoOverflow (tg, vis);
-}
-
-int jRepeatItemHeight (struct track *tg, void *item)
-{
-  // Are we in full view mode and at the scale needed to display
-  // the detail view?
-if (tg->limitedVis == tvFull && winBaseCount <= DETAIL_VIEW_MAX_SCALE)
-    return 24;
-else
-    return tgFixedItemHeight (tg, item);
-}
-
-static void drawDashedHorizLine (struct hvGfx *hvg, int x1, int x2,
-		     int y, int dashLen, int gapLen, Color lineColor)
-// ie.    - - - - - - - - - - - - - - - -
-{
-int cx1 = x1;
-int cx2;
-while (1)
-    {
-    cx2 = cx1 + dashLen;
-    if (cx2 > x2)
-        cx2 = x2;
-    hvGfxLine (hvg, cx1, y, cx2, y, lineColor);
-    cx1 += (dashLen + gapLen);
-    if (cx1 > x2)
-        break;
-    }
-}
-
-static void drawDashedHorizLineWHash (struct hvGfx *hvg, int x1, int x2,
-			  int y, int dashLen, int gapLen, Color lineColor,
-			  int unalignedLen)
-// ie.    - - - - - - -\234\- - - - - - - - -
-{
-int cx1 = x1;
-int cx2;
-
-char lenLabel[20];
-safef (lenLabel, sizeof (lenLabel), "%d", unalignedLen);
-MgFont *font = tl.font;
-int fontHeight = tl.fontHeight;
-int stringWidth = mgFontStringWidth (font, lenLabel) + LABEL_PADDING;
-
-int glyphWidth = x2 - x1;
-
-if (glyphWidth < stringWidth + 6 + (2 * dashLen))
-    stringWidth = 0;
-
-int midX = ((glyphWidth) / 2) + x1;
-int startHash = midX - (stringWidth * 0.5);
-int midPointDrawn = 0;
-
-  /*
-     Degrade Gracefully:
-     * Too little space to draw dashes or even
-     * hash marks, give up.
-   */
-if (glyphWidth < 6 + dashLen)
-    {
-    hvGfxLine (hvg, x1, y, x2, y, lineColor);
-    return;
-    }
-if (glyphWidth < 6 + (2 * dashLen))
-    {
-    midX -= 3;
-    hvGfxLine (hvg, x1, y, midX, y, lineColor);
-    hvGfxLine (hvg, midX, y - 3, midX + 3, y + 3, lineColor);
-    hvGfxLine (hvg, midX + 3, y - 3, midX + 6, y + 3, lineColor);
-    hvGfxLine (hvg, midX + 6, y, x2, y, lineColor);
-    return;
-    }
-
-while (1)
-    {
-    cx2 = cx1 + dashLen;
-    if (cx2 > x2)
-        cx2 = x2;
-
-    if (!midPointDrawn && cx2 > startHash)
-	{
-	// Draw double slashes "\\" instead of dash
-	hvGfxLine (hvg, cx1, y - 3, cx1 + 3, y + 3, lineColor);
-	if (stringWidth)
-	    {
-	    hvGfxTextCentered (hvg, cx1 + 3, y - 3, stringWidth,
-			       fontHeight, MG_BLACK, font, lenLabel);
-	    cx1 += stringWidth;
-	    }
-	hvGfxLine (hvg, cx1 + 3, y - 3, cx1 + 6, y + 3, lineColor);
-	cx1 += 6;
-	midPointDrawn = 1;
-	}
-    else
-	{
-	// Draw a dash
-	hvGfxLine (hvg, cx1, y, cx2, y, lineColor);
-	cx1 += dashLen;
-	}
-
-    if (!midPointDrawn && cx1 + gapLen > midX)
-	{
-	// Draw double slashes "\\" instead of gap
-	hvGfxLine (hvg, cx1, y - 3, cx1 + 3, y + 3, lineColor);
-	if (stringWidth)
-	    {
-	    hvGfxTextCentered (hvg, cx1 + 3, y - 3, stringWidth,
-			       fontHeight, MG_BLACK, font, lenLabel);
-	    cx1 += stringWidth;
-	    }
-	hvGfxLine (hvg, cx1 + 3, y - 3, cx1 + 6, y + 3, lineColor);
-	cx1 += 6;
-	midPointDrawn = 1;
-	}
-    else
-	{
-	cx1 += gapLen;
-	}
-
-    if (cx1 > x2)
-        break;
-    }
-}
-
-static void drawNormalBox (struct hvGfx *hvg, int x1, int y1,
-	       int width, int height, Color fillColor, Color outlineColor)
-{
-struct gfxPoly *poly = gfxPolyNew ();
-int y2 = y1 + height;
-int x2 = x1 + width;
-  /*
-   *     1,5--------------2
-   *       |              |
-   *       |              |
-   *       |              |
-   *       4--------------3
-   */
-gfxPolyAddPoint (poly, x1, y1);
-gfxPolyAddPoint (poly, x2, y1);
-gfxPolyAddPoint (poly, x2, y2);
-gfxPolyAddPoint (poly, x1, y2);
-gfxPolyAddPoint (poly, x1, y1);
-hvGfxDrawPoly (hvg, poly, fillColor, TRUE);
-hvGfxDrawPoly (hvg, poly, outlineColor, FALSE);
-gfxPolyFree (&poly);
-}
-
-static void drawBoxWChevrons (struct hvGfx *hvg, int x1, int y1,
-		  int width, int height, Color fillColor, Color outlineColor,
-		  char strand)
-{
-drawNormalBox (hvg, x1, y1, width, height, fillColor, outlineColor);
-static Color white = 0xffffffff;
-int dir = (strand == '+' ? 1 : -1);
-int midY = y1 + ((height) >> 1);
-clippedBarbs (hvg, x1 + 1, midY, width, ((height >> 1) - 2), 5,
-	      dir, white, TRUE);
-}
-
-static void drawRMGlyph (struct hvGfx *hvg, int y, int heightPer,
-	     int width, int baseWidth, int xOff, struct rmskJoined *rm)
-/*
- *  Draw a detailed RepeatMasker annotation glyph given
- *  a single rmskJoined structure.
- *
- *  A couple of caveats about the use of the rmskJoined
- *  structure to hold a RepeatMasker annotation.
- *
- *  chromStart/chromEnd:  These represent genomic coordinates
- *                        that mark the extents of graphics
- *                        annotation on the genome.  I.e
- *                        aligned blocks + unaligned consensus
- *                        blocks.  The code below may not
- *                        draw to these extents in some cases.
- *
- *  score:  This represents the average divergence of the
- *          individual aligned blocks.  It is a percentage
- *          * 100.  Ie. 23.11 % is encoded as the integer 2311.
- *
- *  blockRelStarts:  Two types of blocks are interwoven in this
- *                format.  Aligned and unaligned blocks.  Aligned
- *                blocks will have a value >= 0 representing the
- *                relative position from chromStart for this
- *                start of this block.  A value of -1 for chromStart
- *                is indicative of unaligned block and starts from
- *                the end of the last aligned block on the chromosome
- *                or from chromStart if it's the first block in the list.
- *
- *  name:  Stores the id#class/family
- *
- *  rgb:  Unused at this time
- *
- *  description: Unused but the intention would be to store
- *               the RepeatMasker *.out lines which make up
- *               all the aligned sections of this joined
- *               annotation.
- *
- *  blockSizes:   As you would expect.
- *
- *  Here is an example:
- *                ie.
- *                A forward strand RM annotation from chr1:186-196
- *                which is aligned to a 100 bp repeat from 75-84
- *                in the consensus would be represented as:
- *
- *                chromStart: 111
- *                chromEnd: 212
- *                blockRelStarts: -1, 75, -1
- *                blockSizes: 75, 10, 16
- *
- */
-{
-int idx;
-int lx1, lx2;
-int cx1, cx2;
-int w;
-struct repeatItem *ri;
-  /*
-   * heightPer is the God given height of a single
-   * track item...respect your overlord.
-   */
-int alignedBlockHeight = heightPer * 0.5;
-int alignedBlockOffset = heightPer - alignedBlockHeight;
-int unalignedBlockHeight = heightPer * 0.75;
-int unalignedBlockOffset = heightPer - unalignedBlockHeight;
-
-Color black = hvGfxFindColorIx (hvg, 0, 0, 0);
-Color fillColor = shadesOfGray[5];
-Color outlineColor = jRepeatClassColors[0];
-
-  // Break apart the name and get the class of the
-  // repeat.
-char class[256];
-  // Simplify repClass for lookup: strip trailing '?',
-  // simplify *RNA to RNA:
-char *poundPtr = index (rm->name, '#');
-if (poundPtr)
-    {
-    safecpy (class, sizeof (class), poundPtr + 1);
-    char *slashPtr = index (class, '/');
-    if (slashPtr)
-        *slashPtr = '\0';
-    }
-else
-    {
-    safecpy (class, sizeof (class), "Unknown");
-    }
-char *p = &(class[strlen (class) - 1]);
-if (*p == '?')
-    *p = '\0';
-if (endsWith (class, "RNA"))
-    safecpy (class, sizeof (class), "RNA");
-
-  // Lookup the class to get the color scheme
-ri = hashFindVal (classHash, class);
-if (ri == NULL)
-    ri = otherRepeatItem;
-
-  // Pick the fill color based on the divergence
-int percId = 10000 - rm->score;
-int grayLevel = grayInRange (percId, 6000, 10000);
-fillColor = shadesOfGray[grayLevel];
-outlineColor = ri->color;
-
-  // Draw from left to right
-for (idx = 0; idx < rm->blockCount; idx++)
-    {
-    int fragGStart = rm->blockRelStarts[idx];
-
-    /*
-     *  Assumptions about blockCount
-     *   - first aligned block = 1, the block 0 is
-     *     the unaligned consnesus either 5' or 3' of
-     *     this block.
-     *   - The last aligned block is blockCount - 1;
-     */
-    if (fragGStart > -1)
-	{
-	// Aligned Block
-	int fragSize = rm->blockSizes[idx];
-	fragGStart += rm->chromStart;
-	int fragGEnd = fragGStart + fragSize;
-	lx1 = roundingScale (fragGStart - winStart, width, baseWidth) + xOff;
-	lx1 = max (lx1, 0);
-	lx2 = roundingScale (fragGEnd - winStart, width, baseWidth) + xOff;
-	w = lx2 - lx1;
-	if (w <= 0)
-	    w = 1;
-
-	if (idx == 1 && rm->blockCount == 3)
-	    {
-	    // One and only one aligned block
-	    drawBoxWChevrons (hvg, lx1, y + alignedBlockOffset, w,
-			      alignedBlockHeight, fillColor,
-			      outlineColor, rm->strand[0]);
-	    }
-	else if (idx == 1)
-	    {
-	    // First block
-	    if (rm->strand[0] == '-')
-		{
-		// First block on negative strand is the point block
-		drawBoxWChevrons (hvg, lx1,
-				  y + alignedBlockOffset, w,
-				  alignedBlockHeight, fillColor,
-				  outlineColor, rm->strand[0]);
-		}
-	    else
-		{
-		// First block on the positive strand is the tail block
-		drawBoxWChevrons (hvg, lx1,
-				  y + alignedBlockOffset, w,
-				  alignedBlockHeight, fillColor,
-				  outlineColor, rm->strand[0]);
-
-		}
-	    }
-	else if (idx == (rm->blockCount - 2))
-	    {
-	    // Last block
-	    if (rm->strand[0] == '-')
-		{
-		// Last block on the negative strand is the tail block
-		drawBoxWChevrons (hvg, lx1,
-				  y + alignedBlockOffset, w,
-				  alignedBlockHeight, fillColor,
-				  outlineColor, rm->strand[0]);
-
-		}
-	    else
-		{
-		// Last block on the positive strand is the poitn block
-		drawBoxWChevrons (hvg, lx1,
-				  y + alignedBlockOffset, w,
-				  alignedBlockHeight, fillColor,
-				  outlineColor, rm->strand[0]);
-
-		}
-	    }
-	else
-	    {
-	    // Intermediate aligned blocks are drawn as rectangles
-	    drawBoxWChevrons (hvg, lx1, y + alignedBlockOffset, w,
-			      alignedBlockHeight, fillColor,
-			      outlineColor, rm->strand[0]);
-	    }
-
-	}
-    else
-	{
-	// Unaligned Block
-	int relStart = 0;
-	if (idx == 0)
-	    {
-	    /*
-	     * Unaligned sequence at the start of an annotation
-	     * Draw as:
-	     *     |-------------     or |------//------
-	     *                  |                      |
-	     *                  >>>>>>>                >>>>>>>>
-	     */
-	    lx2 = roundingScale (rm->chromStart +
-				 rm->blockRelStarts[idx + 1] -
-				 winStart, width, baseWidth) + xOff;
-	    if ((rm->blockSizes[idx] * pixelsPerBase) >
-		MAX_UNALIGNED_PIXEL_LEN)
-		{
-		lx1 = roundingScale (rm->chromStart +
-				     (rm->blockRelStarts[idx + 1] -
-				      (int)
-				      (MAX_UNALIGNED_PIXEL_LEN /
-				       pixelsPerBase)) -
-				     winStart, width, baseWidth) + xOff;
-		// Line Across
-		drawDashedHorizLineWHash (hvg, lx1, lx2,
-					  y +
-					  unalignedBlockOffset,
-					  5, 5, black, rm->blockSizes[idx]);
-		}
-	    else
-		{
-		lx1 = roundingScale (rm->chromStart - winStart,
-				     width, baseWidth) + xOff;
-		// Line Across
-		drawDashedHorizLine (hvg, lx1, lx2,
-				     y + unalignedBlockOffset, 5, 5, black);
-		}
-	    // Line down
-	    hvGfxLine (hvg, lx2, y + alignedBlockOffset, lx2,
-		       y + unalignedBlockOffset, black);
-	    hvGfxLine (hvg, lx1, y + unalignedBlockOffset - 3, lx1,
-		       y + unalignedBlockOffset + 3, black);
-
-	    // Draw labels
-	    MgFont *font = tl.font;
-	    int fontHeight = tl.fontHeight;
-	    int stringWidth =
-		mgFontStringWidth (font, rm->name) + LABEL_PADDING;
-	    hvGfxTextCentered (hvg, lx1 - stringWidth,
-			       y + unalignedBlockOffset + fontHeight,
-			       stringWidth, fontHeight, MG_BLACK, font,
-			       rm->name);
-
-
-	    }
-	else if (idx == (rm->blockCount - 1))
-	    {
-	    /*
-	     * Unaligned sequence at the end of an annotation
-	     * Draw as:
-	     *       -------------|   or        ------//------|
-	     *       |                          |
-	     *  >>>>>                    >>>>>>>
-	     */
-	    lx1 = roundingScale (rm->chromStart +
-				 rm->blockRelStarts[idx - 1] +
-				 rm->blockSizes[idx - 1] - winStart,
-				 width, baseWidth) + xOff;
-	    if ((rm->blockSizes[idx] * pixelsPerBase) >
-		MAX_UNALIGNED_PIXEL_LEN)
-		{
-		lx2 = roundingScale (rm->chromStart +
-				     rm->blockRelStarts[idx -
-							1] +
-				     rm->blockSizes[idx - 1] +
-				     (int)
-				     (MAX_UNALIGNED_PIXEL_LEN /
-				      pixelsPerBase) - winStart,
-				     width, baseWidth) + xOff;
-		// Line Across
-		drawDashedHorizLineWHash (hvg, lx1, lx2,
-					  y +
-					  unalignedBlockOffset,
-					  5, 5, black, rm->blockSizes[idx]);
-		}
-	    else
-		{
-		lx2 = roundingScale (rm->chromStart +
-				     rm->blockRelStarts[idx -
-							1] +
-				     rm->blockSizes[idx - 1] +
-				     rm->blockSizes[idx] -
-				     winStart, width, baseWidth) + xOff;
-		// Line Across
-		drawDashedHorizLine (hvg, lx1, lx2,
-				     y + unalignedBlockOffset, 5, 5, black);
-		}
-	    // Line down
-	    hvGfxLine (hvg, lx1, y + alignedBlockOffset, lx1,
-		       y + unalignedBlockOffset, black);
-	    hvGfxLine (hvg, lx2, y + unalignedBlockOffset - 3, lx2,
-		       y + unalignedBlockOffset + 3, black);
-	    }
-	else
-	    {
-	    /*
-	     * Middle Unaligned
-	     * Draw unaligned sequence between aligned fragments
-	     * as:       .........
-	     *          /         \
-	     *     >>>>>           >>>>>>
-	     *
-	     * or:
-	     *         .............
-	     *         \           /
-	     *     >>>>>           >>>>>>
-	     *
-	     * Also use ....//.... to indicate not to scale if
-	     * necessary.
-	     *
-	     */
-	    int alignedGapSize = rm->blockRelStarts[idx + 1] -
-		(rm->blockRelStarts[idx - 1] + rm->blockSizes[idx - 1]);
-	    int unaSize = rm->blockSizes[idx];
-
-	    int alignedOverlapSize = unaSize - alignedGapSize;
-
-	    if (unaSize < 0)
-		{
-		relStart =
-		    rm->blockRelStarts[idx - 1] +
-		    rm->blockSizes[idx - 1] - (alignedOverlapSize / 2);
-
-		if (abs (unaSize) > rm->blockSizes[idx - 1])
-		    unaSize = -rm->blockSizes[idx - 1];
-
-		lx1 = roundingScale (rm->chromStart +
-				     rm->blockRelStarts[idx -
-							1] +
-				     rm->blockSizes[idx - 1] +
-				     unaSize - winStart, width,
-				     baseWidth) + xOff;
-		lx1 = max (lx1, 0);
-		lx2 = roundingScale (rm->chromStart +
-				     rm->blockRelStarts[idx +
-							1] -
-				     winStart, width, baseWidth) + xOff;
-
-		int midPoint = ((lx2 - lx1) / 2) + lx1;
-
-		// Block Intersection Line
-		hvGfxLine (hvg, lx1, y + alignedBlockOffset, lx1,
-			   y + alignedBlockOffset + alignedBlockHeight,
-			   black);
-
-		// Line Up
-		hvGfxLine (hvg, lx1, y + alignedBlockOffset,
-			   midPoint, y + unalignedBlockOffset, black);
-
-		// Line Down
-		hvGfxLine (hvg, lx2, y + alignedBlockOffset,
-			   midPoint, y + unalignedBlockOffset, black);
-
-		}
-	    else if (alignedOverlapSize > 0 &&
-		     ((alignedOverlapSize * 0.5) >
-		      (0.3 * rm->blockSizes[idx - 1])
-		      || (alignedOverlapSize * 0.5) >
-		      (0.3 * rm->blockSizes[idx + 1])))
-		{
-		// Need to shorten unaligned length
-		int smallOverlapLen = 0;
-		smallOverlapLen = (0.3 * rm->blockSizes[idx - 1]);
-		if (smallOverlapLen > (0.3 * rm->blockSizes[idx + 1]))
-		    smallOverlapLen = (0.3 * rm->blockSizes[idx + 1]);
-		unaSize = (smallOverlapLen * 2) + alignedGapSize;
-		relStart =
-		    rm->blockRelStarts[idx - 1] +
-		    rm->blockSizes[idx - 1] - smallOverlapLen;
-		lx1 = roundingScale (relStart + rm->chromStart -
-				     winStart, width, baseWidth) + xOff;
-		lx1 = max (lx1, 0);
-		lx2 = roundingScale (relStart + rm->chromStart +
-				     unaSize - winStart, width,
-				     baseWidth) + xOff;
-		// Line Up
-		cx1 = roundingScale (rm->chromStart +
-				     rm->blockRelStarts[idx -
-							1] +
-				     rm->blockSizes[idx - 1] -
-				     winStart, width, baseWidth) + xOff;
-		hvGfxLine (hvg, cx1, y + alignedBlockOffset, lx1,
-			   y + unalignedBlockOffset, black);
-
-		// Line Across
-		drawDashedHorizLineWHash (hvg, lx1, lx2,
-					  y +
-					  unalignedBlockOffset,
-					  5, 5, black, rm->blockSizes[idx]);
-		// Line Down
-		cx2 = roundingScale (rm->chromStart +
-				     rm->blockRelStarts[idx +
-							1] -
-				     winStart, width, baseWidth) + xOff;
-		hvGfxLine (hvg, cx2, y + alignedBlockOffset, lx2,
-			   y + unalignedBlockOffset, black);
-		}
-	    else
-		{
-		// Adequate to display full length
-		relStart =
-		    rm->blockRelStarts[idx - 1] +
-		    rm->blockSizes[idx - 1] - (alignedOverlapSize / 2);
-		lx1 = roundingScale (relStart + rm->chromStart -
-				     winStart, width, baseWidth) + xOff;
-		lx1 = max (lx1, 0);
-		lx2 = roundingScale (relStart + rm->chromStart +
-				     unaSize - winStart, width,
-				     baseWidth) + xOff;
-		// Line Up
-		int cx1 =
-		    roundingScale (rm->chromStart +
-				   rm->blockRelStarts[idx - 1] +
-				   rm->blockSizes[idx - 1] - winStart,
-				   width, baseWidth) + xOff;
-		hvGfxLine (hvg, cx1, y + alignedBlockOffset, lx1,
-			   y + unalignedBlockOffset, black);
-		drawDashedHorizLine (hvg, lx1, lx2,
-				     y + unalignedBlockOffset, 5, 5, black);
-		// Line Down
-		cx2 = roundingScale (rm->chromStart +
-				     rm->blockRelStarts[idx +
-							1] -
-				     winStart, width, baseWidth) + xOff;
-		hvGfxLine (hvg, cx2, y + alignedBlockOffset, lx2,
-			   y + unalignedBlockOffset, black);
-		}
-	    }
-	}
-    }
-
-}
-
-static void origRepeatDraw (struct track *tg, int seqStart, int seqEnd,
-		struct hvGfx *hvg, int xOff, int yOff, int width,
-		MgFont * font, Color color, enum trackVisibility vis)
-/* This is the original repeat drawing routine, modified
- * to handle the new rmskJoined table structure.
- */
-{
-int baseWidth = seqEnd - seqStart;
-struct repeatItem *ri;
-int y = yOff;
-int heightPer = tg->heightPer;
-int lineHeight = tg->lineHeight;
-int x1, x2, w;
-boolean isFull = (vis == tvFull);
-Color col;
-struct sqlConnection *conn = hAllocConn (database);
-struct sqlResult *sr = NULL;
-char **row;
-int rowOffset;
-
-
-if (isFull)
-    {
-    /*
-     * Do gray scale representation spread out among tracks.
-     */
-    struct hash *hash = newHash (6);
-    struct rmskJoined *ro;
-    int percId;
-    int grayLevel;
-
-    for (ri = tg->items; ri != NULL; ri = ri->next)
-	{
-	ri->yOffset = y;
-	y += lineHeight;
-	hashAdd (hash, ri->class, ri);
-	}
-    sr = hRangeQuery (conn, tg->table, chromName, winStart, winEnd, NULL,
-		      &rowOffset);
-    while ((row = sqlNextRow (sr)) != NULL)
-	{
-	ro = rmskJoinedLoad (row + rowOffset);
-	char class[256];
-	// Simplify repClass for lookup: strip trailing '?',
-	// simplify *RNA to RNA:
-	char *poundPtr = index (ro->name, '#');
-	if (poundPtr)
-	    {
-	    safecpy (class, sizeof (class), poundPtr + 1);
-	    char *slashPtr = index (class, '/');
-	    if (slashPtr)
-	        *slashPtr = '\0';
-	    }
-	else
-	    {
-	    safecpy (class, sizeof (class), "Unknown");
-	    }
-	char *p = &(class[strlen (class) - 1]);
-	if (*p == '?')
-	    *p = '\0';
-	if (endsWith (class, "RNA"))
-	    safecpy (class, sizeof (class), "RNA");
-	ri = hashFindVal (hash, class);
-	if (ri == NULL)
-	    ri = otherRepeatItem;
-	percId = 10000 - ro->score;
-	grayLevel = grayInRange (percId, 6000, 10000);
-	col = shadesOfGray[grayLevel];
-
-	int idx = 0;
-	for (idx = 0; idx < ro->blockCount; idx++)
-	    {
-	    if (ro->blockRelStarts[idx] > 0)
-		{
-		int blockStart = ro->chromStart + ro->blockRelStarts[idx];
-		int blockEnd =
-		    ro->chromStart + ro->blockRelStarts[idx] +
-		    ro->blockSizes[idx];
-
-		x1 = roundingScale (blockStart - winStart, width,
-				    baseWidth) + xOff;
-		x1 = max (x1, 0);
-		x2 = roundingScale (blockEnd - winStart, width,
-				    baseWidth) + xOff;
-		w = x2 - x1;
-		if (w <= 0)
-		    w = 1;
-		hvGfxBox (hvg, x1, ri->yOffset, w, heightPer, col);
-		}
-	    }
-	rmskJoinedFree (&ro);
-	}
-    freeHash (&hash);
-    }
-else
-    {
-    char table[64];
-    boolean hasBin;
-    struct dyString *query = newDyString (1024);
-    /*
-     * Do black and white on single track.  Fetch less than
-     * we need from database.
-     */
-    if (hFindSplitTable (database, chromName, tg->table, table, &hasBin))
-	{
-	sqlDyStringPrintf (query,
-			"select chromStart,blockCount,blockSizes,"
-			"blockRelStarts from %s where ", table);
-	if (hasBin)
-	    hAddBinToQuery (winStart, winEnd, query);
-	sqlDyStringPrintf (query, "chromStart<%u and chromEnd>%u ",
-			winEnd, winStart);
-	/*
-	 * if we're using a single rmsk table, add chrom to the where clause
-	 */
-	if (startsWith ("rmskJoined", table))
-	    sqlDyStringPrintf (query, " and chrom = '%s' ", chromName);
-	sr = sqlGetResult (conn, query->string);
-	while ((row = sqlNextRow (sr)) != NULL)
-	    {
-	    int idx = 0;
-	    int blockCount = sqlSigned (row[1]);
-	    int sizeOne;
-	    int *blockSizes;
-	    int *blockRelStarts;
-	    int chromStart = sqlUnsigned (row[0]);
-	    sqlSignedDynamicArray (row[2], &blockSizes, &sizeOne);
-	    assert (sizeOne == blockCount);
-	    sqlSignedDynamicArray (row[3], &blockRelStarts, &sizeOne);
-	    assert (sizeOne == blockCount);
-
-	    for (idx = 1; idx < blockCount - 1; idx++)
-		{
-		if (blockRelStarts[idx] >= 0)
-		    {
-		    int blockStart = chromStart + blockRelStarts[idx];
-		    int blockEnd =
-			chromStart + blockRelStarts[idx] + blockSizes[idx];
-
-		    x1 = roundingScale (blockStart - winStart,
-					width, baseWidth) + xOff;
-		    x1 = max (x1, 0);
-		    x2 = roundingScale (blockEnd - winStart, width,
-					baseWidth) + xOff;
-		    w = x2 - x1;
-		    if (w <= 0)
-		        w = 1;
-		    hvGfxBox (hvg, x1, yOff, w, heightPer, MG_BLACK);
-		    }
-		}
-	    }
-	}
-    dyStringFree (&query);
-    }
-sqlFreeResult (&sr);
-hFreeConn (&conn);
-}
-
-/* Main callback for displaying this track in the viewport
- * of the browser.
- */
-static void jRepeatDraw (struct track *tg, int seqStart, int seqEnd,
-	     struct hvGfx *hvg, int xOff, int yOff, int width,
-	     MgFont * font, Color color, enum trackVisibility vis)
-{
-int baseWidth = seqEnd - seqStart;
-
-// TODO: Document
-pixelsPerBase = (float) width / (float) baseWidth;
-  /*
-   * Its unclear to me why heightPer is not updated to the
-   * value set in jRepeatItemHeight() at the time this callback
-   * is invoked.  Getting the correct value myself.
-   * was:
-   * int heightPer = tg->heightPer;
-   */
-int heightPer = jRepeatItemHeight (tg, NULL);
-boolean isFull = (vis == tvFull);
-struct rmskJoined *rm;
-
-  // If we are in full view mode and the scale is sufficient,
-  // display the new visualization.
-if (isFull && baseWidth <= DETAIL_VIEW_MAX_SCALE)
-    {
-    int level = yOff;
-
-    struct subTrack *st = hashFindVal (subTracksHash, tg->table);
-    if (!st)
-	return;
-
-    int lidx = st->levelCount;
-    int currLevel = 0;
-    for (currLevel = 0; currLevel < lidx; currLevel++)
-	{
-	rm = st->levels[currLevel];
-	while (rm)
-	    {
-	    drawRMGlyph (hvg, level, heightPer, width, baseWidth, xOff, rm);
-
-	    char statusLine[128];
-	    int ss1 = roundingScale (rm->alignStart - winStart,
-				     width, baseWidth) + xOff;
-
-	    safef (statusLine, sizeof (statusLine), "%s", rm->name);
-
-	    int x1 = roundingScale (rm->alignStart - winStart, width,
-				    baseWidth) + xOff;
-	    x1 = max (x1, 0);
-	    int x2 = roundingScale (rm->alignEnd - winStart, width,
-				    baseWidth) + xOff;
-	    int w = x2 - x1;
-	    if (w <= 0)
-	        w = 1;
-
-	    mapBoxHc (hvg, rm->alignStart, rm->alignEnd, ss1, level,
-		      w, heightPer, tg->track, rm->id, statusLine);
-	    rm = rm->next;
-	    }
-	level += heightPer;
-	rmskJoinedFreeList (&(st->levels[currLevel]));
-	}
-    }
-else
-    {
-    // Draw the stereotypical view
-    origRepeatDraw (tg, seqStart, seqEnd,
-		    hvg, xOff, yOff, width, font, color, vis);
-    }
-}
-
-void jRepeatMethods (struct track *tg)
-{
-tg->loadItems = jRepeatLoad;
-tg->freeItems = jRepeatFree;
-tg->drawItems = jRepeatDraw;
-tg->colorShades = shadesOfGray;
-tg->itemName = jRepeatName;
-tg->mapItemName = jRepeatName;
-tg->totalHeight = jRepeatTotalHeight;
-tg->itemHeight = jRepeatItemHeight;
-tg->itemStart = tgItemNoStart;
-tg->itemEnd = tgItemNoEnd;
-tg->mapsSelf = TRUE;
-}