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;
+}