bb7c285d51eabd45fe7fbb3ae297acd0324915b7 kent Tue Apr 19 15:09:50 2011 -0700 Refactoring in hopes of making auto-scale work as you'd hope with multiwigs. That still isn't there, this is just preliminaries. diff --git src/hg/hgTracks/wigTrack.c src/hg/hgTracks/wigTrack.c index c31ea99..2f1a6b7 100644 --- src/hg/hgTracks/wigTrack.c +++ src/hg/hgTracks/wigTrack.c @@ -114,39 +114,41 @@ colorTrack->loadItems(colorTrack); colorTrack->ixColor = hvGfxFindRgb(hvg, &colorTrack->color); colorTrack->ixAltColor = hvGfxFindRgb(hvg, &colorTrack->altColor); } if(colorTrack->drawItemAt == linkedFeaturesDrawAt) wigFillInColorLfArray(wigTrack, colorArray, colSize, colorTrack); else if(colorTrack->drawItemAt == bedDrawSimpleAt) wigFillInColorBedArray(wigTrack, colorArray, colSize, colorTrack, hvg); if(trackLoaded && colorTrack->freeItems != NULL) colorTrack->freeItems(colorTrack); } void wigSetCart(struct track *track, char *dataID, void *dataValue) - /* set one of the variables in the wigCart */ +/* set one of the variables in the wigCart. Actually just MIN_Y or MAX_Y */ { struct wigCartOptions *wigCart; wigCart = (struct wigCartOptions *) track->extraUiData; if (sameWord(dataID, MIN_Y)) wigCart->minY = *((double *)dataValue); else if (sameWord(dataID, MAX_Y)) wigCart->maxY = *((double *)dataValue); +else + internalErr(); } /* these two routines unused at this time */ #if defined(NOT) static void wigItemFree(struct wigItem **pEl) /* Free up a wigItem. */ { struct wigItem *el = *pEl; if (el != NULL) { /* freeMem(el->name); DO NOT - this belongs to tg->mapName */ freeMem(el->db); freeMem(el->file); freez(pEl); } @@ -529,54 +531,46 @@ sqlFreeResult(&sr); hFreeConn(&conn); slReverse(&wiList); tg->items = wiList; } /* wigLoadItems() */ static void wigFreeItems(struct track *tg) { #if defined(DEBUG) safef(dbgMsg, DBGMSGSZ, "I haven't seen wigFreeItems ever called ?"); wigDebugPrint("wigFreeItems"); #endif } -struct preDrawElement * initPreDraw(int width, int *preDrawSize, - int *preDrawZero) -/* initialize a preDraw array of size width */ +struct preDrawContainer *initPreDrawContainer(int width) +/* Initialize preDraw of given size */ { -struct preDrawElement *preDraw = (struct preDrawElement *)NULL; -int i = 0; - -/* we are going to keep an array that is three times the size of - * the screen to allow a screen full on either side of the visible - * region. Those side screens can be used in the smoothing - * operation so there won't be any discontinuity at the visible screen - * boundaries. - */ -*preDrawSize = width * 3; -*preDrawZero = width / 3; -preDraw = (struct preDrawElement *) needMem ((size_t) - *preDrawSize * sizeof(struct preDrawElement)); -for (i = 0; i < *preDrawSize; ++i) +struct preDrawContainer *pre; +AllocVar(pre); +int size = pre->preDrawSize = width + 2*wiggleSmoothingMax; +pre->preDrawZero = wiggleSmoothingMax; +struct preDrawElement *preDraw = AllocArray(pre->preDraw, pre->preDrawSize); +int i; +for (i = 0; i < size; ++i) { preDraw[i].count = 0; preDraw[i].max = wigEncodeStartingUpperLimit; preDraw[i].min = wigEncodeStartingLowerLimit; } -return preDraw; +return pre; } static double doTransform(double x, enum wiggleTransformFuncEnum transformFunc) /* Do log-type transformation if asked. */ { if (transformFunc == wiggleTransformFuncLog) { if (x >= 0) x = log(1+x); else x = -log(1-x); } return x; } @@ -1110,32 +1104,32 @@ if (Span < minimalSpan) minimalSpan = Span; } hashElFreeList(&elList); /* There may not be a span of 1, use whatever is lowest */ if (minimalSpan > usingDataSpan) usingDataSpan = minimalSpan; return usingDataSpan; } void wigDrawPredraw(struct track *tg, int seqStart, int seqEnd, struct hvGfx *hvg, int xOff, int yOff, int width, MgFont *font, Color color, enum trackVisibility vis, - struct preDrawContainer *preDrawList, - int preDrawZero, int preDrawSize, double *retGraphUpperLimit, double *retGraphLowerLimit) + struct preDrawContainer *preDrawList, int preDrawZero, + int preDrawSize, double *retGraphUpperLimit, double *retGraphLowerLimit) /* Draw once we've figured out predraw... */ { enum wiggleYLineMarkEnum yLineOnOff; double yLineMark; /* determined from data */ double overallUpperLimit = wigEncodeStartingUpperLimit; double overallLowerLimit = wigEncodeStartingLowerLimit; double overallRange=0; /* determined from data */ double graphUpperLimit=0; /* scaling choice will set these */ double graphLowerLimit=0; /* scaling choice will set these */ double graphRange=0; /* scaling choice will set these */ double epsilon; /* range of data in one pixel */ Color *colorArray = NULL; /* Array of pixels to be drawn. */ struct wigCartOptions *wigCart = (struct wigCartOptions *) tg->extraUiData; @@ -1214,65 +1208,63 @@ drawArbitraryYLine(vis, wigCart->yLineOnOff, graphUpperLimit, graphLowerLimit, hvg, xOff, yOff, width, tg->lineHeight, wigCart->yLineMark, graphRange, wigCart->yLineOnOff); wigMapSelf(tg, hvg, seqStart, seqEnd, xOff, yOff, width); freez(&colorArray); if (retGraphUpperLimit != NULL) *retGraphUpperLimit = graphUpperLimit; if (retGraphLowerLimit != NULL) *retGraphLowerLimit = graphLowerLimit; } - -static void wigDrawItems(struct track *tg, int seqStart, int seqEnd, - struct hvGfx *hvg, int xOff, int yOff, int width, - MgFont *font, Color color, enum trackVisibility vis) -/* Draw wiggle items that resolve to doing a box for each pixel. */ +struct preDrawContainer *wigLoadPreDraw(struct track *tg, int seqStart, int seqEnd, int width) +/* Do bits that load the predraw buffer tg->preDraw and also preDrawSize and preDrawZero. */ { struct wigItem *wi; double pixelsPerBase = scaleForPixels(width); double basesPerPixel = 1.0; int itemCount = 0; char currentFile[PATH_LEN]; int wibFH = 0; /* file handle to binary file */ -struct preDrawElement *preDraw; /* to accumulate everything in prep for draw */ -int preDrawZero; /* location in preDraw where screen starts */ -int preDrawSize; /* size of preDraw array */ int i; /* an integer loop counter */ int x1 = 0; /* screen coordinates */ int x2 = 0; /* screen coordinates */ int usingDataSpan = 1; /* will become larger if possible */ if (tg->items == NULL) - return; + return NULL; currentFile[0] = '\0'; if (pixelsPerBase > 0.0) basesPerPixel = 1.0 / pixelsPerBase; /* width - width of drawing window in pixels * pixelsPerBase - pixels per base * basesPerPixel - calculated as 1.0/pixelsPerBase */ itemCount = 0; -preDraw = initPreDraw(width, &preDrawSize, &preDrawZero); +/* Allocate predraw and save it and related info in the track. */ +struct preDrawContainer *pre = tg->preDrawContainer = initPreDrawContainer(width); +struct preDrawElement *preDraw = pre->preDraw; /* to accumulate everything in prep for draw */ +int preDrawZero = pre->preDrawZero; /* location in preDraw where screen starts */ +int preDrawSize = pre->preDrawSize; /* size of preDraw array */ usingDataSpan = wigFindSpan(tg, basesPerPixel); /* walk through all the data and prepare the preDraw array */ for (wi = tg->items; wi != NULL; wi = wi->next) { size_t bytesRead; /* to check fread being OK */ int dataOffset = 0; /* within data block during drawing */ ++itemCount; /* Now that we know what Span to draw, see if this item should be * drawn at all. */ @@ -1386,44 +1378,46 @@ if (upperLimit > preDraw[xCoord].max) preDraw[xCoord].max = upperLimit; if (wi->lowerLimit < preDraw[xCoord].min) preDraw[xCoord].min = wi->lowerLimit; preDraw[xCoord].sumData += wi->sumData; preDraw[xCoord].sumSquares += wi->sumSquares; } } } /* Draw if span is correct */ } /* for (wi = tg->items; wi != NULL; wi = wi->next) */ if (wibFH > 0) { close(wibFH); wibFH = 0; } +return pre; +} -/* now we are ready to draw. Each element in the preDraw[] array - * cooresponds to a single pixel on the screen - */ - -struct preDrawContainer *preDrawContainer; -AllocVar(preDrawContainer); -preDrawContainer->preDraw = preDraw; +static void wigDrawItems(struct track *tg, int seqStart, int seqEnd, + struct hvGfx *hvg, int xOff, int yOff, int width, + MgFont *font, Color color, enum trackVisibility vis) +/* Draw wiggle items that resolve to doing a box for each pixel. */ +{ +struct preDrawContainer *pre = wigLoadPreDraw(tg, seqStart, seqEnd, width); +if (pre != NULL) + { wigDrawPredraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis, - preDrawContainer, preDrawZero, preDrawSize, &tg->graphUpperLimit, &tg->graphLowerLimit); - -freeMem(preDrawContainer); -freeMem(preDraw); -} /* wigDrawItems() */ + pre, pre->preDrawZero, pre->preDrawSize, + &tg->graphUpperLimit, &tg->graphLowerLimit); + } +} void wigLeftAxisLabels(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, char *shortLabel, double graphUpperLimit, double graphLowerLimit, boolean showNumbers) /* Draw labels on left for a wiggle-type track. */ { int fontHeight = tl.fontHeight+1; int centerOffset = 0; double lines[2]; /* lines to label */ int numberOfLines = 1; /* at least one: 0.0 */ int i; /* loop counter */ struct wigCartOptions *wigCart = (struct wigCartOptions *) tg->extraUiData; @@ -1548,31 +1542,30 @@ } /* drawing 0.0 and perhaps yLineMark */ } /* if (height >= (3 * fontHeight)) */ } /* if (tg->visibility == tvFull) */ } /* wigAxisLeftLabels */ void wigLeftLabels(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) /* drawing left labels */ { wigLeftAxisLabels(tg, seqStart, seqEnd, hvg, xOff, yOff, width, height, withCenterLabels, font, color, vis, tg->shortLabel, tg->graphUpperLimit, tg->graphLowerLimit, TRUE); } - struct wigCartOptions *wigCartOptionsNew(struct cart *cart, struct trackDb *tdb, int wordCount, char *words[]) /* Create a wigCartOptions from cart contents and tdb. */ { struct wigCartOptions *wigCart; int defaultHeight; /* truncated by limits */ double yLineMark; /* from trackDb or cart */ int maxHeight = atoi(DEFAULT_HEIGHT_PER); int minHeight = MIN_HEIGHT_PER; AllocVar(wigCart); /* These Fetch functions look for variables in the cart bounded by * limits specified in trackDb or returning defaults */ @@ -1586,30 +1579,37 @@ wigFetchMinMaxPixelsWithCart(cart,tdb,tdb->track, &minHeight, &maxHeight, &defaultHeight); wigFetchYLineMarkValueWithCart(cart,tdb,tdb->track, &yLineMark); wigCart->yLineMark = yLineMark; wigCart->yLineOnOff = wigFetchYLineMarkWithCart(cart,tdb,tdb->track, (char **) NULL); wigCart->alwaysZero = wigFetchAlwaysZeroWithCart(cart,tdb,tdb->track, (char **) NULL); wigCart->transformFunc = wigFetchTransformFuncWithCart(cart,tdb,tdb->track, (char **) NULL); wigCart->maxHeight = maxHeight; wigCart->defaultHeight = defaultHeight; wigCart->minHeight = minHeight; wigFetchMinMaxYWithCart(cart,tdb,tdb->track, &wigCart->minY, &wigCart->maxY, NULL, NULL, wordCount, words); wigCart->colorTrack = trackDbSetting(tdb, "wigColorBy"); +char *containerType = trackDbSetting(tdb, "container"); +if (containerType != NULL && sameString(containerType, "multiWig")) + wigCart->isMultiWig = TRUE; + +char *aggregate = wigFetchAggregateValWithCart(cart, tdb); +if (aggregate != NULL) + wigCart->overlay = wigIsOverlayTypeAggregate(aggregate); return wigCart; } /* Make track group for wig multiple alignment. * WARNING ! - track->visibility is merely the default value * from the trackDb entry at this time. It will be set after this * by hgTracks from its cart UI setting. When called in * TotalHeight it will then be the requested visibility. */ void wigMethods(struct track *track, struct trackDb *tdb, int wordCount, char *words[]) { struct wigCartOptions *wigCart = wigCartOptionsNew(cart, tdb, wordCount, words); track->minRange = wigCart->minY; track->maxRange = wigCart->maxY;