c9aa9c0f8bd30426080ca5a2d5546d1f05befe9b jcasper Wed Jun 26 15:51:39 2024 -0700 Fix for drawing wrong exon numbers in codon mouseovers, refs #33742 diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c index c69493f..3b7af0a 100644 --- src/hg/hgTracks/simpleTracks.c +++ src/hg/hgTracks/simpleTracks.c @@ -2962,31 +2962,31 @@ { int sClp = (s < winStart) ? winStart : s; int eClp = (e > winEnd) ? winEnd : e; int sx = round((sClp - winStart)*scale) + insideX; int ex = round((eClp - winStart)*scale) + insideX; // skip regions entirely outside available picture // (accounts for space taken by exon arrows buttons) if (sx <= picEnd && ex >= picStart) { // clip it to avail pic sx = (sx < picStart) ? picStart : sx; ex = (ex > picEnd) ? picEnd : ex; - int w = ex - sx; + int w = ex - sx; // w could be negative, but we'll skip drawing if it is int exonIntronNumber; char *exonIntronText; int numExonIntrons = numExons; if (isExon) { exonIntronText = exonText; } else { exonIntronText = intronText; --numExonIntrons; // introns are one fewer than exons } char strandChar; @@ -3017,38 +3017,40 @@ { startPhase = gp->exonFrames[exonIx-1]; //printf("start phase is set<br>"); if (!revStrand) endPhase = gp->exonFrames[exonIx]; else if (exonIx>1) endPhase = gp->exonFrames[exonIx-2]; // construct a string that tells the user about the codon frame situation of this exon makeExonFrameText(exonIntronNumber, numExons, startPhase, endPhase, phaseText); } if (w > 0) // draw exon or intron if width is greater than 0 { // draw mapBoxes for the codons if we are zoomed in far enough + if (isExon && lf->codons && zoomedToCdsColorLevel) + { struct simpleFeature *codon; struct dyString *codonDy = dyStringNew(0); int codonS, codonE; - if (isExon && lf->codons && zoomedToCdsColorLevel) - { for (codon = lf->codons; codon != NULL; codon = codon->next) { codonS = codon->start; codonE = codon->end; + if (codonS > e || codonE < s) + continue; // only write out mouseovers for codons in the current exon if (codonS <= winEnd && codonE >= winStart) { int codonSClp = (codonS < winStart) ? winStart : codonS; int codonEClp = (codonE > winEnd) ? winEnd : codonE; int codonsx = round((codonSClp - winStart)*scale) + insideX; int codonex = round((codonEClp - winStart)*scale) + insideX; // skip regions entirely outside available picture // (accounts for space taken by exon arrows buttons) if (codonsx <= picEnd && codonex >= picStart) { // clip it to avail pic codonsx = (codonsx < picStart) ? picStart : codonsx; codonex = (codonex > picEnd) ? picEnd : codonex; @@ -3065,68 +3067,51 @@ dyStringPrintf(codonDy, "%s, ", existingText); int codonHgvsIx = (codon->codonIndex - 1) * 3; if (codonHgvsIx >= 0) dyStringPrintf(codonDy, "c.%d-%d, ", codonHgvsIx + 1, codonHgvsIx + 3); dyStringPrintf(codonDy, "strand %c, %s %d of %d%s", strandChar, exonIntronText, exonIntronNumber, numExonIntrons, phaseText); tg->mapItem(tg, hvg, item, codonDy->string, tg->mapItemName(tg, item), sItem, eItem, codonsx, y, w, heightPer); // and restore the mouseOver lf->mouseOver = oldMouseOver; } } } } } - } - else - { - // temporarily remove the mouseOver from the lf, since linkedFeatureMapItem will always - // prefer a lf->mouseOver over the itemName - if (!isEmpty(existingText)) - safef(mouseOverText, sizeof(mouseOverText), "%s, strand %c, %s %d of %d%s", - existingText, strandChar, exonIntronText, exonIntronNumber, numExonIntrons, phaseText); - else - safef(mouseOverText, sizeof(mouseOverText), "strand %c, %s %d of %d%s", - strandChar, exonIntronText, exonIntronNumber, numExonIntrons, phaseText); - char *oldMouseOver = lf->mouseOver; - lf->mouseOver = NULL; - tg->mapItem(tg, hvg, item, mouseOverText, tg->mapItemName(tg, item), - sItem, eItem, sx, y, w, heightPer); - // and restore the mouseOver - lf->mouseOver = oldMouseOver; - } - - if (w > 0) // draw exon or intron if width is greater than 0 + else // either an intron, or else an exon zoomed out too far for codons (or no codons) { char *sep = ""; if (!isEmpty(existingText)) sep = ", "; safef(mouseOverText, sizeof(mouseOverText), "%s%sstrand %c, %s %d of %d%s", existingText, sep, strandChar, exonIntronText, exonIntronNumber, numExonIntrons, phaseText); // temporarily remove the mouseOver from the lf, since linkedFeatureMapItem will always // prefer a lf->mouseOver over the itemName char *oldMouseOver = lf->mouseOver; lf->mouseOver = NULL; tg->mapItem(tg, hvg, item, mouseOverText, tg->mapItemName(tg, item), sItem, eItem, sx, y, w, heightPer); // and restore the old mouseOver lf->mouseOver = oldMouseOver; picStart = ex; // prevent pileups. is this right? add 1? does it work? + // JC: Why do we care about pileups? First mapbox drawn wins. + } } } } if (isExon) { eLast = e; ref = ref->next; if (!ref) break; } else { exonIx++; }