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;