76bde04179c67dde93143803a1502cb80e8abc33
kent
  Thu Jun 30 11:27:08 2022 -0700
Making qInserts be rendered as two bases wide rather than always a single pixel line.  If zoomed in enough will show size of insert in query as a number in the middle of the box.  See also redmine #29642. Also qInserts are drawn after, not before, the red blocks of base mismatches.

diff --git src/hg/hgTracks/cds.c src/hg/hgTracks/cds.c
index ed74e51..7b6b064 100644
--- src/hg/hgTracks/cds.c
+++ src/hg/hgTracks/cds.c
@@ -339,33 +339,49 @@
 /* Draw a 1-pixel wide vertical line at the given chromosomal coord.
  * The line is 0 bases wide (chromStart==chromEnd) but that doesn't
  * matter if we're zoomed out to >1base/pixel, so this is OK for diffs
  * when zoomed way out and for insertion points at any scale. */
 {
 int thisX = round((double)(chromStart-winStart)*scale) + xOff;
 int thisY = y;
 int thisHeight = height;
 if ((chromStart < lf->tallStart) || (chromStart > lf->tallEnd))
     {
     /* adjust for UTR. WARNING: this duplicates shortOff & shortHeight
      * calculations in linkedFeaturesDrawAt */
     thisY += height/4;
     thisHeight = height - height/2;
     }
-hvGfxLine(hvg, thisX, thisY, thisX, thisY+thisHeight, color);
+hvGfxBox(hvg, thisX-2, thisY, 4, thisHeight, color);
 }
 
