dbbc85fe1ded040b85b123282425606bba9674f8 braney Sat Apr 20 13:44:01 2013 -0700 polishing some of the snake track code, added support for HAL snakes in assembly hubs. refs #10637 diff --git src/hg/hgTracks/snakeTrack.c src/hg/hgTracks/snakeTrack.c index 52e9f7e..f77cc1e 100644 --- src/hg/hgTracks/snakeTrack.c +++ src/hg/hgTracks/snakeTrack.c @@ -1,81 +1,97 @@ /* snakeTrack - stuff to load and display snake type tracks in browser. */ -/* uses standard chains from the database */ +/* uses standard chains from the database or HAL files */ +/* probably the chain and hal support should be in different files + * but they share drawing code + */ #include "common.h" #include "hash.h" #include "localmem.h" #include "linefile.h" #include "jksql.h" #include "hdb.h" #include "hgTracks.h" #include "chainBlock.h" #include "chainLink.h" #include "chainDb.h" #include "chainCart.h" +#include "errCatch.h" +#include "twoBit.h" +#include "bigWarn.h" +#include <pthread.h> +#include "trackHub.h" + +#ifdef USE_HAL +#include "halBlockViz.h" +#endif struct snakeFeature { struct snakeFeature *next; int start, end; /* Start/end in browser coordinates. */ int qStart, qEnd; /* query start/end */ int level; /* level in packed snake */ int orientation; /* strand... -1 is '-', 1 is '+' */ boolean drawn; /* did we draw this feature? */ + char *sequence; /* may have sequence, or NULL */ + char *qName; /* chrom name on other species */ }; +// static machinery to calculate packed snake + struct level { boolean init; /* has this level been initialized */ int orientation; /* strand.. see above */ int edge; /* the leading edge of this level */ int adjustLevel; /* used to compress out the unused levels */ boolean hasBlock; /* are there any blocks in this level */ }; -static struct level Levels[1000000]; /* for packing the snake */ +static struct level Levels[1000000]; /* for packing the snake, not re-entrant! */ static int maxLevel = 0; /* deepest level */ /* blocks that make it through the min size filter */ static struct snakeFeature *newList = NULL; static int snakeFeatureCmpQStart(const void *va, const void *vb) /* sort by start position on the query sequence */ { const struct snakeFeature *a = *((struct snakeFeature **)va); const struct snakeFeature *b = *((struct snakeFeature **)vb); int diff = a->qStart - b->qStart; if (diff == 0) { diff = a->start - b->start; } return diff; } -void clearLevels() +static void clearLevels() /* clear out the data structure that we use to pack the snake */ { int ii; for(ii=0; ii < sizeof(Levels) / sizeof(Levels[0]); ii++) Levels[ii].init = FALSE; maxLevel = 0; } -void calcSnake(struct snakeFeature *list, int level) +static void calcSnake(struct snakeFeature *list, int level) // calculate the packed snake // updates global newList with unsorted blocks that pass the min // size filter. { struct snakeFeature *cb = list; struct snakeFeature *proposedList = NULL; if (level > maxLevel) maxLevel = level; if (level > ArraySize(Levels)) errAbort("too many levels"); if (Levels[level].init == FALSE) { // initialize the level if this is the first time we've seen it @@ -173,45 +189,47 @@ // transfer proposedList to new block list for(temp=proposedList; temp; temp = next) { next = temp->next; temp->next = NULL; slAddHead(&newList, temp); } } struct cartOptions { enum chainColorEnum chainColor; /* ChromColors, ScoreColors, NoColors */ int scoreFilter ; /* filter chains by score if > 0 */ }; -int snakeHeight(struct track *tg, enum trackVisibility vis) +static int snakeHeight(struct track *tg, enum trackVisibility vis) /* calculate height of all the snakes being displayed */ { int height = 0; struct slList *item = tg->items; item = tg->items; for (item=tg->items;item; item = item->next) { height += tg->itemHeight(tg, item); } return height; } +// mySQL code to read in chains + static void doQuery(struct sqlConnection *conn, char *fullName, struct lm *lm, struct hash *hash, int start, int end, boolean isSplit, int chainId) /* doQuery- check the database for chain elements between * start and end. Use the passed hash to resolve chain * id's and place the elements into the right * linkedFeatures structure */ { struct sqlResult *sr = NULL; char **row; struct linkedFeatures *lf; struct snakeFeature *sf; struct dyString *query = newDyString(1024); char *force = ""; @@ -256,31 +274,31 @@ sf->qEnd = pChain->qSize - temp; } sf->orientation = lf->orientation; slAddHead(&lf->components, sf); } } sqlFreeResult(&sr); dyStringFree(&query); } struct snakeInfo { int maxLevel; } snakeInfo; -void calcPackSnake(struct track *tg, void *item) +static void calcPackSnake(struct track *tg, void *item) { struct linkedFeatures *lf = (struct linkedFeatures *)item; if (lf->components == NULL) return; // we use the codons field to keep track of whether we already // calculated the height of this snake if (lf->codons == NULL) { clearLevels(); struct snakeFeature *sf; // this will destroy lf->components, and add to newList calcSnake((struct snakeFeature *)lf->components, 0); lf->components = (struct simpleFeature *)newList; @@ -337,105 +355,62 @@ count++; } maxLevel = count - 1; // remap blocks for(sf=(struct snakeFeature *)lf->components; sf; sf = sf->next) sf->level = Levels[sf->level].adjustLevel; struct snakeInfo *si; AllocVar(si); si->maxLevel = maxLevel; lf->codons = (struct simpleFeature *)si; } } -int packSnakeItemHeight(struct track *tg, void *item) +static int packSnakeItemHeight(struct track *tg, void *item) // return height of a single packed snake { if (item == NULL) return 0; struct linkedFeatures *lf = (struct linkedFeatures *)item; if (lf->components == NULL) return 0; calcPackSnake(tg, item); struct snakeInfo *si = (struct snakeInfo *)lf->codons; int lineHeight = tg->lineHeight ; return (si->maxLevel + 1) * (2 * lineHeight); } -int fullSnakeItemHeight(struct track *tg, void *item) -// return height of full snake -{ -struct linkedFeatures *lf = (struct linkedFeatures *)item; -struct snakeFeature *sf; -int s, e; -int lineHeight = tg->lineHeight ; -int oldOrient = 0; -int tStart, tEnd; -int size = 0; -//int count = 0; -tStart = 0; -tEnd = 0; -if (lf->components) - size = lineHeight; -for (sf = (struct snakeFeature *)lf->components; sf ; sf = sf->next) +static int snakeItemHeight(struct track *tg, void *item) { - int orient = sf->orientation; - - s = sf->start; e = sf->end; - /* - if ((e < winStart) || (s > winEnd)) - continue; - if (s < winStart) s = winStart; - */ - - if (((oldOrient) && (oldOrient != orient)) - || ((oldOrient == 1) && (tEnd) && (s < tEnd)) - || ((oldOrient == -1) && (tStart) && (e > tStart))) - { - size += lineHeight; - } - oldOrient = orient; - tEnd = e; - tStart = s; - } -return size; -} - -int snakeItemHeight(struct track *tg, void *item) -{ - if (tg->visibility == tvFull) - return fullSnakeItemHeight(tg, item); - else if (tg->visibility == tvPack) return packSnakeItemHeight(tg, item); -return 0; } static int linkedFeaturesCmpScore(const void *va, const void *vb) /* Help sort linkedFeatures by score */ { const struct linkedFeatures *a = *((struct linkedFeatures **)va); const struct linkedFeatures *b = *((struct linkedFeatures **)vb); if (a->score > b->score) return -1; else if (a->score < b->score) return 1; return 0; } -void snakeDraw(struct track *tg, int seqStart, int seqEnd, +static void snakeDraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis) /* Draw linked features items. */ { struct slList *item; int y; struct linkedFeatures *lf; double scale = scaleForWindow(width, seqStart, seqEnd); int height = snakeHeight(tg, vis); hvGfxSetClip(hvg, xOff, yOff, width, height); // score snakes by how many bases they cover for (item = tg->items; item != NULL; item = item->next) { @@ -449,97 +424,246 @@ } } slSort(&tg->items, linkedFeaturesCmpScore); y = yOff; for (item = tg->items; item != NULL; item = item->next) { if(tg->itemColor != NULL) color = tg->itemColor(tg, item, hvg); tg->drawItemAt(tg, item, hvg, xOff, y, scale, font, color, vis); y += tg->itemHeight(tg, item); } } -void snakeLeftLabels(struct track *tg, int seqStart, int seqEnd, - struct hvGfx *hvg, int xOff, int yOff, int width, int height, - boolean withCenterLabels, MgFont *font, Color color, - enum trackVisibility vis) -{ -} - -void packSnakeDrawAt(struct track *tg, void *item, +static void packSnakeDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) /* Draw a single simple bed item at position. */ { struct linkedFeatures *lf = (struct linkedFeatures *)item; calcPackSnake(tg, item); +if (lf->components == NULL) + return; + +boolean isHalSnake = FALSE; +if (lf->original == (void *)1) + isHalSnake = TRUE; + +struct snakeFeature *sf = (struct snakeFeature *)lf->components, *prevSf = NULL; +int s = tg->itemStart(tg, item); +int sClp = (s < winStart) ? winStart : s; +int x1 = round((sClp - winStart)*scale) + xOff; +int textX = x1; +int yOff = y; +boolean withLabels = (withLeftLabels && (vis == tvPack) && !tg->drawName); +unsigned labelColor = MG_BLACK; + +// draw the labels (this code needs a clean up ) +if (withLabels) + { + char *name = tg->itemName(tg, item); + int nameWidth = mgFontStringWidth(font, name); + int dotWidth = tl.nWidth/2; + boolean snapLeft = FALSE; + boolean drawNameInverted = FALSE; + textX -= nameWidth + dotWidth; + snapLeft = (textX < insideX); + /* Special tweak for expRatio in pack mode: force all labels + * left to prevent only a subset from being placed right: */ + snapLeft |= (startsWith("expRatio", tg->tdb->type)); +#ifdef IMAGEv2_NO_LEFTLABEL_ON_FULL + if (theImgBox == NULL && snapLeft) +#else///ifndef IMAGEv2_NO_LEFTLABEL_ON_FULL + if (snapLeft) /* Snap label to the left. */ +#endif ///ndef IMAGEv2_NO_LEFTLABEL_ON_FULL + { + textX = leftLabelX; + assert(hvgSide != NULL); + hvGfxUnclip(hvgSide); + hvGfxSetClip(hvgSide, leftLabelX, yOff, insideWidth, tg->height); + if(drawNameInverted) + { + int boxStart = leftLabelX + leftLabelWidth - 2 - nameWidth; + hvGfxBox(hvgSide, boxStart, y, nameWidth+1, tg->heightPer - 1, color); + hvGfxTextRight(hvgSide, leftLabelX, y, leftLabelWidth-1, tg->heightPer, + MG_WHITE, font, name); + } + else + hvGfxTextRight(hvgSide, leftLabelX, y, leftLabelWidth-1, tg->heightPer, + labelColor, font, name); + hvGfxUnclip(hvgSide); + hvGfxSetClip(hvgSide, insideX, yOff, insideWidth, tg->height); + } + else + { + if(drawNameInverted) + { + hvGfxBox(hvg, textX - 1, y, nameWidth+1, tg->heightPer-1, color); + hvGfxTextRight(hvg, textX, y, nameWidth, tg->heightPer, MG_WHITE, font, name); + } + else + hvGfxTextRight(hvg, textX, y, nameWidth, tg->heightPer, labelColor, font, name); + } + } + +// now we're going to draw the boxes + +s = sf->start; int lastE = -1; +int lastS = -1; int offY = y; -struct snakeFeature *sf, *prevSf; int lineHeight = tg->lineHeight ; int tStart, tEnd, qStart; int qs, qe; -int s, e; int heightPer = tg->heightPer; int lastX = -1,lastY = y; int lastQEnd = 0; int lastLevel = -1; +int e; qe = lastQEnd = 0; for (sf = (struct snakeFeature *)lf->components; sf != NULL; lastQEnd = qe, prevSf = sf, sf = sf->next) { qs = sf->qStart; qe = sf->qEnd; y = offY + (sf->level * 2) * lineHeight; s = sf->start; e = sf->end; tEnd = sf->end; + int osx; int sx, ex; if (!positiveRangeIntersection(winStart, winEnd, s, e)) continue; - sx = round((double)((int)s-winStart)*scale) + xOff; + osx = sx = round((double)((int)s-winStart)*scale) + xOff; ex = round((double)((int)e-winStart)*scale) + xOff; // color by strand - color = (sf->orientation == -1) ? MG_RED : MG_BLUE; + static Color darkBlueColor = 0; + static Color darkRedColor = 0; + if (darkRedColor == 0) + { + //the light blue: rgb(149, 204, 252) + //the light red: rgb(232, 156, 156) + darkRedColor = hvGfxFindColorIx(hvg, 232,156,156); + darkBlueColor = hvGfxFindColorIx(hvg, 149,204,252); + } + color = (sf->orientation == -1) ? darkRedColor : darkBlueColor; int w = ex - sx; if (w == 0) w = 1; assert(w > 0); char buffer[1024]; safef(buffer, sizeof buffer, "%d %d",sf->qStart,sf->qEnd); if (sx < insideX) { int olap = insideX - sx; sx = insideX; w -= olap; } + char qAddress[4096]; + safef(qAddress, sizeof qAddress, "qName=%s&qs=%d&qe=%d&qWidth=%d",tg->itemName(tg, item), qs, qe, winEnd - winStart); mapBoxHgcOrHgGene(hvg, s, e, sx+1, y, w-2, heightPer, tg->track, - "blockAlign", buffer, NULL, TRUE, "boxAlignExtra=on"); + buffer, buffer, NULL, TRUE, qAddress); hvGfxBox(hvg, sx, y, w, heightPer, color); + int ow = w; + + // now draw the mismatches if we're at high enough resolution + if (winBaseCount < 50000) + { + char *twoBitString = trackDbSetting(tg->tdb, "twoBit"); + static struct twoBitFile *tbf = NULL; + static char *lastTwoBitString = NULL; + static struct dnaSeq *seq = NULL; + static char *lastQName = NULL; + + // sequence for chain snakes is in 2bit files which we cache + if (!isHalSnake) + { + if (twoBitString == NULL) + twoBitString = "/gbdb/hg19/hg19.2bit"; + + if ((lastTwoBitString == NULL) || + differentString(lastTwoBitString, twoBitString)) + { + if (tbf != NULL) + { + lastQName = NULL; + twoBitClose(&tbf); + } + tbf = twoBitOpen(twoBitString); + } + + // we're reading in the whole chrom + if ((lastQName == NULL) || differentString(sf->qName, lastQName)) + seq = twoBitReadSeqFrag(tbf, sf->qName, 0, 0); + lastQName = sf->qName; + lastTwoBitString = twoBitString; + } + + char *ourDna; + if (isHalSnake) + ourDna = sf->sequence; + else + ourDna = &seq->dna[sf->qStart]; + + int seqLen = sf->qEnd - sf->qStart; + toUpperN(ourDna, seqLen); + if (!isHalSnake && (sf->orientation == -1)) + reverseComplement(ourDna,seqLen); + + // get the reference sequence + struct dnaSeq *extraSeq = hDnaFromSeq(database, chromName, sf->start, sf->end, dnaUpper); + int si = s; + char *ptr1 = extraSeq->dna; + char *ptr2 = ourDna; + for(; si < e; si++,ptr1++,ptr2++) + { + if (*ptr1 != *ptr2) + { + int misX1 = round((double)((int)si-winStart)*scale) + xOff; + int misX2 = round((double)((int)(si+1)-winStart)*scale) + xOff; + int w1 = misX2 - misX1; + if (w1 < 1) + w1 = 1; + + // mismatch! + hvGfxBox(hvg, misX1, y, w1, heightPer, MG_RED); + } + } + + // if we're zoomed to base level, draw sequence of mismatch + if (zoomedToBaseLevel) + { + spreadAlignString(hvg, osx, y, ow, heightPer, MG_WHITE, font, ourDna, + extraSeq->dna, seqLen, TRUE, FALSE); + } + + } sf->drawn = TRUE; tEnd = e; tStart = s; qStart = sf->qStart; lastY = y; lastLevel = sf->level; //lastX = x; } + +// now we're going to draw the lines between the blocks + lastX = -1,lastY = y; lastQEnd = 0; lastLevel = 0; qe = lastQEnd = 0; prevSf = NULL; for (sf = (struct snakeFeature *)lf->components; sf != NULL; lastQEnd = qe, prevSf = sf, sf = sf->next) { int y1, y2; int sx, ex; qs = sf->qStart; qe = sf->qEnd; if (lastLevel == sf->level) { y1 = offY + (lastLevel * 2) * lineHeight + lineHeight/2; y2 = offY + (sf->level * 2) * lineHeight + lineHeight/2; @@ -557,340 +681,154 @@ s = sf->start; e = sf->end; sx = round((double)((int)s-winStart)*scale) + xOff; ex = round((double)((int)e-winStart)*scale) + xOff; color = (sf->orientation == -1) ? MG_RED : MG_BLUE; if (lastX != -1) { char buffer[1024]; #define MG_ORANGE 0xff0082E6 int color = MG_GRAY; if (lastQEnd != qs) color = MG_ORANGE; -#ifdef NOTNOW // insert in query - if (sf->orientation == -1) + // draw the vertical orange bars if there is an insert in the other sequence + if ((winBaseCount < 50000) ) { - if ((lastE == e) && (qs != lastQEnd)) + if ((sf->orientation == 1) && (qs != lastQEnd) && (lastE == s)) { - printf("%d ",qs-lastQEnd); - hvGfxLine(hvg, ex, y2, ex, y2 + lineHeight, MG_ORANGE); - } + hvGfxLine(hvg, sx, y2 - lineHeight/2 , sx, y2 + lineHeight/2, MG_ORANGE); + safef(buffer, sizeof buffer, "%dbp", qs - lastQEnd); + mapBoxHgcOrHgGene(hvg, s, e, sx, y2 - lineHeight/2, 1, lineHeight, tg->track, + "foo", buffer, NULL, TRUE, NULL); } - else - { - if ((lastE == s )) // && (qs != lastQEnd)) - printf("%d ",qs-lastQEnd); - if ((lastE == s ) && (qs != lastQEnd)) + else if ((sf->orientation == -1) && (qs != lastQEnd) && (lastS == e)) { - printf("%d ",qs-lastQEnd); - hvGfxLine(hvg, sx, y2, sx, y2 + lineHeight, MG_ORANGE); - printf("%d %d |",lastE,s); + hvGfxLine(hvg, ex, y2 - lineHeight/2 , ex, y2 + lineHeight/2, MG_ORANGE); + safef(buffer, sizeof buffer, "%dbp", qs - lastQEnd); + mapBoxHgcOrHgGene(hvg, s, e, ex, y2 - lineHeight/2, 1, lineHeight, tg->track, + "foo", buffer, NULL, TRUE, NULL); } } -#endif + // now draw the lines between blocks if ((!((lastX == sx) && (y1 == y2))) && (sf->drawn || ((prevSf != NULL) && (prevSf->drawn))) && (((lastE > winStart) && (lastE < winEnd)) || ((s > winStart) && (s < winEnd)))) { if (lastLevel == sf->level) { safef(buffer, sizeof buffer, "%dbp", qs - lastQEnd); if (sf->orientation == -1) { if (lastX != ex) { hvGfxLine(hvg, ex, y1, lastX, y2, color); mapBoxHgcOrHgGene(hvg, s, e, ex, y1, lastX-ex, 1, tg->track, - "foo", buffer, NULL, TRUE, NULL); + "", buffer, NULL, TRUE, NULL); } } else { - if (lastX != sx - 1) + if (lastX != sx) { hvGfxLine(hvg, lastX, y1, sx, y2, color); mapBoxHgcOrHgGene(hvg, s, e, lastX, y1, sx-lastX, 1, tg->track, - "foo", buffer, NULL, TRUE, NULL); + "", buffer, NULL, TRUE, NULL); } } } else if (lastLevel > sf->level) { hvGfxLine(hvg, lastX, y1, sx, y2, color); hvGfxLine(hvg, sx, y2, sx, y2 - lineHeight - lineHeight/3, color); char buffer[1024]; safef(buffer, sizeof buffer, "%d-%d %dbp gap",prevSf->qStart,prevSf->qEnd, qs - lastQEnd); mapBoxHgcOrHgGene(hvg, s, e, sx, y2 - lineHeight - lineHeight/3, 2, lineHeight + lineHeight/3, tg->track, - "foo", buffer, NULL, TRUE, NULL); + "", buffer, NULL, TRUE, NULL); } else { - hvGfxLine(hvg, lastX-1, y1, sx, y2, color); - hvGfxLine(hvg, sx, y2, sx, y2 + lineHeight , color); char buffer[1024]; safef(buffer, sizeof buffer, "%d-%d %dbp gap",prevSf->qStart,prevSf->qEnd, qs - lastQEnd); + if (sf->orientation == -1) + { + hvGfxLine(hvg, lastX-1, y1, ex, y2, color); + hvGfxLine(hvg, ex, y2, ex, y2 + lineHeight , color); + mapBoxHgcOrHgGene(hvg, s, e, ex-1, y2, 2, lineHeight , tg->track, + "", buffer, NULL, TRUE, NULL); + } + else + { + hvGfxLine(hvg, lastX-1, y1, sx, y2, color); + hvGfxLine(hvg, sx, y2, sx, y2 + lineHeight , color); mapBoxHgcOrHgGene(hvg, s, e, sx-1, y2, 2, lineHeight , tg->track, - "foo", buffer, NULL, TRUE, NULL); + "", buffer, NULL, TRUE, NULL); + + } } } } tEnd = e; tStart = s; qStart = sf->qStart; if (sf->orientation == -1) lastX = sx; else lastX = ex; + lastS = s; lastE = e; lastLevel = sf->level; lastQEnd = qe; } } -void fullSnakeDrawAt(struct track *tg, void *item, - struct hvGfx *hvg, int xOff, int y, double scale, - MgFont *font, Color color, enum trackVisibility vis) -/* Draw a single simple bed item at position. */ -{ -struct linkedFeatures *lf = (struct linkedFeatures *)item; -struct snakeFeature *sf, *prevSf; -int s, e; -int heightPer = tg->heightPer; -int lineHeight = tg->lineHeight ; -int oldOrient = 0; -int tStart, tEnd, qStart; -int lastQEnd = 0; -int midY; -int qs, qe; -qStart = 0; -tStart = xOff; -tEnd = winEnd; -prevSf = NULL; - -qe = lastQEnd = 0; -for (sf = (struct snakeFeature *)lf->components; sf != NULL; lastQEnd = qe, prevSf = sf, sf = sf->next) - { - int orient = sf->orientation; - midY = y + heightPer/2; - - qs = sf->qStart; - s = sf->start; e = sf->end; - /* - if (qs < lastQEnd ) - continue; - */ - - qe = sf->qEnd; - /* - if ((e < winStart) || (s > winEnd)) - continue; - */ - - //if (s < winStart) s = winStart; - - if (((oldOrient) && (oldOrient != orient)) - || ((oldOrient == 1) && (tEnd) && (s < tEnd)) - || ((oldOrient == -1) && (tStart) && (e > tStart))) - { - if ((qStart) && (sf->qStart - qStart) < 500000) - { - if (oldOrient == 1) - { - if ((orient == -1) && (tEnd < sf->start)) - { - int x1, x2, x3, w; - - x1 = round((double)((int)tEnd-winStart)*scale) + xOff; - x2 = round((double)((int)e-winStart)*scale) + xOff + 8; - x3 = round((double)((int)sf->end-winStart)*scale) + xOff; - w = x2-x1; - hvGfxLine(hvg, x1, midY, x2, midY, color); - hvGfxLine(hvg, x2, lineHeight + midY, x2, midY, color); - hvGfxLine(hvg, x2, lineHeight+midY, x3, lineHeight+midY, color); - clippedBarbs(hvg, x1, midY, w, tl.barbHeight, tl.barbSpacing, - oldOrient, color, FALSE); - clippedBarbs(hvg, x3, midY + lineHeight, x2-x3, tl.barbHeight, tl.barbSpacing, - orient, color, FALSE); - } - else if ((orient == -1) && (tEnd > sf->start)) - { - int x1, x2, x3, w; - - x1 = round((double)((int)tEnd-winStart)*scale) + xOff; - x2 = round((double)((int)tEnd-winStart)*scale) + xOff + 8; - x3 = round((double)((int)sf->end-winStart)*scale) + xOff; - w = x2-x1; - hvGfxLine(hvg, x1, midY, x2, midY, color); - hvGfxLine(hvg, x2, lineHeight + midY, x2, midY, color); - hvGfxLine(hvg, x2, lineHeight+midY, x3, lineHeight+midY, color); - clippedBarbs(hvg, x1, midY, w+1, tl.barbHeight, tl.barbSpacing, - oldOrient, color, FALSE); - clippedBarbs(hvg, x3, midY + lineHeight, x2-x3+1, tl.barbHeight, tl.barbSpacing, - orient, color, FALSE); - } - else if ((orient == 1) && (s < tEnd)) - { - int x1, x2, x3,x4, w; - - x1 = round((double)((int)tEnd-winStart)*scale) + xOff; - x2 = round((double)((int)tEnd-winStart)*scale) + xOff + 8; - x3 = round((double)((int)s-winStart)*scale) + xOff - 8; - x4 = round((double)((int)s-winStart)*scale) + xOff; - w = x2-x1; - hvGfxLine(hvg, x1, midY, x2, midY, color); - hvGfxBox(hvg, x2, midY-2, 4, 4, color); - hvGfxBox(hvg, x3 - 4, midY-2 + lineHeight, 4, 4, color); - hvGfxLine(hvg, x3, lineHeight + midY, x4, lineHeight+midY, color); - clippedBarbs(hvg, x1, midY, w+1, tl.barbHeight, tl.barbSpacing, - oldOrient, color, FALSE); - if (x3 > x4) - printf("oops\n"); - clippedBarbs(hvg, x3, midY + lineHeight, x4-x3+1, tl.barbHeight, tl.barbSpacing, - orient , color, FALSE); - } - } - else if (oldOrient == -1) - { - if ((orient == 1) && (tStart >= sf->start)) - { - int x1, x2, x3, w; - - x1 = round((double)((int)tStart-winStart)*scale) + xOff; - x2 = round((double)((int)sf->start-winStart)*scale) + xOff - 8; - x3 = round((double)((int)sf->start-winStart)*scale) + xOff; - w = x1 - x2; - hvGfxLine(hvg, x1, midY, x2, midY, color); - hvGfxLine(hvg, x2, lineHeight + midY, x2, midY, color); - hvGfxLine(hvg, x2, lineHeight+midY, x3, lineHeight+midY, color); - clippedBarbs(hvg, x2, midY, w, tl.barbHeight, tl.barbSpacing, - oldOrient, color, FALSE); - clippedBarbs(hvg, x2, lineHeight+midY, x3-x2+1, tl.barbHeight, tl.barbSpacing, - orient, color, FALSE); - } - else if ((orient == 1) && (tStart < sf->start)) - { - int x1, x2, x3, w; - - x1 = round((double)((int)tStart-winStart)*scale) + xOff; - x2 = round((double)((int)tStart-winStart)*scale) + xOff - 8; - x3 = round((double)((int)sf->start-winStart)*scale) + xOff; - w = x1-x2; - hvGfxLine(hvg, x1, midY, x2, midY, color); - hvGfxLine(hvg, x2, lineHeight + midY, x2, midY, color); - hvGfxLine(hvg, x2, lineHeight+midY, x3, lineHeight+midY, color); - clippedBarbs(hvg, x2, midY, w, tl.barbHeight, tl.barbSpacing, - oldOrient, color, FALSE); - if (x3 < x2) - printf("oops\n"); - clippedBarbs(hvg, x2, midY + lineHeight, x3-x2, tl.barbHeight, tl.barbSpacing, - orient, color, FALSE); - } - else if ((orient == -1) && (e > sf->start)) - { - int x1, x2, x3,x4, w; - - x1 = round((double)((int)tStart-winStart)*scale) + xOff; - x2 = round((double)((int)tStart-winStart)*scale) + xOff - 8; - x3 = round((double)((int)e-winStart)*scale) + xOff + 8; - x4 = round((double)((int)e-winStart)*scale) + xOff; - w = x1-x2; - hvGfxLine(hvg, x1, midY, x2, midY, color); - hvGfxBox(hvg, x2, midY-2, 4, 4, color); - hvGfxLine(hvg, x3, lineHeight + midY, x4, lineHeight+midY, color); - hvGfxBox(hvg, x3, lineHeight + midY-2, 4, 4, color); - clippedBarbs(hvg, x2, midY, w+1, tl.barbHeight, tl.barbSpacing, - oldOrient, color, FALSE); - if (x4 > x3) - printf("oops\n"); - clippedBarbs(hvg, x4, midY + lineHeight, x3-x4+1, tl.barbHeight, tl.barbSpacing, - oldOrient , color, FALSE); - } - } - } - - y += lineHeight; - } - else if ((oldOrient) && ((qStart) && (sf->qStart - qStart) < 500000)) - { - int x1, x2, w; - - x1 = round((double)((int)tEnd-winStart)*scale) + xOff; - x2 = round((double)((int)sf->start -winStart)*scale) + xOff; - hvGfxLine(hvg, x1, midY, x2, midY, color); - if (x2 > x1) - { - w = x2-x1; - clippedBarbs(hvg, x1, midY, w+1, tl.barbHeight, tl.barbSpacing, - oldOrient, color, FALSE); - } - else - { - w = x1-x2; - clippedBarbs(hvg, x2, midY, w+1, tl.barbHeight, tl.barbSpacing, - oldOrient, color, FALSE); - } - } - color = lfChromColor(tg, item, hvg); - -color = (sf->orientation == -1) ? MG_RED : MG_BLUE; - drawScaledBoxSample(hvg, s, e, scale, xOff, y, heightPer, - color, lf->score ); - tEnd = e; - tStart = s; - qStart = sf->qStart; - oldOrient = orient; - } -} -void snakeDrawAt(struct track *tg, void *item, +static void snakeDrawAt(struct track *tg, void *item, struct hvGfx *hvg, int xOff, int y, double scale, MgFont *font, Color color, enum trackVisibility vis) /* Draw a single simple bed item at position. */ { if (tg->visibility == tvFull) - fullSnakeDrawAt(tg, item, hvg, xOff, y, scale, - font, color, vis); - else if (tg->visibility == tvPack) packSnakeDrawAt(tg, item, hvg, xOff, y, scale, font, color, vis); } -void fixItems(struct linkedFeatures *lf) -// put all blocks from a single query chromosome into one +static void fixItems(struct linkedFeatures *lf) +// put all chain blocks from a single query chromosome into one // linkedFeatures structure { struct linkedFeatures *firstLf, *next; struct snakeFeature *sf, *nextSf; firstLf = lf; for (;lf; lf = next) { next = lf->next; if (!sameString(firstLf->name, lf->name) && (lf->components != NULL)) { slSort(&firstLf->components, snakeFeatureCmpQStart); firstLf = lf; } for (sf = (struct snakeFeature *)lf->components; sf != NULL; sf = nextSf) { + sf->qName = lf->name; sf->orientation = lf->orientation; nextSf = sf->next; if (firstLf != lf) { lf->components = NULL; slAddHead(&firstLf->components, sf); } } } if (firstLf != NULL) { slSort(&firstLf->components, snakeFeatureCmpQStart); firstLf->next = 0; } @@ -953,57 +891,143 @@ * one or two lines to the edge of the screen. */ #define STARTSLOP 0 #define MULTIPLIER 10 #define MAXLOOK 100000 extra = (STARTSLOP < maxOverLeft) ? STARTSLOP : maxOverLeft; start = seqStart - extra; extra = (STARTSLOP < maxOverRight) ? STARTSLOP : maxOverRight; end = seqEnd + extra; doQuery(conn, fullName, lm, hash, start, end, isSplit, -1); } } hFreeConn(&conn); } +#ifdef USE_HAL +void halSnakeLoadItems(struct track *tg) +{ +struct errCatch *errCatch = errCatchNew(); +if (errCatchStart(errCatch)) + { + char *fileName = trackDbSetting(tg->tdb, "bigDataUrl"); + char *otherSpecies = trackDbSetting(tg->tdb, "otherSpecies"); + int handle = halOpenLOD(fileName); + int needSeq = (winBaseCount < 50000) ? 1 : 0; + struct hal_block_t* head = halGetBlocksInTargetRange(handle, otherSpecies, trackHubSkipHubName(database), chromName, winStart, winEnd, needSeq, 1); + struct hal_block_t* cur = head; + struct linkedFeatures *lf; + struct hash *qChromHash = newHash(5); + struct linkedFeatures *lfList = NULL; + char buffer[4096]; + + while (cur) + { + struct hashEl* hel; + + //safef(buffer, sizeof buffer, "%s.%c", cur->qChrom,cur->strand); + safef(buffer, sizeof buffer, "%s", cur->qChrom); + if ((hel = hashLookup(qChromHash, buffer)) == NULL) + { + AllocVar(lf); + lf->original = (void *)1; + slAddHead(&lfList, lf); + lf->start = 0; + lf->end = 1000000000; + lf->grayIx = maxShade; + lf->name = cloneString(buffer); + lf->orientation = (cur->strand == '+') ? 1 : -1; + hashAdd(qChromHash, lf->name, lf); + } + else + { + lf = hel->val; + } + + struct snakeFeature *sf; + AllocVar(sf); + slAddHead(&lf->components, sf); + + sf->start = cur->tStart; + sf->end = cur->tStart + cur->size; + if (cur->strand == '-') + { + sf->qStart = cur->qStart; + sf->qEnd = cur->qStart + cur->size; + } + else + { + sf->qStart = cur->qStart; + sf->qEnd = cur->qStart + cur->size; + } + sf->orientation = (cur->strand == '+') ? 1 : -1; + sf->sequence = cloneString(cur->sequence); + + // printBlock(stdout, cur); + cur = cur->next; + } + for(lf=lfList; lf ; lf = lf->next) + { + slSort(&lf->components, snakeFeatureCmpQStart); + } + //halFreeBlocks(head); + //halClose(handle, myThread); + + tg->items = lfList; + } +errCatchEnd(errCatch); +if (errCatch->gotError) + { + tg->networkErrMsg = cloneString(errCatch->message->string); + tg->drawItems = bigDrawWarning; + tg->totalHeight = bigWarnTotalHeight; + } +errCatchFree(&errCatch); +} +#endif // USE_HAL + + void snakeLoadItems(struct track *tg) +// Load chains from a mySQL database { char *track = tg->table; struct chain chain; int rowOffset; char **row; struct sqlConnection *conn = hAllocConn(database); struct sqlResult *sr = NULL; struct linkedFeatures *list = NULL, *lf; int qs; char optionChr[128]; /* Option - chromosome filter */ char *optionChrStr; char extraWhere[128] ; struct cartOptions *chainCart; struct chain *pChain; chainCart = (struct cartOptions *) tg->extraUiData; safef( optionChr, sizeof(optionChr), "%s.chromFilter", tg->table); optionChrStr = cartUsualString(cart, optionChr, "All"); int ourStart = winStart; int ourEnd = winEnd; // we're grabbing everything now.. we really should be // doing this as a preprocessing stage, rather than at run-time ourStart = 0; ourEnd = 500000000; +//ourStart = winStart; +//ourEnd = winEnd; if (startsWith("chr",optionChrStr)) { safef(extraWhere, sizeof(extraWhere), "qName = \"%s\" and score > %d",optionChrStr, chainCart->scoreFilter); sr = hRangeQuery(conn, track, chromName, ourStart, ourEnd, extraWhere, &rowOffset); } else { if (chainCart->scoreFilter > 0) { safef(extraWhere, sizeof(extraWhere), "score > \"%d\"",chainCart->scoreFilter); sr = hRangeQuery(conn, track, chromName, ourStart, ourEnd, @@ -1089,30 +1113,50 @@ } static void setNoColor(struct track *tg) { tg->itemColor = chainNoColor; tg->color.r = 0; tg->color.g = 0; tg->color.b = 0; tg->altColor.r = 127; tg->altColor.g = 127; tg->altColor.b = 127; tg->ixColor = MG_BLACK; tg->ixAltColor = MG_GRAY; } +#ifdef USE_HAL +void halSnakeMethods(struct track *tg, struct trackDb *tdb, + int wordCount, char *words[]) +{ +//errAbort("halSnakeMethds\n"); +linkedFeaturesMethods(tg); +tg->canPack = FALSE; +tdb->canPack = FALSE; +tg->loadItems = halSnakeLoadItems; +tg->drawItems = snakeDraw; +tg->mapItemName = lfMapNameFromExtra; +tg->subType = lfSubChain; +//tg->extraUiData = (void *) chainCart; +tg->totalHeight = snakeHeight; + +tg->drawItemAt = snakeDrawAt; +tg->itemHeight = snakeItemHeight; +} +#endif + void snakeMethods(struct track *tg, struct trackDb *tdb, int wordCount, char *words[]) /* Fill in custom parts of alignment chains. */ { struct cartOptions *chainCart; AllocVar(chainCart); boolean normScoreAvailable = chainDbNormScoreAvailable(tdb); /* what does the cart say about coloring option */ chainCart->chainColor = chainFetchColorOption(cart, tdb, FALSE); chainCart->scoreFilter = cartUsualIntClosestToHome(cart, tdb, @@ -1143,26 +1187,26 @@ { char option[128]; /* Option - rainbow chromosome color */ char *optionStr; /* this old option was broken before */ safef(option, sizeof(option), "%s.color", tg->table); optionStr = cartUsualString(cart, option, "on"); if (differentWord("on",optionStr)) { setNoColor(tg); chainCart->chainColor = chainColorNoColors; } else chainCart->chainColor = chainColorChromColors; } -tg->canPack = TRUE; +tg->canPack = FALSE; tg->loadItems = snakeLoadItems; tg->drawItems = snakeDraw; tg->mapItemName = lfMapNameFromExtra; tg->subType = lfSubChain; tg->extraUiData = (void *) chainCart; tg->totalHeight = snakeHeight; tg->drawItemAt = snakeDrawAt; tg->itemHeight = snakeItemHeight; }