cee60adf868375933ac0eb26e1b84048639e804f braney Fri Feb 24 11:07:54 2023 -0800 ongoing work on snakes diff --git src/hg/hgTracks/snake.c src/hg/hgTracks/snake.c index 065a6ca..3e0ba5a 100644 --- src/hg/hgTracks/snake.c +++ src/hg/hgTracks/snake.c @@ -16,35 +16,30 @@ #include "chainCart.h" #include "errCatch.h" #include "twoBit.h" #include "bigWarn.h" #include <pthread.h> #include "trackHub.h" #include "limits.h" #include "snakeUi.h" #include "bits.h" #include "trix.h" #include "chromAlias.h" #include "bigPsl.h" #include "snake.h" -// this is the number of pixels used by the target self-align bar -#define DUP_LINE_HEIGHT 0 -// this is the number of pixels used when displaying the insertion lengths -#define INSERT_TEXT_HEIGHT 0 - 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; } @@ -521,36 +516,36 @@ if (insertHead) { slReverse(&insertHead); calcPackSnakeHelper(insertHead, level + 1); insertHead = NULL; } // do we have any proposed blocks if (proposedList == NULL) return; // we parsed all the blocks in the list to see if they fit in our level // now let's see if the list of blocks for this level is big enough // to actually add +// order the blocks so lowest start position is first +slReverse(&proposedList); struct snakeFeature *temp; double scale = scaleForWindow(insideWidth, winStart, winEnd); int start, end; -// order the blocks so lowest start position is first -slReverse(&proposedList); start=proposedList->start; for(temp=proposedList; temp->next; temp = temp->next) ; end=temp->end; // calculate how big the string of blocks is in screen coordinates double apparentSize = scale * (end - start); if (apparentSize < 0) errAbort("size of a list of blocks should not be less than zero"); // check to see if the apparent size is big enough if (apparentSize < 1) return; @@ -619,41 +614,37 @@ { if (tg->networkErrMsg != NULL) { // we had a parallel load failure tg->drawItems = bigDrawWarning; tg->totalHeight = bigWarnTotalHeight; return bigWarnTotalHeight(tg, vis); } if (vis == tvDense) return tg->lineHeight; if (vis == tvSquish) return tg->lineHeight/2; -int height = DUP_LINE_HEIGHT + INSERT_TEXT_HEIGHT; -struct slList *item = tg->items; - -item = tg->items; +int height = 0; +struct linkedFeatures *item = tg->items; -for (item=tg->items;item; item = item->next) +for (;item; item = item->next) { height += tg->itemHeight(tg, item); } -if (height < DUP_LINE_HEIGHT + tg->lineHeight) - height = DUP_LINE_HEIGHT + tg->lineHeight; return height; } // this is a 16 color palette with every other color being a lighter version of // the color before it static int snakePalette2[] = { 0x1f77b4, 0xaec7e8, 0xff7f0e, 0xffbb78, 0x2ca02c, 0x98df8a, 0xd62728, 0xff9896, 0x9467bd, 0xc5b0d5, 0x8c564b, 0xc49c94, 0xe377c2, 0xf7b6d2, 0x7f7f7f, 0xc7c7c7, 0xbcbd22, 0xdbdb8d, 0x17becf, 0x9edae5 }; static Color hashColor(char *name) { bits32 hashVal = hashString(name); @@ -675,30 +666,72 @@ { width -= -x; x = 0; } if (x + width > insideWidth) { width -= x + width - insideWidth; } mapBoxHgcOrHgGene(hvg, start, end, x, y, width, height, track, item, statusLine, directUrl, withHgsid, extra); } +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 snake 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); + +if ((tg->visibility == tvFull) || (tg->visibility == tvPack)) + { + // score snakes by how many bases they cover + for (item = tg->items; item != NULL; item = item->next) + { + lf = (struct linkedFeatures *)item; + struct snakeFeature *sf; + + lf->score = 0; + for (sf = (struct snakeFeature *)lf->components; sf != NULL; sf = sf->next) + { + lf->score += sf->end - sf->start; + } + } + + 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); + if (vis == tvFull) + y += tg->itemHeight(tg, 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. */ { unsigned showSnpWidth = cartOrTdbInt(cart, tg->tdb, SNAKE_SHOW_SNP_WIDTH, SNAKE_DEFAULT_SHOW_SNP_WIDTH); struct linkedFeatures *lf = (struct linkedFeatures *)item; if (tg->visibility == tvFull) calcFullSnake(tg, item); else if (tg->visibility == tvPack) calcPackSnake(tg, item); @@ -1095,30 +1128,31 @@ 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->next = lf; 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); } } } @@ -1135,51 +1169,42 @@ } static void makeSnakeFeatures(struct linkedFeatures *lf) { for(; lf; lf = lf->next) { struct simpleFeature *sf = lf->components; struct snakeFeature *sfList = NULL; for(;sf; sf = sf->next) { struct snakeFeature *this; AllocVar(this); *(struct simpleFeature *)this = *sf; - /* - if ((lf) && lf->orientation == -1) - { - int temp; - - temp = this->qStart; - this->qStart = lf->qSize - this->qEnd; - this->qEnd = lf->qSize - temp; - } - */ this->orientation = lf->orientation; slAddHead(&sfList, this); } lf->components = (struct simpleFeature *)sfList; } } void maybeLoadSnake(struct track *track) /* check to see if we're doing snakes and if so load the correct methods. */ { boolean doSnake = cartOrTdbBoolean(cart, track->tdb, "doSnake", FALSE); if (doSnake) { track->drawLeftLabels = snakeDrawLeftLabels; track->itemHeight = snakeItemHeight; track->totalHeight = snakeHeight; track->drawItemAt = snakeDrawAt; + track->drawItems = snakeDraw; - slSort(track->items, linkedFeaturesCmpStart); + slSort(&track->items, linkedFeaturesCmpName); makeSnakeFeatures(track->items); fixItems(track->items); track->visibility = track->limitedVis = tvFull; track->canPack = FALSE; } }