beee82d43659b3f682f57301c4a64feec96314ff braney Thu Feb 1 14:25:25 2018 -0800 add support for math on bedGraph (including custom tracks) diff --git src/hg/lib/mathWig.c src/hg/lib/mathWig.c index 23f0473..3d1ab26 100644 --- src/hg/lib/mathWig.c +++ src/hg/lib/mathWig.c @@ -75,51 +75,82 @@ x2 = width ; if (x1 < width) { for (; x1 < x2; ++x1) { if ((x1 >= 0)) { array[x1] = BIN_TO_VALUE(datum,wi->lowerLimit,wi->dataRange); } } } } } } +void getBedGraphData(char *db, char *table, char *chrom, unsigned winStart, unsigned winEnd, double *array) +/* Query a bedGraph table and fill in the values in the array. */ +{ +struct sqlConnection *conn = hAllocConn(db); +int rowOffset; +struct sqlResult *sr; +char **row; +unsigned width = winEnd - winStart; + +sr = hRangeQuery(conn, table, chrom, winStart, winEnd, + NULL, &rowOffset); +while ((row = sqlNextRow(sr)) != NULL) + { + unsigned chromStart = sqlUnsigned(row[rowOffset + 1]); + unsigned chromEnd = sqlUnsigned(row[rowOffset + 2]); + unsigned start = max(0, chromStart - winStart); + unsigned end = min(width, chromEnd - winStart); + int ii; + + for (ii = start; ii < end; ii++) + array[ii] = sqlFloat(row[rowOffset + 3]); + } + +} + void getWigData(char *db, char *table, char *chrom, unsigned winStart, unsigned winEnd, double *array) -/* Query the database to find the regions in the WIB file we need to read to get data for a specified range. */ +/* Query the database to find the regions in the WIB file we need to read to get data for a specified range. Only use the smallest of spans. */ { struct sqlConnection *conn = hAllocConn(db); int rowOffset; struct sqlResult *sr; char **row; -struct wiggle wiggle; -int span = 0; +struct wiggle *wiggleList = NULL, *wiggle; +int minSpan = 1000000000; sr = hRangeQuery(conn, table, chrom, winStart, winEnd, NULL, &rowOffset); while ((row = sqlNextRow(sr)) != NULL) { - wiggleStaticLoad(row + rowOffset, &wiggle); - getWigDataFromFile(&wiggle, array, winStart, winEnd); - if (span == 0) - span = wiggle.span; - else - if (span != wiggle.span) - errAbort("multiple spans in wiggle table"); + wiggle = wiggleLoad(row + rowOffset); + slAddHead(&wiggleList, wiggle); + if (wiggle->span < minSpan) + minSpan = wiggle->span; + } + +struct wiggle *nextWiggle; +for(wiggle = wiggleList; wiggle; wiggle = nextWiggle) + { + nextWiggle = wiggle->next; + if (wiggle->span == minSpan) + getWigDataFromFile(wiggle, array, winStart, winEnd); + freez(&wiggle); } } void getBigWigData(char *file, char *chrom, unsigned winStart, unsigned winEnd, double *array) /* Query a bigBed file to find the wiggle values we need for a specified range. */ { struct lm *lm = lmInit(0); struct bbiFile *bwf = bigWigFileOpen(file); struct bbiInterval *iv, *ivList = bigWigIntervalQuery(bwf, chrom, winStart, winEnd, lm); unsigned width = winEnd - winStart; for (iv = ivList; iv != NULL; iv = iv->next) { unsigned start = max(0, iv->start - winStart); unsigned end = min(width, iv->end - winStart); @@ -149,32 +180,48 @@ { double *dataLoad = operand; if (firstTime) dataLoad = accumulator; if (pushOpcode(&opcodeStack, words[jj])) continue; if (missingIsZero) for(ii=0; ii < width; ii++) dataLoad[ii] = 0; else for(ii=0; ii < width; ii++) dataLoad[ii] = NAN; - if (startsWith("$", words[jj])) // ignore native tracks for the moment - getWigData(db, &words[jj][1], chrom, winStart, winEnd, dataLoad); + boolean isWiggle = FALSE; + boolean isBedGraph = FALSE; + if (startsWith("$", words[jj])) + isWiggle = TRUE; + else if (startsWith("^", words[jj])) + isBedGraph = TRUE; + + if (isBedGraph || isWiggle) + { + char *useDb = &words[jj][1]; + char *dot = strchr( &words[jj][1], '.'); + *dot = 0; + char *useTable = dot + 1; + if (isWiggle) + getWigData(useDb, useTable, chrom, winStart, winEnd, dataLoad); + else + getBedGraphData(useDb, useTable, chrom, winStart, winEnd, dataLoad); + } else getBigWigData(words[jj], chrom, winStart, winEnd, dataLoad); if (firstTime) { firstTime = FALSE; continue; } char opcode; if (opcodeStack.depth == 0) { opcode = lastOpcode; if (opcode == 0) opcode = '+';