+static void drawMidSize(struct linkedFeatures *lf, struct hvGfx *hvg,
+                         int chromStart, int xOff, int y,
+			 int height, double scale, Color color, MgFont *font, int size)
+/* Draw a short string encoding size around chromStart */
+/* Draw a 1-pixel wide vertical line at the given chromosomal coord.
+ * The line is 0 bases wide (chromStart==chromEnd) but that doesn't
+ * matter if we're zoomed out to >1base/pixel, so this is OK for diffs
+ * when zoomed way out and for insertion points at any scale. */
+{
+char sizeString[32];
+safef(sizeString, sizeof(sizeString), "%d", size);
+drawScaledBoxLabel(hvg,  chromStart-1, chromStart+1, 
+    scale, xOff, y, height, color, font, sizeString);
+}
+
+
 
 static void drawCdsDiffBaseTickmarksOnly(struct track *tg,
 	struct linkedFeatures *lf,
 	struct hvGfx *hvg, int xOff,
 	int y, double scale, int heightPer,
 	struct dnaSeq *qSeq, int qOffset, struct psl *psl,
 	int winStart)
 /* Draw thin vertical red lines only where mRNA bases differ from genomic.  
  * This assumes that lf has been drawn already, we're zoomed out past 
  * zoomedToBaseLevel, we're not in dense mode etc. */
 {
 struct simpleFeature *sf = NULL;
 char *winDna = getCachedDna(winStart, winEnd);
 Color c = cdsColor[CDS_STOP];
 // check if we need a contrasting color instead of default 'red' (CDS_STOP)
@@ -1789,96 +1805,103 @@
     drawCdsDiffCodonsOnly(tg, lf, hvg, xOff, y, scale,
 			  heightPer, qSeq, qOffset, psl, winStart);
     }
 if (drawOpt == baseColorDrawDiffBases && !zoomedToBaseLevel && enabled)
     {
     drawCdsDiffBaseTickmarksOnly(tg, lf, hvg, xOff, y, scale,
 				 heightPer, qSeq, qOffset, psl, winStart);
     }
 }
 
 
 void baseColorOverdrawQInsert(struct track *tg,  struct linkedFeatures *lf,
 			      struct hvGfx *hvg, int xOff,
 			      int y, double scale, int heightPer,
 			      struct dnaSeq *qSeq, int qOffset, struct psl *psl,
-			      int winStart, enum baseColorDrawOpt drawOpt,
+			      MgFont *font, int winStart, enum baseColorDrawOpt drawOpt,
 			      boolean indelShowQInsert, boolean indelShowPolyA)
 /* If applicable, draw 1-pixel wide orange lines for query insertions in the
  * middle of the query, 1-pixel wide blue lines for query insertions at the 
  * end of the query, and 1-pixel wide green (instead of blue) when a query 
  * insertion at the end is a valid poly-A tail. */
 {
 assert(psl);
 int i;
 int s;
 int lastBlk = psl->blockCount - 1;
 boolean gotPolyAStart=FALSE, gotPolyAEnd=FALSE;
 
 if (indelShowPolyA && qSeq)
     {
     /* Draw green lines for polyA first, so if the entire transcript is 
      * jammed into one pixel and the other end has a blue line, blue is 
      * what the user sees. */
     if (psl->qStarts[0] != 0 && psl->strand[0] == '-')
 	{
 	/* Query is -.  We reverse-complemented in baseColorDrawSetup,
 	 * so test for polyT head: */
 	int polyTSize = headPolyTSizeLoose(qSeq->dna, qSeq->size);
 	if (polyTSize > 0 && (polyTSize + 3) >= psl->qStarts[0])
 	    {
 	    if (psl->strand[1] == '-')
 		s = psl->tSize - psl->tStarts[0] - 1;
 	    else
 		s = psl->tStarts[0];
-	    drawVertLine(lf, hvg, s, xOff, y, heightPer-1, scale,
+	    // drawVertLine(lf, hvg, s, xOff, y, heightPer-1, scale,
+	    //             cdsColor[CDS_POLY_A]);
+	    drawScaledBox(hvg, s, s+1, scale, xOff, y+1, heightPer-2,
 			 cdsColor[CDS_POLY_A]);
 	    gotPolyAStart = TRUE;
 	    }
 	}
     if ((psl->qStarts[lastBlk] + psl->blockSizes[lastBlk] != psl->qSize) &&
 	psl->strand[0] == '+')
 	{
 	if (psl->strand[1] == '-')
 	    {
 	    /* Query is + but target is -.  We reverse-complemented in
 	     * baseColorDrawSetup, so test for polyT head: */
 	    int polyTSize = headPolyTSizeLoose(qSeq->dna, qSeq->size);
 	    int rcQStart = (psl->qSize -
 			(psl->qStarts[lastBlk] + psl->blockSizes[lastBlk]));
 	    if (polyTSize > 0 && (polyTSize + 3) >= rcQStart)
 		{
 		s = psl->tStart;
-		drawVertLine(lf, hvg, s, xOff, y, heightPer-1, scale,
+	//	drawVertLine(lf, hvg, s, xOff, y, heightPer-1, scale,
+	//		     cdsColor[CDS_POLY_A]);
+	        drawScaledBox(hvg, s, s+1, scale, xOff, y+1, heightPer-2,
 			 cdsColor[CDS_POLY_A]);
 		gotPolyAEnd = TRUE;
 		}
 	    }
 	else
 	    {
 	    /* Both are +.  We didn't reverse-complement in
 	     * baseColorDrawSetup, so test for polyA tail: */
 	    int polyASize = tailPolyASizeLoose(qSeq->dna, qSeq->size);
 	    if (polyASize > 0 &&
 		((polyASize + 3) >= 
 		 (psl->qSize -
 		  (psl->qStarts[lastBlk] + psl->blockSizes[lastBlk]))))
 		{
 		s = psl->tStarts[lastBlk] + psl->blockSizes[lastBlk];
-		drawVertLine(lf, hvg, s, xOff, y, heightPer-1, scale,
+	//	drawVertLine(lf, hvg, s, xOff, y, heightPer-1, scale,
+	//		     cdsColor[CDS_POLY_A]);
+	        drawScaledBox(hvg, s, s+1, scale, xOff, y+1, heightPer-2,
 			 cdsColor[CDS_POLY_A]);
 		gotPolyAEnd = TRUE;
+		gotPolyAEnd = TRUE;
 		}
 	    }
 	}
     }
 
 if (indelShowQInsert)
     {
     if (psl->qStarts[0] != 0 && !gotPolyAStart)
 	{
 	/* Insert at beginning of query -- draw vertical blue line 
 	 * unless it's polyA. */
 	s = (psl->strand[1] == '-') ? (psl->tSize - psl->tStarts[0] - 1) :
 				      psl->tStarts[0];
 	drawVertLine(lf, hvg, s, xOff, y, heightPer-1, scale,
 		     cdsColor[CDS_QUERY_INSERTION_AT_END]);
@@ -1886,32 +1909,33 @@
     for (i = 1;  i < psl->blockCount;  i++)
 	{
 	int qBlkStart = psl->qStarts[i];
 	int qPrevBlkEnd = (psl->qStarts[i-1] + psl->blockSizes[i-1]);
 	if (qBlkStart > qPrevBlkEnd)
 	    {
 	    int tBlkStart = psl->tStarts[i];
 	    int tPrevBlkEnd = (psl->tStarts[i-1] + psl->blockSizes[i-1]);
 	    /* Note: if tBlkStart < tPrevBlkEnd, then we have overlap on 
 	     * target, possibly indicating a bug in the aligner. */
 	    if (tBlkStart <= tPrevBlkEnd)
 		{
 		/* Insert in query only -- draw vertical orange line. */
 		s = (psl->strand[1] == '-') ? (psl->tSize - psl->tStarts[i] - 1) :
 					      psl->tStarts[i];
-		drawVertLine(lf, hvg, s, xOff, y, heightPer-1, scale,
-			     cdsColor[CDS_QUERY_INSERTION]);
+		Color color = cdsColor[CDS_QUERY_INSERTION];
+		drawMidSize(lf, hvg, s, xOff, y, heightPer, scale,
+			     color, font, qBlkStart - qPrevBlkEnd);
 		}
 	    }
 	/* Note: if qBlkStart < qPrevBlkEnd, then we have overlap on query,
 	 * possibly indicating a bug in the aligner.  Most likely a gap 
 	 * should be drawn in that case (really a target insert) but I don't
 	 * think this is the place to do it.  Should be caught by 
 	 * pre-screening table data for block coords that overlap. */
 	}
     if (psl->qStarts[lastBlk] + psl->blockSizes[lastBlk] != psl->qSize &&
 	!gotPolyAEnd)
 	{
 	/* Insert at end of query -- draw vertical blue line unless it's 
 	 * all polyA. */
 	s = (psl->strand[1] == '-') ?
 	    (psl->tSize - (psl->tStarts[lastBlk] + psl->blockSizes[lastBlk])) :
@@ -1986,31 +2010,31 @@
 struct simpleFeature *sf;
 for (sf = lf->components; sf != NULL; sf = sf->next)
     {
     if (tStart > sf->start) tStart = sf->start;
     if (tEnd < sf->end) tEnd = sf->end;
     if (qStart > sf->qStart) qStart = sf->qStart;
     if (qEnd < sf->qEnd) qEnd = sf->qEnd;
     blockCount += 1;
     }
 
 struct psl *psl;
 AllocVar(psl);
 psl->strand[0] = (lf->orientation < 0 ? '-' : '+');
 
 psl->qName = cloneString(qName);
-psl->qSize = qEnd;  // Might need fixup 
+psl->qSize = lf->qSize;
 psl->qStart = qStart;
 psl->qEnd = qEnd;
 
 psl->tName = cloneString(tName);
 psl->tSize = tSize;
 psl->tStart = tStart;
 psl->tEnd = tEnd;
 
 /* Set block count and allocate block-by-block arrays */
 psl->blockCount = blockCount;
 unsigned *blockSizes = AllocArray(psl->blockSizes, blockCount);
 unsigned *qStarts = AllocArray(psl->qStarts, blockCount);
 unsigned *tStarts = AllocArray(psl->tStarts, blockCount);
 
 /* Go through link features filling in blockSizes, qStarts, qEnds */