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 */