src/hg/hgTracks/bedGraph.c 1.22
1.22 2010/04/27 23:31:41 braney
first pass at multiWiggle. This shouldn't change existing behavior. Add extTable to your bigWig trackDb to get two tables into one bigWig wiggle track.
Index: src/hg/hgTracks/bedGraph.c
===================================================================
RCS file: /projects/compbio/cvsroot/kent/src/hg/hgTracks/bedGraph.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -b -B -U 1000000 -r1.21 -r1.22
--- src/hg/hgTracks/bedGraph.c 25 Mar 2010 17:46:01 -0000 1.21
+++ src/hg/hgTracks/bedGraph.c 27 Apr 2010 23:31:41 -0000 1.22
@@ -1,271 +1,275 @@
/* bedGraph - stuff to handle loading and display of
* bedGraph type tracks in browser. Will be graphing a specified
* column of a bed file.
*/
#include "common.h"
#include "hash.h"
#include "linefile.h"
#include "jksql.h"
#include "hdb.h"
#include "hgTracks.h"
#include "wiggle.h"
#include "scoredRef.h"
#include "customTrack.h"
#include "wigCommon.h"
static char const rcsid[] = "$Id$";
/* The item names have been massaged during the Load. An
* individual item may have been read in on multiple table rows and
* had an extension on it to make it unique from the others. Also,
* each different zoom level had a different extension name.
* All these names were condensed into the root of the name with
* the extensions removed.
*/
static char *bedGraphName(struct track *tg, void *item)
/* Return name of bedGraph level track. */
{
struct bedGraphItem *bg = item;
return bg->name;
}
void ctBedGraphLoadItems(struct track *tg)
{
/* load custom bedGraph track data */
/* Verify this is a custom track */
if (tg->customPt == (void *)NULL)
errAbort("ctBedGraphLoadItems: did not find a custom wiggle track: %s", tg->mapName);
errAbort("custom track bedGraph load items not yet implemented");
}
/* bedGraphLoadItems - an ordinary bed load, but we are interested
* in only the chrom, start, end, and the graphColumn
*/
static void bedGraphLoadItems(struct track *tg)
{
struct sqlConnection *conn;
struct sqlResult *sr = (struct sqlResult *) NULL;
char **row = (char **)NULL;
int rowOffset = 0;
struct bedGraphItem *bgList = NULL;
int itemsLoaded = 0;
int colCount = 0;
struct wigCartOptions *wigCart = (struct wigCartOptions *) tg->extraUiData;
int graphColumn = 5;
char *tableName;
if(sameString(tg->mapName, "affyTranscription"))
wigCart->colorTrack = "affyTransfrags";
graphColumn = wigCart->graphColumn;
#ifndef GBROWSE
if (tg->customPt)
{
struct customTrack *ct = (struct customTrack *) tg->customPt;
tableName = ct->dbTableName;
conn = hAllocConn(CUSTOM_TRASH);
}
else
#endif /* GBROWSE */
{
tableName = tg->mapName;
conn = hAllocConnTrack(database, tg->tdb);
}
sr = hRangeQuery(conn, tableName, chromName, winStart, winEnd, NULL,
&rowOffset);
colCount = sqlCountColumns(sr) - rowOffset;
/* Must have at least four good columns */
if (colCount < 4)
errAbort("bedGraphLoadItems: table %s only has %d data columns, must be at least 4", tableName, colCount);
if (colCount < graphColumn)
errAbort("bedGraphLoadItems: table %s only has %d data columns, specified graph column %d does not exist",
tableName, colCount, graphColumn);
/* before loop, determine actual row[graphColumn] index */
graphColumn += (rowOffset - 1);
while ((row = sqlNextRow(sr)) != NULL)
{
struct bedGraphItem *bg;
struct bed *bed;
++itemsLoaded;
/* load chrom, start, end */
bed = bedLoadN(row+rowOffset, 3);
AllocVar(bg);
bg->start = bed->chromStart;
bg->end = bed->chromEnd;
if ((colCount > 4) && ((graphColumn + rowOffset) != 4))
bg->name = cloneString(row[3+rowOffset]);
else
{
char name[128];
safef(name,ArraySize(name),"%s.%d", bed->chrom, itemsLoaded);
bg->name = cloneString(name);
}
bg->dataValue = sqlFloat(row[graphColumn]);
/* filled in by DrawItems */
bg->graphUpperLimit = wigEncodeStartingUpperLimit;
bg->graphLowerLimit = wigEncodeStartingLowerLimit;
slAddHead(&bgList, bg);
bedFree(&bed);
}
sqlFreeResult(&sr);
hFreeConn(&conn);
slReverse(&bgList);
tg->items = bgList;
} /* bedGraphLoadItems() */
static void bedGraphFreeItems(struct track *tg) {
#if defined(DEBUG)
snprintf(dbgMsg, DBGMSGSZ, "I haven't seen bedGraphFreeItems ever called ?");
wigDebugPrint("bedGraphFreeItems");
#endif
}
static void bedGraphDrawItems(struct track *tg, int seqStart, int seqEnd,
struct hvGfx *hvg, int xOff, int yOff, int width,
MgFont *font, Color color, enum trackVisibility vis)
{
struct bedGraphItem *wi;
double pixelsPerBase = scaleForPixels(width);
double basesPerPixel = 1.0;
int i; /* an integer loop counter */
if (pixelsPerBase > 0.0)
basesPerPixel = 1.0 / pixelsPerBase;
/* walk through all the data and prepare the preDraw array */
int preDrawZero, preDrawSize;
struct preDrawElement *preDraw = initPreDraw(width, &preDrawSize, &preDrawZero);
for (wi = tg->items; wi != NULL; wi = wi->next)
{
double dataValue = wi->dataValue; /* the data value to graph */
/* Ready to draw, what do we know:
* the feature being processed:
* chrom coords: [wi->start : wi->end)
* its data value: dataValue = wi->dataValue
*
* The drawing window, in pixels:
* xOff = left margin, yOff = top margin, h = height of drawing window
* drawing window in chrom coords: seqStart, seqEnd
* 'basesPerPixel' is known, 'pixelsPerBase' is known
*/
/* let's check end point screen coordinates. If they are
* the same, then this entire data block lands on one pixel,
* It is OK if these end up + or -, we do want to
* keep track of pixels before and after the screen for
* later smoothing operations
*/
int x1 = (wi->start - seqStart) * pixelsPerBase;
int x2 = (wi->end - seqStart) * pixelsPerBase;
if (x2 > x1)
{
for (i = x1; i <= x2; ++i)
{
int xCoord = preDrawZero + i;
if ((xCoord >= 0) && (xCoord < preDrawSize))
{
++preDraw[xCoord].count;
if (dataValue > preDraw[xCoord].max)
preDraw[xCoord].max = dataValue;
if (dataValue < preDraw[xCoord].min)
preDraw[xCoord].min = dataValue;
preDraw[xCoord].sumData += dataValue;
preDraw[xCoord].sumSquares += dataValue * dataValue;
}
}
}
else
{ /* only one pixel for this block of data */
int xCoord = preDrawZero + x1;
/* if the point falls within our array, record it.
* the (wi->validCount > 0) is a safety check. It
* should always be true unless the data was
* prepared incorrectly.
*/
if ((xCoord >= 0) && (xCoord < preDrawSize))
{
++preDraw[xCoord].count;
if (dataValue > preDraw[xCoord].max)
preDraw[xCoord].max = dataValue;
if (dataValue < preDraw[xCoord].min)
preDraw[xCoord].min = dataValue;
preDraw[xCoord].sumData += dataValue;
preDraw[xCoord].sumSquares += dataValue * dataValue;
}
}
} /* for (wi = tg->items; wi != NULL; wi = wi->next) */
/* 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;
wigDrawPredraw(tg, seqStart, seqEnd, hvg, xOff, yOff, width, font, color, vis,
- preDraw, preDrawZero, preDrawSize, &tg->graphUpperLimit, &tg->graphLowerLimit);
+ preDrawContainer, preDrawZero, preDrawSize, &tg->graphUpperLimit, &tg->graphLowerLimit);
+freeMem(preDrawContainer);
freeMem(preDraw);
} /* bedGraphDrawItems() */
/*
* 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 bedGraphMethods(struct track *track, struct trackDb *tdb,
int wordCount, char *words[])
{
struct wigCartOptions *wigCart = wigCartOptionsNew(cart, tdb, wordCount, words);
wigCart->bedGraph = TRUE; /* signal to left labels */
switch (wordCount)
{
case 2:
wigCart->graphColumn = atoi(words[1]);
/* protect against nonsense values */
if ( (wigCart->graphColumn < 2) ||
(wigCart->graphColumn > 100) )
wigCart->graphColumn = 5; /* default score column */
break;
default:
wigCart->graphColumn = 5; /* default score column */
break;
}
track->minRange = wigCart->minY;
track->maxRange = wigCart->maxY;
track->graphUpperLimit = wigEncodeStartingUpperLimit;
track->graphLowerLimit = wigEncodeStartingLowerLimit;
track->loadItems = bedGraphLoadItems;
track->freeItems = bedGraphFreeItems;
track->drawItems = bedGraphDrawItems;
track->itemName = bedGraphName;
track->mapItemName = bedGraphName;
track->totalHeight = wigTotalHeight;
track->itemHeight = tgFixedItemHeight;
track->itemStart = tgItemNoStart;
track->itemEnd = tgItemNoEnd;
track->mapsSelf = TRUE;
track->extraUiData = (void *) wigCart;
track->colorShades = shadesOfGray;
track->drawLeftLabels = wigLeftLabels;
/* the lfSubSample type makes the image map function correctly */
track->subType = lfSubSample; /*make subType be "sample" (=2)*/
} /* bedGraphMethods() */