bd5ebb2dc0b10ad589ed54c3319da1fac28d2b26
max
Wed May 7 06:38:51 2025 -0700
adding html to genePred exon mouseover, refs #33749
diff --git src/hg/hgTracks/simpleTracks.c src/hg/hgTracks/simpleTracks.c
index 7019c9e5acb..55dfafa301c 100644
--- src/hg/hgTracks/simpleTracks.c
+++ src/hg/hgTracks/simpleTracks.c
@@ -2659,53 +2659,55 @@
if (*pNewWinEnd > virtSeqBaseCount)
*pNewWinEnd = virtSeqBaseCount;
*pNewWinStart = *pNewWinEnd - newWinSize;
}
#define EXONTEXTLEN 256
static void makeExonFrameText(int exonIntronNumber, int numExons, int startPhase, int endPhase, char *buf)
/* Write mouseover text that describes the exon's phase into buf[EXONTEXTLEN].
Note that start/end-phases are in the direction of transcription:
if transcript is on + strand, the start phase is the exonFrame value, and the end phase is the next exonFrame (3' on DNA) value
if transcript is on - strand, the start phase is the previous (=3' on DNA) exonFrame and the end phase is the exonFrame */
{
+static const char *phaseHelp = "Phase?
";
+
if (startPhase==-1) // UTRs don't have a frame at all
{
- safef(buf, EXONTEXTLEN, ", untranslated region");
+ safef(buf, EXONTEXTLEN, "No Codon: Untranslated region
");
}
else
{
char *exonNote = "";
boolean isNotLastExon = (exonIntronNumberCodon phase: start %d, end %d%s
%s", startPhase, endPhase, exonNote, phaseHelp);
}
else
{
if (startPhase==0)
exonNote = ": in-frame exon";
else
exonNote = ": out-of-frame exon";
- safef(buf, EXONTEXTLEN, ", start codon phase %d%s", startPhase, exonNote);
+ safef(buf, EXONTEXTLEN, "Codon phase: start %d%s
%s", startPhase, exonNote, phaseHelp);
}
}
}
boolean linkedFeaturesNextPrevItem(struct track *tg, struct hvGfx *hvg, void *item, int x, int y, int w, int h, boolean next)
/* Draw a mapBox over the arrow-button on an *item already in the window*. */
/* Clicking this will do one of several things: */
{
boolean result = FALSE;
struct linkedFeatures *lf = item;
struct simpleFeature *exons = lf->components;
struct simpleFeature *exon = exons;
char *nextExonText;
char *prevExonText;
long newWinSize = virtWinEnd - virtWinStart;
@@ -2998,39 +3000,38 @@
}
else {
exonIntronNumber = numExonIntrons-exonIx+1;
strandChar = '-';
}
// we still need to show the existing mouseover text
char* existingText = lf->mouseOver;
if (isEmpty(existingText))
existingText = lf->name;
// construct a string that tells the user about the codon frame situation of this exon
// char *frameText = "";
// for coding exons, determine the start and end phase of the exon and an English text describing both:
// if transcript is on + strand, the start phase is the exonFrame value, and the end phase is the next exonFrame (3' on DNA) value
- // if transcript is on - strand, the start phase is the previous (=3' on DNA) exonFrame and the end phase is the exonFrame */
+ // if transcript is on - strand, the start phase is the previous (=3' on DNA) exonFrame and the end phase is the exonFrame
int startPhase = -1;
int endPhase = -1;
char phaseText[EXONTEXTLEN];
phaseText[0] = 0;
if ((gp != NULL) && gp->exonFrames && isExon)
{
startPhase = gp->exonFrames[exonIx-1];
- //printf("start phase is set
");
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;
@@ -3054,52 +3055,52 @@
if (codonsx <= picEnd && codonex >= picStart)
{
// clip it to avail pic
codonsx = (codonsx < picStart) ? picStart : codonsx;
codonex = (codonex > picEnd) ? picEnd : codonex;
int w = codonex - codonsx;
if (w > 0)
{
// 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;
dyStringClear(codonDy);
if (!isEmpty(existingText))
- dyStringPrintf(codonDy, "%s, ", existingText);
+ dyStringPrintf(codonDy, "Transcript: %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",
+ dyStringPrintf(codonDy, "cDNA: c.%d-%d
", codonHgvsIx + 1, codonHgvsIx + 3);
+ dyStringPrintf(codonDy, "Strand: %c
Exon: %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 // either an intron, or else an exon zoomed out too far for codons (or no codons)
{
char *sep = "";
if (!isEmpty(existingText))
- sep = ", ";
+ sep = "
";
- safef(mouseOverText, sizeof(mouseOverText), "%s%sstrand %c, %s %d of %d%s",
+ safef(mouseOverText, sizeof(mouseOverText), "Transcript: %s%sStrand: %c
Exon: %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.
}
}