src/hg/hgTracks/wigTrack.c 1.95
1.95 2009/11/17 20:47:50 kent
Adding whisker plots.
Index: src/hg/hgTracks/wigTrack.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/hgTracks/wigTrack.c,v
retrieving revision 1.94
retrieving revision 1.95
diff -b -B -U 4 -r1.94 -r1.95
--- src/hg/hgTracks/wigTrack.c 6 Nov 2009 22:27:12 -0000 1.94
+++ src/hg/hgTracks/wigTrack.c 17 Nov 2009 20:47:50 -0000 1.95
@@ -9,8 +9,9 @@
#include "jksql.h"
#include "hdb.h"
#include "hgTracks.h"
#include "wiggle.h"
+#include "hmmstats.h"
#include "scoredRef.h"
#ifndef GBROWSE
#include "customTrack.h"
#endif /* GBROWSE */
@@ -586,8 +587,9 @@
else
dataValue = preDraw[i].max;
break;
case (wiggleWindowingMean):
+ case (wiggleWindowWhiskers):
dataValue =
preDraw[i].sumData / preDraw[i].count;
break;
default:
@@ -730,12 +732,14 @@
*epsilon = graphRange / lineHeight;
return(graphRange);
}
-Color * allocColorArray(struct preDrawElement *preDraw, int width,
- int preDrawZero, char *colorTrack, struct track *tg, struct hvGfx *hvg)
+static Color * makeColorArray(struct preDrawElement *preDraw, int width,
+ int preDrawZero, struct wigCartOptions *wigCart, struct track *tg, struct hvGfx *hvg)
/* allocate and fill in a coloring array based on another track */
{
+char *colorTrack = wigCart->colorTrack;
+boolean whiskers = (wigCart->windowingFunction == wiggleWindowWhiskers);
int x1;
Color *colorArray = NULL; /* Array of pixels to be drawn. */
/* Set up the color by array. Determine color of each pixel
@@ -751,14 +755,21 @@
double dataValue; /* the data value in data space */
dataValue = preDraw[preDrawIndex].smooth;
/* negative data is the alternate color */
+ if (whiskers)
+ {
+ colorArray[x1] = tg->ixColor;
+ }
+ else
+ {
if (dataValue < 0.0)
colorArray[x1] = tg->ixAltColor;
else
colorArray[x1] = tg->ixColor;
}
}
+ }
/* Fill in colors from alternate track if necessary. */
if(colorTrack != NULL)
{
@@ -769,38 +780,45 @@
return colorArray;
}
+double uglyFoo;
+
void graphPreDraw(struct preDrawElement *preDraw, int preDrawZero, int width,
struct track *tg, struct hvGfx *hvg, int xOff, int yOff,
double graphUpperLimit, double graphLowerLimit, double graphRange,
double epsilon, Color *colorArray, enum trackVisibility vis,
- enum wiggleGraphOptEnum lineBar)
+ struct wigCartOptions *wigCart)
/* graph the preDraw array */
{
int x1;
-int lastRealX = -1;
-int lastRealY = -1;
+int h = tg->lineHeight; /* the height of our drawing window */
+double scaleFactor = h/graphRange;
+Color mediumColor = shadesOfGray[grayInRange(30, 0, 100)];
+Color lightColor = shadesOfGray[grayInRange(15, 0, 100)];
+Color clipColor = MG_MAGENTA;
+enum wiggleGraphOptEnum lineBar = wigCart->lineBar;
+boolean whiskers = (wigCart->windowingFunction == wiggleWindowWhiskers);
+
+/* Return gray shade corresponding to a number from 50 - 100 */
/* right now this is a simple pixel by pixel loop. Future
* enhancements could draw boxes where pixels
* are all the same height in a run.
*/
for (x1 = 0; x1 < width; ++x1)
{
- Color drawColor = hvGfxFindColorIx(hvg, 0, 0, 0);
+ Color drawColor = colorArray[x1];
int preDrawIndex = x1 + preDrawZero;
+ struct preDrawElement *p = &preDraw[preDrawIndex];
/* count is non-zero meaning valid data exists here */
- if (preDraw[preDrawIndex].count)
+ if (p->count)
{
- int h = tg->lineHeight; /* the height of our drawing window */
- int boxHeight; /* the size of our box to draw */
- int boxTop; /* box top starts here */
- int y1; /* y coordinate of data point */
- int y0; /* y coordinate of data = 0.0 */
- int yPointGraph; /* y coordinate of data for point style */
- double dataValue; /* the data value in data space */
+ /* data value has been picked by previous scanning.
+ * Could be smoothed, maybe not.
+ */
+ double dataValue = p->smooth;
/* The graphing coordinate conversion situation is:
* graph coordinate y = 0 is graphUpperLimit data space
* and total graph height is h which is graphRange in data space
@@ -816,72 +834,100 @@
* are below the lower graphing limit. This is OK, the
* clipping will be taken care of by the vgBox() function.
*/
- /* data value has been picked by previous scanning.
- * Could be smoothed, maybe not.
- */
- dataValue = preDraw[preDrawIndex].smooth;
+ if (vis == tvFull || vis == tvPack)
+ {
+#define scaleHeightToPixels(val) (scaleFactor * (graphUpperLimit - (val)) + yOff)
+ if (lineBar == wiggleGraphBar)
+ {
+ if (whiskers)
+ {
+ int zeroPos = scaleHeightToPixels(0);
+ int scaledVal = scaleHeightToPixels(dataValue);
+ double std = calcStdFromSums(p->sumData, p->sumSquares, p->count);
+ if (dataValue < 0)
+ {
+ int scaledMin = scaleHeightToPixels(p->min);
+ hvGfxBox(hvg, x1+xOff, zeroPos, 1, scaledMin-zeroPos, lightColor);
+ if (!isnan(std)) // Test needed because of bug in version 1.5 bigWiles
+ {
+ int scaledMinus = scaleHeightToPixels(dataValue-std);
+ hvGfxBox(hvg, x1+xOff, zeroPos, 1, scaledMinus-zeroPos, mediumColor);
+ }
+ int boxHeight = scaledVal - zeroPos;
+ if (boxHeight < 1) boxHeight = 1;
+ hvGfxBox(hvg, x1+xOff, zeroPos, 1, boxHeight, drawColor);
+#ifdef SOON
+#endif /* SOON */
+ }
+ else
+ {
+ int scaledMax = scaleHeightToPixels(p->max);
+ hvGfxBox(hvg, x1+xOff, scaledMax, 1, zeroPos-scaledMax, lightColor);
+ if (!isnan(std)) // Test needed because of bug in version 1.5 bigWiles
+ {
+ int scaledPlus = scaleHeightToPixels(dataValue+std);
+ hvGfxBox(hvg, x1+xOff, scaledPlus, 1, zeroPos-scaledPlus, mediumColor);
+ }
+ int boxHeight = zeroPos - scaledVal;
+ if (boxHeight < 1) boxHeight = 1;
+ hvGfxBox(hvg, x1+xOff, scaledVal, 1, boxHeight, drawColor);
+ }
+ }
+ else
+ {
+ int y0 = graphUpperLimit * scaleFactor;
+ int y1 = (graphUpperLimit - dataValue)*scaleFactor;
- y1 = h * ((graphUpperLimit - dataValue)/graphRange);
- yPointGraph = yOff + y1 - 1;
- y0 = h * ((graphUpperLimit)/graphRange);
- boxHeight = abs(y1 - y0);
- boxTop = min(y1,y0);
+ int boxHeight = abs(y1 - y0);
+ int boxTop = min(y1,y0);
/* special case where dataValue is on the zero line, it
* needs to have a boxHeight of 1, otherwise it disappears into
* zero nothingness
*/
- if (fabs(dataValue) < epsilon)
- {
+ if (boxHeight < 1)
boxHeight = 1;
- }
+
/* Last pixel (bottom) is a special case of a closed interval */
- if ((boxTop == h) && (boxHeight == 0))
+ if ((boxTop == h) && (boxHeight == 1))
{
boxTop = h - 1;
boxHeight = 1;
}
- /* Special case data value on upper limit line */
- if ((boxTop+boxHeight) == 0)
- boxHeight += 1;
- /* Special case data value is below the lower view limit,
- * should still show a 1 pixel wide line at the bottom */
- if ((graphLowerLimit >= 0.0) && (dataValue < graphLowerLimit))
- {
- boxTop = h - 1;
- boxHeight = 1;
- }
- /* Special case data value is above the upper view limit,
- * should still show a 1 pixel wide line at the top */
- if ((graphUpperLimit <= 0.0) && (dataValue > graphUpperLimit))
- {
- boxTop = 0;
- boxHeight = 1;
- }
-
- drawColor = colorArray[x1];
-/* /\* negative data is the alternate color *\/ */
-/* if (dataValue < 0.0) */
-/* drawColor = tg->ixAltColor; */
-/* else */
-/* drawColor = tg->ixColor; */
-
- /* vgBox will take care of clipping. No need to worry
- * about coordinates or height of line to draw.
- * We are actually drawing single pixel wide lines here.
- */
- if (vis == tvFull || vis == tvPack)
- {
- if (lineBar == wiggleGraphBar)
- {
hvGfxBox(hvg, x1+xOff, yOff+boxTop, 1, boxHeight, drawColor);
}
+ }
else
{ /* draw a 3 pixel height box */
+ if (whiskers)
+ {
+ int scaledMin = scaleHeightToPixels(p->min);
+ int scaledMax = scaleHeightToPixels(p->max);
+ hvGfxBox(hvg, x1+xOff, scaledMax, 1, scaledMin - scaledMax, lightColor);
+ int scaledMean = scaleHeightToPixels(dataValue);
+ double std = calcStdFromSums(p->sumData, p->sumSquares, p->count);
+ if (!isnan(std)) // Test needed because of bug in version 1.5 bigWiles
+ {
+ int scaledMeanPlus = scaleHeightToPixels(dataValue+std);
+ int scaledMeanMinus = scaleHeightToPixels(dataValue-std);
+ hvGfxBox(hvg, x1+xOff, scaledMeanPlus, 1,
+ scaledMeanMinus - scaledMeanPlus, mediumColor);
+ }
+ hvGfxBox(hvg, x1+xOff, scaledMean, 1, 1, drawColor);
+ }
+ else
+ {
+ int yPointGraph = scaleHeightToPixels(dataValue) - 1;
hvGfxBox(hvg, x1+xOff, yPointGraph, 1, 3, drawColor);
}
+ }
+ if (dataValue > graphUpperLimit)
+ hvGfxBox(hvg, x1+xOff, yOff, 1, 2, clipColor);
+ else if (dataValue < graphLowerLimit)
+ hvGfxBox(hvg, x1+xOff, yOff + h - 1, 1, 2, clipColor);
+#undef scaleHeightToPixels /* No longer use this symbol */
} /* vis == tvFull || vis == tvPack */
else if (vis == tvDense || vis == tvSquish)
{
double grayValue;
@@ -892,15 +938,11 @@
grayIndex = ((grayValue-graphLowerLimit)/graphRange)*MAX_WIG_VALUE;
drawColor =
tg->colorShades[grayInRange(grayIndex, 0, MAX_WIG_VALUE)];
-
- boxHeight = tg->lineHeight;
hvGfxBox(hvg, x1+xOff, yOff, 1,
- boxHeight, drawColor);
+ tg->lineHeight, drawColor);
} /* vis == tvDense || vis == tvSquish */
- lastRealX = xOff + x1;
- lastRealY = yOff + y1;
} /* if (preDraw[].count) */
} /* for (x1 = 0; x1 < width; ++x1) */
} /* graphPreDraw() */
@@ -1064,14 +1106,14 @@
&overallRange, &epsilon, tg->lineHeight,
wigCart->maxY, wigCart->minY, wigCart->alwaysZero);
-colorArray = allocColorArray(preDraw, width, preDrawZero,
- wigCart->colorTrack, tg, hvg);
+colorArray = makeColorArray(preDraw, width, preDrawZero,
+ wigCart, tg, hvg);
graphPreDraw(preDraw, preDrawZero, width,
tg, hvg, xOff, yOff, graphUpperLimit, graphLowerLimit, graphRange,
- epsilon, colorArray, vis, wigCart->lineBar);
+ epsilon, colorArray, vis, wigCart);
drawZeroLine(vis, wigCart->horizontalGrid,
graphUpperLimit, graphLowerLimit,
hvg, xOff, yOff, width, tg->lineHeight);