537b5bc5e05bc4f094bd3d45f6ec74798351fd76 braney Sun May 22 16:33:23 2011 -0700 now have pack and full modes. Coloring by strand is default. Needs a more useful way of drawing the lines that connect the blocks in pack mode. Maybe snake mode should be option in detail page? That way we can overload the track controls. diff --git src/hg/hgTracks/snakeTrack.c src/hg/hgTracks/snakeTrack.c index 608dcd2..9560efe 100644 --- src/hg/hgTracks/snakeTrack.c +++ src/hg/hgTracks/snakeTrack.c @@ -4,50 +4,173 @@ #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" static char const rcsid[] = "$Id: chainTrack.c,v 1.27 2006/02/23 01:41:31 baertsch Exp $"; +struct snakeFeature +/* Minimal feature - just stores position in browser coordinates. */ + { + struct snakeFeature *next; + int start, end; /* Start/end in browser coordinates. */ + int qStart, qEnd; /* query start/end */ + int level; + int orientation; + }; + +struct level +{ +boolean init; +int orientation; +int edge; +}; + + +static struct level Levels[1000000]; +static int maxLevel = 0; +static int maxEnd = 0; +static struct snakeFeature *newList = NULL; +static int inserts = 0; +static int addedToExist = 0; +static int endCaps = 0; + +static int snakeFeatureCmpQStart(const void *va, const void *vb) +{ +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() +{ +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) +{ +struct snakeFeature *cb = list; +boolean didInit = FALSE; + +if (level > maxLevel) + maxLevel = level; +if (level > ArraySize(Levels)) + errAbort("too many levels"); + +if (Levels[level].init == FALSE) + { + didInit = TRUE; + Levels[level].init = TRUE; + Levels[level].orientation = list->orientation; + if (list->orientation == -1) + Levels[level].edge = 1000000000; // bigger than the biggest chrom + else + Levels[level].edge = 0; + } + +struct snakeFeature *next; +struct snakeFeature *insertHead = NULL; +for(; cb; cb = next) + { + next = cb->next; + //cb->next = NULL; + + if ((Levels[level].orientation != cb->orientation) || + ((cb->orientation == 1) && (Levels[level].edge > cb->start)) || + ((cb->orientation == -1) && (Levels[level].edge < cb->end))) + { + slAddHead(&insertHead, cb); + continue; + } + + if (insertHead) + { + inserts++; + slReverse(&insertHead); + calcSnake(insertHead, level + 1); + insertHead = NULL; + } + + if (!didInit) + { + addedToExist++; + didInit = TRUE; + } + //struct cBlockData *cData; + //AllocVar(cData); + cb->level = level; + //cb->data = (void *)cData; + +//printf("%d ", cb->qStart); + if (cb->orientation == 1) + Levels[level].edge = cb->end; + else + Levels[level].edge = cb->start; + + if (cb->end > maxEnd) + maxEnd = cb->end; + + slAddHead(&newList, cb); + } + +if (insertHead) + { + slReverse(&insertHead); + calcSnake(insertHead, level + 1); + insertHead = NULL; + endCaps++; + } +} struct cartOptions { enum chainColorEnum chainColor; /* ChromColors, ScoreColors, NoColors */ int scoreFilter ; /* filter chains by score if > 0 */ }; 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 simpleFeature *sf; +struct snakeFeature *sf; struct dyString *query = newDyString(1024); char *force = ""; if (isSplit) force = "force index (bin)"; if (chainId == -1) dyStringPrintf(query, "select chainId,tStart,tEnd,qStart from %sLink %s where ", fullName, force); else dyStringPrintf(query, "select chainId, tStart,tEnd,qStart from %sLink where chainId=%d and ", fullName, chainId); if (!isSplit) @@ -66,171 +189,281 @@ struct chain *pChain = lf->extra; lmAllocVar(lm, sf); sf->start = sqlUnsigned(row[1]); sf->end = sqlUnsigned(row[2]); sf->qStart = sqlUnsigned(row[3]); sf->qEnd = sf->qStart + (sf->end - sf->start); if ((pChain) && pChain->qStrand == '-') { int temp; temp = sf->qStart; sf->qStart = pChain->qSize - sf->qEnd; sf->qEnd = pChain->qSize - temp; } - sf->grayIx = lf->orientation; + sf->orientation = lf->orientation; slAddHead(&lf->components, sf); } } sqlFreeResult(&sr); dyStringFree(&query); } -int snakeItemHeight(struct track *tg, void *item) +struct snakeInfo +{ +int maxLevel; +} snakeInfo; + +void calcPackSnake(struct track *tg, void *item) +{ +struct linkedFeatures *lf = (struct linkedFeatures *)item; +if (lf->components == NULL) + { + //lf->filterColor = 0; + return; + } + +if (lf->codons == NULL) + { + clearLevels(); + calcSnake((struct snakeFeature *)lf->components, 0); + lf->components = (struct simpleFeature *)newList; + newList = NULL; + slSort(&lf->components, snakeFeatureCmpQStart); + struct snakeInfo *si; + AllocVar(si); + si->maxLevel = maxLevel; + lf->codons = (struct simpleFeature *)si; + } +} + +int packSnakeItemHeight(struct track *tg, void *item) +{ +struct linkedFeatures *lf = (struct linkedFeatures *)item; +calcPackSnake(tg, item); +struct snakeInfo *si = (struct snakeInfo *)lf->codons; +int lineHeight = tg->lineHeight ; +return (si->maxLevel + 1) * lineHeight; +} + +int fullSnakeItemHeight(struct track *tg, void *item) { -//return 40; struct linkedFeatures *lf = (struct linkedFeatures *)item; -struct simpleFeature *sf; +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 = lf->components; sf ; sf = sf->next) +for (sf = (struct snakeFeature *)lf->components; sf ; sf = sf->next) { - int orient = sf->grayIx; + 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 starting pos. */ { 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, 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 *lfStart = (struct linkedFeatures *)tg->items; struct linkedFeatures *lf; double scale = scaleForWindow(width, seqStart, seqEnd); for(lf = lfStart; lf; lf = lf->next) { - struct simpleFeature *sf; + struct snakeFeature *sf; lf->score = 0; - for (sf = lf->components; sf != NULL; sf = sf->next) + 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); 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 snakeDrawAt(struct track *tg, void *item, +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); + +int x; +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; +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 * lineHeight; + s = sf->start; e = sf->end; + tEnd = sf->end; + x = round((double)((int)tEnd-winStart)*scale) + xOff; + //color = lfChromColor(tg, item, hvg); +color = (sf->orientation == -1) ? MG_RED : MG_BLUE; + + //if (lastX != -1) + //hvGfxLine(hvg, lastX, lastY + lineHeight/2, x, y + lineHeight/2, MG_BLACK); + drawScaledBoxSample(hvg, s, e, scale, xOff, y, heightPer, + color, lf->score ); + tEnd = e; + tStart = s; + qStart = sf->qStart; + lastY = y; + lastX = x; + } +lastX = -1,lastY = y; +lastQEnd = 0; +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 * lineHeight; + s = sf->start; e = sf->end; + tEnd = sf->end; + x = round((double)((int)tEnd-winStart)*scale) + xOff; + //color = lfChromColor(tg, item, hvg); +color = (sf->orientation == -1) ? MG_RED : MG_BLUE; + + if (lastX != -1) + hvGfxLine(hvg, lastX, lastY + lineHeight/2, x, y + lineHeight/2, MG_BLACK); + //drawScaledBoxSample(hvg, s, e, scale, xOff, y, heightPer, + //color, lf->score ); + tEnd = e; + tStart = s; + qStart = sf->qStart; + lastY = y; + lastX = x; + } +} + +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 simpleFeature *sf, *prevSf; +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 = lf->components; sf != NULL; lastQEnd = qe, prevSf = sf, sf = sf->next) +for (sf = (struct snakeFeature *)lf->components; sf != NULL; lastQEnd = qe, prevSf = sf, sf = sf->next) { - int orient = sf->grayIx; + 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 (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; @@ -352,166 +585,147 @@ 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; } } -static int simpleFeatureCmpQStart(const void *va, const void *vb) -{ -const struct simpleFeature *a = *((struct simpleFeature **)va); -const struct simpleFeature *b = *((struct simpleFeature **)vb); -int diff = a->qStart - b->qStart; - -if (diff == 0) +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. */ { - diff = a->start - b->start; - } -return diff; + 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); } static int linkedFeaturesCmpChrom(const void *va, const void *vb) /* Help sort linkedFeatures by starting pos. */ { const struct linkedFeatures *a = *((struct linkedFeatures **)va); const struct linkedFeatures *b = *((struct linkedFeatures **)vb); return strcmp(a->name, b->name); } -int snakeHeight(struct track *tg, enum trackVisibility vis) +void fixItems(struct linkedFeatures *lf) { -int height = 0; -struct slList *item = tg->items, *nextItem; -struct linkedFeatures *firstLf, *lf = (struct linkedFeatures *)tg->items; -struct simpleFeature *sf, *nextSf; - -slSort(&tg->items, linkedFeaturesCmpChrom); - -item = tg->items; +struct linkedFeatures *firstLf, *next; +struct snakeFeature *sf, *nextSf; -lf = (struct linkedFeatures *)tg->items; -if (item) - { firstLf = lf; - for (;item; item = nextItem) +for (;lf; lf = next) { - struct linkedFeatures *lf = (struct linkedFeatures *)item; - nextItem = item->next; + next = lf->next; if (!sameString(firstLf->name, lf->name)) { - slSort(&firstLf->components, simpleFeatureCmpQStart); + slSort(&firstLf->components, snakeFeatureCmpQStart); firstLf = lf; } - for (sf = lf->components; sf != NULL; sf = nextSf) + for (sf = (struct snakeFeature *)lf->components; sf != NULL; sf = nextSf) { - sf->grayIx = lf->orientation; + sf->orientation = lf->orientation; nextSf = sf->next; if (firstLf != lf) { lf->components = NULL; slAddHead(&firstLf->components, sf); + } } } - slSort(&firstLf->components, simpleFeatureCmpQStart); +slSort(&firstLf->components, snakeFeatureCmpQStart); +firstLf->next = 0; +} + +int snakeHeight(struct track *tg, enum trackVisibility vis) +{ +int height = 0; +struct slList *item = tg->items; + +slSort(&tg->items, linkedFeaturesCmpChrom); + +item = tg->items; for (item=tg->items;item; item = item->next) { height += tg->itemHeight(tg, item); } - } -return 3500; //height; +return height; } -static void chainDraw(struct track *tg, int seqStart, int seqEnd, - struct hvGfx *hvg, int xOff, int yOff, int width, - MgFont *font, Color color, enum trackVisibility vis) -/* Draw chained features. This loads up the simple features from - * the chainLink table, calls linkedFeaturesDraw, and then - * frees the simple features again. */ +static void loadLinks(struct track *tg, int seqStart, int seqEnd, + enum trackVisibility vis) { +int start, end, extra; +char fullName[64]; +int maxOverLeft = 0, maxOverRight = 0; +int overLeft, overRight; struct linkedFeatures *lf; -struct simpleFeature *sf; +//struct snakeFeature *sf; struct lm *lm; struct hash *hash; /* Hash of chain ids. */ struct sqlConnection *conn; -//double scale = ((double)(winEnd - winStart))/width; -char fullName[64]; -int start, end, extra; -//struct simpleFeature *lastSf = NULL; -int maxOverLeft = 0, maxOverRight = 0; -int overLeft, overRight; - -if (tg->items == NULL) /*Exit Early if nothing to do */ - return; - lm = lmInit(1024*4); hash = newHash(0); conn = hAllocConn(database); /* Make up a hash of all linked features keyed by * id, which is held in the extras field. To * avoid burning memory on full chromosome views * we'll just make a single simple feature and * exclude from hash chains less than three pixels wide, * since these would always appear solid. */ for (lf = tg->items; lf != NULL; lf = lf->next) { //double pixelWidth = (lf->end - lf->start) / scale; - if (1)//pixelWidth >= 2.5) - { char buf[256]; struct chain *pChain = lf->extra; safef(buf, sizeof(buf), "%d", pChain->id); //hashAdd(hash, lf->extra, lf); hashAdd(hash, buf, lf); overRight = lf->end - seqEnd; if (overRight > maxOverRight) maxOverRight = overRight; overLeft = seqStart - lf->start ; if (overLeft > maxOverLeft) maxOverLeft = overLeft; } - else - { - lmAllocVar(lm, sf); - sf->start = lf->start; - sf->end = lf->end; - sf->grayIx = lf->grayIx; - lf->components = sf; - } - } /* if some chains are bigger than 3 pixels */ if (hash->size) { boolean isSplit = TRUE; /* Make up range query. */ sprintf(fullName, "%s_%s", chromName, tg->table); if (!hTableExists(database, fullName)) { strcpy(fullName, tg->table); isSplit = FALSE; } /* in dense mode we don't draw the lines * so we don't need items off the screen @@ -596,54 +810,34 @@ { lmAllocVar(lm, sf); sf->start = 0; sf->end = 1; sf->grayIx = lf->grayIx; sf->qStart = lf->components->qStart; sf->qEnd = sf->qStart + (sf->end - sf->start); sf->next = lf->components; lf->components = sf; slSort(&lf->components, linkedFeaturesCmpStart); } } #endif } } -if (1) -{ -snakeHeight(tg, vis); -snakeDraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, - font, color, vis); - } - else - { -linkedFeaturesDraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, - font, color, vis); - } -/* Cleanup time. */ -for (lf = tg->items; lf != NULL; lf = lf->next) - lf->components = NULL; - -lmCleanup(&lm); -freeHash(&hash); hFreeConn(&conn); } void snakeLoadItems(struct track *tg) -/* Load up all of the chains from correct table into tg->items - * item list. At this stage to conserve memory for other tracks - * we don't load the links into the components list until draw time. */ { 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; @@ -659,31 +853,31 @@ sr = hRangeQuery(conn, track, chromName, winStart, winEnd, extraWhere, &rowOffset); } else { if (chainCart->scoreFilter > 0) { snprintf(extraWhere, sizeof(extraWhere), "score > \"%d\"",chainCart->scoreFilter); sr = hRangeQuery(conn, track, chromName, winStart, winEnd, extraWhere, &rowOffset); } else { snprintf(extraWhere, sizeof(extraWhere), " "); - sr = hRangeQuery(conn, track, chromName, winStart, winEnd, + sr = hRangeQuery(conn, track, chromName, 0, 500000000, NULL, &rowOffset); } } while ((row = sqlNextRow(sr)) != NULL) { //char buf[16]; chainHeadStaticLoad(row + rowOffset, &chain); AllocVar(pChain); *pChain = chain; AllocVar(lf); lf->start = lf->tallStart = chain.tStart; lf->end = lf->tallEnd = chain.tEnd; lf->grayIx = maxShade; if (chainCart->chainColor == chainColorScoreColors) { @@ -697,61 +891,56 @@ lf->filterColor = -1; if (chain.qStrand == '-') { lf->orientation = -1; qs = chain.qSize - chain.qEnd; } else { lf->orientation = 1; qs = chain.qStart; } char buffer[1024]; snprintf(buffer, sizeof(buffer), "%s", chain.qName); - //snprintf(buffer, sizeof(buffer), "%s %c %dk", - //chain.qName, chain.qStrand, qs/1000); lf->name = cloneString(buffer); - //snprintf(lf->name, sizeof(lf->name), "%s %c %dk", - // chain.qName, chain.qStrand, qs/1000); - //snprintf(lf->name, sizeof(lf->name), "%s", - // chain.qName); - //snprintf(lf->popUp, sizeof(lf->name), "%s %c start %d size %d", - // chain.qName, chain.qStrand, qs, chain.qEnd - chain.qStart); - //snprintf(buf, sizeof(buf), "%d", chain.id); - //lf->extra = cloneString(buf); lf->extra = pChain; - //printf("setting extra to %llu\n",(long long) pChain); slAddHead(&list, lf); } /* Make sure this is sorted if in full mode. Sort by score when * coloring by score and in dense */ if (tg->visibility != tvDense) slSort(&list, linkedFeaturesCmpStart); else if ((tg->visibility == tvDense) && (chainCart->chainColor == chainColorScoreColors)) slSort(&list, chainCmpScore); else slReverse(&list); tg->items = list; /* Clean up. */ sqlFreeResult(&sr); hFreeConn(&conn); + +/* now load the items */ +//loadLinks(tg, 0, 500000000, tg->visibility); +loadLinks(tg, winStart, winEnd, tg->visibility); +lf=tg->items; +fixItems(lf); } /* chainLoadItems() */ static Color chainScoreColor(struct track *tg, void *item, struct hvGfx *hvg) { struct linkedFeatures *lf = (struct linkedFeatures *)item; return(tg->colorShades[lf->grayIx]); } static Color chainNoColor(struct track *tg, void *item, struct hvGfx *hvg) { return(tg->ixColor); } static void setNoColor(struct track *tg) @@ -760,46 +949,41 @@ 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; } void snakeMethods(struct track *tg, struct trackDb *tdb, int wordCount, char *words[]) /* Fill in custom parts of alignment chains. */ { -//boolean normScoreAvailable = FALSE; struct cartOptions *chainCart; -//char scoreOption[256]; AllocVar(chainCart); boolean normScoreAvailable = chainDbNormScoreAvailable(tdb); -//normScoreAvailable = chainDbNormScoreAvailable(chromName, tg->table, NULL); /* what does the cart say about coloring option */ chainCart->chainColor = chainFetchColorOption(cart, tdb, FALSE); -//snprintf( scoreOption, sizeof(scoreOption), "%s.scoreFilter", tdb->tableName); chainCart->scoreFilter = cartUsualIntClosestToHome(cart, tdb, FALSE, SCORE_FILTER, 0); -//chainCart->scoreFilter = cartUsualInt(cart, scoreOption, 0); linkedFeaturesMethods(tg); tg->itemColor = lfChromColor; /* default coloring option */ /* if normScore column is available, then allow coloring */ if (normScoreAvailable) { switch (chainCart->chainColor) { case (chainColorScoreColors): tg->itemColor = chainScoreColor; tg->colorShades = shadesOfGray; break; case (chainColorNoColors): @@ -814,25 +998,26 @@ { char option[128]; /* Option - rainbow chromosome color */ char *optionStr; /* this old option was broken before */ snprintf(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->loadItems = snakeLoadItems; -tg->drawItems = chainDraw; +tg->drawItems = snakeDraw; tg->mapItemName = lfMapNameFromExtra; tg->subType = lfSubChain; tg->extraUiData = (void *) chainCart; -// tg->drawItems = snakeDraw; - tg->drawItemAt = snakeDrawAt; tg->totalHeight = snakeHeight; + + tg->drawItemAt = snakeDrawAt; tg->itemHeight = snakeItemHeight; }