118634b1bb159357168a349dbf600f545e096f56 max Fri Jul 24 08:17:41 2026 -0700 Revert "hgTracks: strand-direction arrows on the zoomed-in codon/CDS and UTR display" This reverts commit ded41ea1968e30e2c248f65d1c9fec9793cb82fc. diff --git src/hg/hgTracks/cds.c src/hg/hgTracks/cds.c index 2f774345c7d..cefe211aea1 100644 --- src/hg/hgTracks/cds.c +++ src/hg/hgTracks/cds.c @@ -100,100 +100,59 @@ else if (btStart >= tEnd) { qEnd = lastBqEnd; foundEnd = TRUE; break; } } lastBqEnd = bqEnd; } *retQStart = qStart; *retQEnd = qEnd; return TRUE; } -static void drawCodonStrandArrow(struct hvGfx *hvg, int boundaryX, int midY, - int height, Color boxColor, int strand) -/* Draw a strand-direction chevron centered on the left boundary of a codon box - * (i.e. in the whitespace between the centered amino-acid letters of two - * adjacent codons). The chevron points in the strand direction (1 = right, - * -1 = left; reverse-complement display is handled by hvGfxLine). It is drawn - * in the box's contrasting color (white on the dark-blue codon shades, the same - * color as the codon letter) so it reads clearly, and the caller draws it before - * the amino-acid text so the letter stays crisp. */ -{ -if (strand == 0) - return; -int bh = (height - 2) / 2; // chevron half-height -if (bh > 3) - bh = 3; // keep it small -if (bh < 2) - return; // not enough vertical room - -// contrasting color: white on the dark-blue codon shades, matching the letter -Color aColor = hvGfxContrastingColor(hvg, boxColor); -if (strand > 0) - { - // ">" apex on the right, wings opening to the left - hvGfxLine(hvg, boundaryX + bh, midY, boundaryX - bh, midY - bh, aColor); - hvGfxLine(hvg, boundaryX + bh, midY, boundaryX - bh, midY + bh, aColor); - } -else - { - // "<" apex on the left, wings opening to the right - hvGfxLine(hvg, boundaryX - bh, midY, boundaryX + bh, midY - bh, aColor); - hvGfxLine(hvg, boundaryX - bh, midY, boundaryX + bh, midY + bh, aColor); - } -} - static void drawScaledBoxWithText(struct hvGfx *hvg, int chromStart, int chromEnd, double scale, int xOff, int y, int height, Color color, int score, MgFont *font, char *text, bool zoomed, - int winStart, int maxPixels, boolean isCoding, boolean justifyString, - int strand) + int winStart, int maxPixels, boolean isCoding, boolean justifyString) /* Draw a box scaled from chromosome to window coordinates with - a codon or set of 3 or less bases drawn in the box. If strand is non-zero - and a whole codon is drawn, a faint strand-direction chevron is drawn in the - box before the amino-acid letter. */ + a codon or set of 3 or less bases drawn in the box. */ { /*first draw the box itself*/ drawScaledBox(hvg, chromStart, chromEnd, scale, xOff, y, height, color); /*draw text in box if space, and align properly for codons or DNA*/ if (zoomed) { int i; Color textColor = hvGfxContrastingColor(hvg, color); int x1, x2, w; x1 = round((double)(chromStart-winStart)*scale) + xOff; x2 = round((double)(chromEnd-winStart)*scale) + xOff; if (x2 >= maxPixels) x2 = maxPixels - 1; w = x2-x1; if (w < 1) w = 1; if (chromEnd - chromStart == 3 && isCoding) { - /* faint strand arrow between this amino acid and the previous one, - * drawn before the letter so the letter stays legible */ - if (w >= 6) - drawCodonStrandArrow(hvg, x1, y + height/2, height, color, strand); if (justifyString) spreadBasesString(hvg, x1, y, w, height, textColor, font, text, strlen(text), TRUE); else hvGfxTextCentered(hvg, x1, y, w, height, textColor, font, text); } else if (chromEnd - chromStart < 3 && isCoding) { if (justifyString) spreadBasesString(hvg, x1, y, w, height, cdsColor[CDS_PARTIAL_CODON], font, text, strlen(text), TRUE); else hvGfxTextCentered(hvg, x1, y, w, height, cdsColor[CDS_PARTIAL_CODON], font, text); } else { int thisX,thisX2; @@ -1695,89 +1654,89 @@ mrnaBases[0] = '\0'; if (psl && isCoding) getMrnaBases(psl, mrnaSeq, mrnaOffset, mrnaS, s, e, (lf->orientation == -1), mrnaBases, &queryInsertion); if (queryInsertion && isCoding) color = cdsColor[CDS_QUERY_INSERTION]; dyStringAppendN(dyMrnaSeq, (char*)&mrnaSeq->dna[mrnaS - mrnaOffset], e-s); if (drawOpt == baseColorDrawItemBases) { if (cartUsualBooleanDb(cart, database, COMPLEMENT_BASES_VAR, FALSE)) complement(dyMrnaSeq->string, dyMrnaSeq->stringSize); drawScaledBoxWithText(hvg, s, e, scale, xOff, y, heightPer, color, lf->score, font, dyMrnaSeq->string, - zoomedToBaseLevel, winStart, maxPixels, isCoding, TRUE, lf->orientation); + zoomedToBaseLevel, winStart, maxPixels, isCoding, TRUE); } else if (drawOpt == baseColorDrawItemCodons) { if (e <= lf->tallEnd) { boolean startColor = FALSE; /* re-set color of this block based on mrna codons rather than * genomic, but keep the odd/even cycle of dark/light shades. */ int mrnaGrayIx = codonToGrayIx(mrnaBases, (grayIx > 26), NULL, FALSE, TRUE, NULL); if (color == cdsColor[CDS_START]) startColor = TRUE; color = colorAndCodonFromGrayIx(hvg, mrnaCodon, mrnaGrayIx, ixColor); if (startColor && sameString(mrnaCodon,"M")) color = cdsColor[CDS_START]; drawScaledBoxWithText(hvg, s, e, scale, xOff, y, heightPer, color, lf->score, font, mrnaCodon, zoomedToCodonLevel, winStart, - maxPixels, isCoding, TRUE, lf->orientation); + maxPixels, isCoding, TRUE); } else drawScaledBox(hvg, s, e, scale, xOff, y, heightPer, color); } else if (drawOpt == baseColorDrawDiffBases) { char *diffStr = NULL; char *genoDna = getCachedDna(s, e); diffStr = needMem(sizeof(char) * (e - s + 1)); maskDiffString(diffStr, dyMrnaSeq->string, genoDna, ' ', dyMrnaSeq->stringSize); // fprintf(stderr, "drawOpt =- diffBases. %d %d %d %d\n", (int)strlen(genoDna), (int)strlen(dyMrnaSeq->string), (int)dyMrnaSeq->stringSize, e-s); if (cartUsualBooleanDb(cart, database, COMPLEMENT_BASES_VAR, FALSE)) complement(diffStr, strlen(diffStr)); drawScaledBoxWithText(hvg, s, e, scale, xOff, y, heightPer, color, lf->score, font, diffStr, - zoomedToBaseLevel, winStart, maxPixels, isCoding, TRUE, lf->orientation); + zoomedToBaseLevel, winStart, maxPixels, isCoding, TRUE); freeMem(diffStr); } else if (drawOpt == baseColorDrawDiffCodons) { if (e <= lf->tallEnd) { /* Color codons red wherever mrna differs from genomic; * keep the odd/even cycle of dark/light shades. */ colorAndCodonFromGrayIx(hvg, genomicCodon, grayIx, ixColor); int mrnaGrayIx = mrnaCodonToGrayIx(mrnaBases, genomicCodon[0], (grayIx > 26)); color = colorAndCodonFromGrayIx(hvg, mrnaCodon, mrnaGrayIx, ixColor); // Look up mrnaCodon again because if mrnaGrayIx is GRAYIX_SYN_PROT, // codon value is lost: safef(mrnaCodon, sizeof(mrnaCodon), "%c", baseColorLookupCodon(mrnaBases)); if (mrnaCodon[0] != genomicCodon[0]) { drawScaledBoxWithText(hvg, s, e, scale, xOff, y, heightPer, color, lf->score, font, mrnaCodon, zoomedToCodonLevel, - winStart, maxPixels, isCoding, TRUE, lf->orientation); + winStart, maxPixels, isCoding, TRUE); } else drawScaledBox(hvg, s, e, scale, xOff, y, heightPer, color); } else drawScaledBox(hvg, s, e, scale, xOff, y, heightPer, color); } else if (drawOpt != baseColorDrawCds) errAbort("Unknown drawOpt: %d<br>\n", drawOpt); dyStringFree(&dyMrnaSeq); } else { if (s < e) @@ -1807,37 +1766,37 @@ /* When we are zoomed out far enough so that multiple bases/codons share the * same pixel, we have to draw differences in a separate pass (baseColorOverdrawDiff) * so don't waste time drawing the differences here: */ boolean zoomedOutToPostProcessing = ((drawOpt == baseColorDrawDiffBases && !zoomedToBaseLevel) || (drawOpt == baseColorDrawDiffCodons && !zoomedToCdsColorLevel)); if (drawOpt == baseColorDrawGenomicCodons && (e-s <= 3)) { if (lf->highlightColor) { drawScaledBox(hvg, s, e, scale, xOff, y, heightPer, lf->highlightColor); drawScaledBoxWithText(hvg, s, e, scale, xOff, y+1, heightPer-2, color, lf->score, font, codon, - zoomedToCodonLevel, winStart, maxPixels, TRUE, !sf->codonIndex, lf->orientation); + zoomedToCodonLevel, winStart, maxPixels, TRUE, !sf->codonIndex); } else { drawScaledBoxWithText(hvg, s, e, scale, xOff, y, heightPer, color, lf->score, font, codon, - zoomedToCodonLevel, winStart, maxPixels, TRUE, !sf->codonIndex, lf->orientation); + zoomedToCodonLevel, winStart, maxPixels, TRUE, !sf->codonIndex); } } else if (qSeq != NULL && (psl != NULL || sf != NULL) && !zoomedOutToPostProcessing && drawOpt != baseColorDrawGenomicCodons && drawOpt != baseColorDrawOff) { if (lf->highlightColor) { drawScaledBox(hvg, s, e, scale, xOff, y, heightPer, lf->highlightColor); drawDiffTextBox(hvg, xOff+1, y+1, scale, heightPer-2, font, color, chromName, s, e, sf, psl, qSeq, qOffset, lf, grayIx, drawOpt, maxPixels, tg->colorShades, originalColor); } else @@ -1948,114 +1907,30 @@ enabled = FALSE; if (drawOpt == baseColorDrawDiffCodons && !zoomedToCdsColorLevel && lf->codons && enabled) { 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); } } -static void drawStrandBarbsInRange(struct hvGfx *hvg, int s, int e, double scale, - int xOff, int winStart, int midY, int barbHeight, int barbSpacing, - int orientation, Color color) -/* Clip base range [s,e] to the window and draw evenly-spaced strand chevrons - * (barbs only, no connecting line) across it. */ -{ -if (s < winStart) s = winStart; -if (e > winEnd) e = winEnd; -if (e <= s) - return; -int x1 = round((double)(s-winStart)*scale) + xOff; -int x2 = round((double)(e-winStart)*scale) + xOff; -int w = x2 - x1; -if (w < barbHeight*2) - return; // too narrow to show an arrow cleanly -clippedBarbs(hvg, x1, midY, w, barbHeight, barbSpacing, orientation, color, FALSE); -} - -void baseColorDrawCdsArrows(struct track *tg, struct linkedFeatures *lf, - struct hvGfx *hvg, int xOff, int y, double scale, - int heightPer, int winStart, enum baseColorDrawOpt drawOpt, - Color color) -/* When zoomed in far enough to color the codons, distribute strand-direction - * chevrons across each exon on top of the boxes (the per-codon letter arrows in - * drawScaledBoxWithText only appear once the codons are big enough to label). - * The coding part gets white chevrons at the standard barb spacing, but only - * when the codons are too small to label (otherwise the letter arrows cover it). - * The UTR parts get the feature's contrasting color at a wider spacing, as a - * visual hint that they are non-coding. No-op below the codon-color zoom level, - * when coding coloring is off, or when the strand is unknown. */ -{ -if (drawOpt <= baseColorDrawOff) - return; -if (!zoomedToCdsColorLevel) - return; -if (lf->orientation == 0) - return; - -if (!cdsColorsMade) - { - makeCdsShades(hvg, cdsColor); - cdsColorsMade = TRUE; - } - -int midY = y + (heightPer>>1); -int orientation = lf->orientation; - -/* white reads clearly on top of the dark-blue codon shades (the same high - * contrast the codon-letter text uses); only draw it when the codons are too - * small to show their letters (which carry their own arrows) */ -boolean drawCds = !zoomedToCodonLevel; -Color cdsColor1 = hvGfxFindColorIx(hvg, 0xff, 0xff, 0xff); -int cdsBh = tl.barbHeight; -int cdsSpacing = tl.barbSpacing*2; - -/* UTR boxes are drawn shorter and in the feature color, so size the chevron to - * the short box (but at least 1px, so it still shows in squish mode where the - * box is only a few pixels tall) and use the feature's contrasting color; space - * them more widely than the coding chevrons as a cue that UTRs are non-coding */ -int shortOff = heightPer/4; -int shortHeight = heightPer - 2*shortOff; -int utrBh = shortHeight/2; -if (utrBh > tl.barbHeight) - utrBh = tl.barbHeight; -if (utrBh < 1) - utrBh = 1; -Color utrColor = hvGfxContrastingColor(hvg, color); -int utrSpacing = tl.barbSpacing*3; - -struct simpleFeature *sf; -for (sf = lf->components; sf != NULL; sf = sf->next) - { - if (drawCds) - drawStrandBarbsInRange(hvg, max(sf->start, lf->tallStart), min(sf->end, lf->tallEnd), - scale, xOff, winStart, midY, cdsBh, cdsSpacing, orientation, cdsColor1); - /* 5' and 3' UTR portions of this exon (the parts outside [tallStart,tallEnd]) */ - drawStrandBarbsInRange(hvg, sf->start, min(sf->end, lf->tallStart), - scale, xOff, winStart, midY, utrBh, utrSpacing, orientation, utrColor); - drawStrandBarbsInRange(hvg, max(sf->start, lf->tallEnd), sf->end, - scale, xOff, winStart, midY, utrBh, utrSpacing, orientation, utrColor); - } -} - - 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, 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; @@ -2425,31 +2300,31 @@ struct simpleFeature *sf; if (!cdsColorsMade) { makeCdsShades(hvg, cdsColor); cdsColorsMade = TRUE; } for (sf = sfList; sf != NULL; sf = sf->next) { char codon[4]; Color color = colorAndCodonFromGrayIx(hvg, codon, sf->grayIx, MG_GRAY); if (zoomedToText) drawScaledBoxWithText(hvg, sf->start, sf->end, scale, insideX, y, height, color, 1.0, font, codon, TRUE, - winStart, maxPixels, TRUE, TRUE, 0); + winStart, maxPixels, TRUE, TRUE); else /* zoomed in just enough to see colored boxes */ drawScaledBox(hvg, sf->start, sf->end, scale, xOff, y, height, color); /* mouse-over the codon box with the amino acid's three-letter abbreviation * and full name (sf->codonAa was set when the codon was translated) */ baseColorAddRulerCodonMapItem(hvg, sf, scale, xOff, y, height); } } void baseColorSetCdsBounds(struct linkedFeatures *lf, struct psl *psl, struct track *tg) /* set CDS bounds in linked features for a PSL. Used when zoomed out too far * for codon or base coloring, but still want to render CDS bounds */