91c4d60a5bcbf19016e3eb0fd4fdcccb2588a5b4
kent
  Thu Jun 30 19:03:04 2022 -0700
Fixing BAM base level coloring recently introduced bug.  Making the purple incompletely aligned ends be a little more visible and include the size of missing begin or end if zooomed in enough.

diff --git src/hg/hgTracks/cds.c src/hg/hgTracks/cds.c
index 7b6b064..b7e68ce 100644
--- src/hg/hgTracks/cds.c
+++ src/hg/hgTracks/cds.c
@@ -331,42 +331,45 @@
 	}
     }
 }
 
 
 static void drawVertLine(struct linkedFeatures *lf, struct hvGfx *hvg,
                          int chromStart, int xOff, int y,
 			 int height, double scale, Color color)
 /* 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;
+height -= 1;
 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;
     }
 hvGfxBox(hvg, thisX-2, thisY, 4, thisHeight, color);
 }
+#ifdef UNUSED
+#endif /* UNUSED */
 
-static void drawMidSize(struct linkedFeatures *lf, struct hvGfx *hvg,
+static void drawMidNumber(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);
 }
 
 
@@ -401,31 +404,30 @@
     if (s > winEnd || e < winStart)
       continue;
     if (e > s)
 	{
 	int mrnaS = -1;
 	if (psl)
 	    mrnaS = convertCoordUsingPsl(s, psl);
 	else
 	    mrnaS = sf->qStart + (s - sf->start);
 	if(mrnaS >= 0)
 	    {
 	    int i;
 	    for (i=0; i < (e - s); i++)
 		{
 		if (qSeq->dna[mrnaS+i-qOffset] != winDna[s-winStart+i])
-		    // drawVertLine(lf, hvg, s+i, xOff, y+1, heightPer-2, scale, c);
 		    drawScaledBox(hvg,  s+i, s+i+1, scale, xOff, y+1, heightPer-2, c);
 		}
 	    }
 	}
     }
 }
 
 
 static void maskDiffString( char *retStr, char *s1, char *s2, char mask )
 /*copies s1, masking off similar characters, and returns result into retStr.
  *if strings are of different size it stops after s1 is done.*/
 {
 int s1Len = strlen(s1);
 memset(retStr, mask, s1Len);
 int i;
@@ -1834,126 +1836,123 @@
     {
     /* 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,
-	    //             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,
-	//		     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,
-	//		     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)
+    int qStart = psl->qStarts[0];
+    if (qStart != 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]);
+        Color color = cdsColor[CDS_QUERY_INSERTION_AT_END];
+	drawVertLine(lf, hvg, s, xOff, y, heightPer, scale, color);
+	drawMidNumber(lf, hvg, s, xOff, y, heightPer, scale, color, font, qStart);
 	}
     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];
 		Color color = cdsColor[CDS_QUERY_INSERTION];
-		drawMidSize(lf, hvg, s, xOff, y, heightPer, scale,
-			     color, font, qBlkStart - qPrevBlkEnd);
+		drawMidNumber(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)
+    int missingAtEnd = psl->qSize - (psl->qStarts[lastBlk] + psl->blockSizes[lastBlk]);
+    if (missingAtEnd != 0 && !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])) :
 	    (psl->tStarts[lastBlk] + psl->blockSizes[lastBlk]);
-	drawVertLine(lf, hvg, s, xOff, y, heightPer-1, scale,
-		     cdsColor[CDS_QUERY_INSERTION_AT_END]);
+        Color color = cdsColor[CDS_QUERY_INSERTION_AT_END];
+	drawVertLine(lf, hvg, s, xOff, y, heightPer, scale, color);
+	drawMidNumber(lf, hvg, s, xOff, y, heightPer, scale, color, font, missingAtEnd);
 	}
     }
 }
 
 void baseColorInitTrack(struct hvGfx *hvg, struct track *tg)
 /* Set up base coloring state (e.g. cache genomic sequence) for tg.
  * This must be called by tg->drawItems if baseColorDrawSetup is used 
  * in tg->drawItemAt.  Peeks at tg->drawItems method to determine whether
  * tg is linkedFeatures or linkedFeaturesSeries (currently the only
  * two supported track types -- bed, psl etc. are subclasses of these). */
 {
 enum baseColorDrawOpt drawOpt = baseColorGetDrawOpt(tg);
 boolean indelShowDoubleInsert, indelShowQueryInsert, indelShowPolyA;
 indelEnabled(cart, (tg ? tg->tdb : NULL), basesPerPixel,
 	     &indelShowDoubleInsert, &indelShowQueryInsert, &indelShowPolyA);
@@ -2094,31 +2093,31 @@
 
 /* If we are using item sequence, fetch alignment and sequence: */
 struct psl *psl = NULL;
 struct dnaSeq *mrnaSeq = NULL;
 int mrnaOffset = 0;
 if (indelShowQueryInsert || indelShowPolyA || drawOpt > baseColorDrawOff)
     {
     char *type = tg->tdb->type;
     boolean needPsl = FALSE;
     char *qName = lf->name;
     if (sameString("lrg", tg->tdb->track))
 	{
 	psl = lrgToPsl(lf->original, hChromSize(database, chromName));
 	needPsl = TRUE;
 	}
-    else if (startsWith("psl", type) || sameString("bigPsl", type))
+    else if (startsWith("psl", type) || sameString("bigPsl", type) || startsWithWord("bam", type))
 	{
 	psl = (struct psl *)(lf->original);
 	needPsl = TRUE;
 	}
     else if (startsWithWord("chain", type) || startsWithWord("bigChain", type))
 	{
 	qName = cloneFirstWord(lf->name);
         psl = linkedFeatureToPsl(lf, qName, chromName, hChromSize(database, chromName));
 	needPsl = TRUE;
 	}
     boolean doRc = FALSE;
     if (needPsl)
 	{
         if (psl == NULL)
 	    drawOpt = baseColorDrawOff;