677b513b231891e30d32024de7ded7766ef72058 braney Wed May 24 14:09:42 2017 -0700 add mathWig track type which is an arithmetic combination of bigWi. diff --git src/hg/lib/mathWig.c src/hg/lib/mathWig.c new file mode 100644 index 0000000..18e3bd1 --- /dev/null +++ src/hg/lib/mathWig.c @@ -0,0 +1,111 @@ +/* Copyright (C) 2017 The Regents of the University of California + * See README in this or parent directory for licensing information. */ + +#include "common.h" +#include "bigWig.h" + +// stack of arithmetic operators +struct opcodeStack + { + int depth; + int maxDepth; + char *stack; + }; + +static boolean pushOpcode(struct opcodeStack *opcodeStack, char *word) +/* Check to see if word is operator, if so, push it onto the stack */ +{ +boolean ret = FALSE; + +if (strlen(word) > 1) + return FALSE; + +switch(*word) + { + case '+': + case '*': + case '-': + case '/': + if (opcodeStack->depth == opcodeStack->maxDepth) + { + opcodeStack->maxDepth += 10; + opcodeStack->stack = realloc(opcodeStack->stack, opcodeStack->maxDepth); + } + opcodeStack->stack[opcodeStack->depth] = *word; + opcodeStack->depth++; + ret = TRUE; + break; + } + +return ret; +} + +double *mathWigGetValues(char *equation, char *chrom, unsigned winStart, unsigned winEnd) +/* Build an array of doubles that is calculated from bigWig's listed + * in equation in the requested region. */ +{ +char *words[100]; +int count = chopByWhite(equation, words, sizeof(words)/sizeof(char *)); +int jj,ii; +unsigned width = winEnd - winStart; +struct lm *lm = lmInit(0); +double *data = needHugeMem(width * sizeof(double)); +bzero(data, width * sizeof(double)); +struct opcodeStack opcodeStack; +bzero(&opcodeStack, sizeof opcodeStack); + +boolean firstTime = TRUE; +for (jj=0; jj < count; jj++) + { + if (pushOpcode(&opcodeStack, words[jj])) + continue; + struct bbiFile *bwf = bigWigFileOpen(words[jj]); + + struct bbiInterval *iv, *ivList = bigWigIntervalQuery(bwf, chrom, winStart, winEnd, lm); + + if (firstTime) + { + for (iv = ivList; iv != NULL; iv = iv->next) + { + unsigned start = max(0, iv->start - winStart); + unsigned end = min(width, iv->end - winStart); + + for (ii = start; ii < end; ii++) + data[ii] = iv->val; + } + + firstTime = FALSE; + } + else + { + if (opcodeStack.depth == 0) + errAbort("underflow in opcode stack"); + char opcode = opcodeStack.stack[--opcodeStack.depth]; + for (iv = ivList; iv != NULL; iv = iv->next) + { + unsigned start = max(0, iv->start - winStart); + unsigned end = min(width, iv->end - winStart); + for (ii = start; ii < end; ii++) + { + switch(opcode) + { + case '+': + data[ii] += iv->val; + break; + case '-': + data[ii] -= iv->val; + break; + case '*': + data[ii] *= iv->val; + break; + case '/': + data[ii] /= iv->val; + break; + } + } + } + } + } + +return data; +}