33990deeb6214328424d9acf9bfaf667ae8f3f4f
angie
  Wed Mar 28 15:34:14 2012 -0700
Feature #6152 (Variant Annotation Tool): Added annoStreamWig and annoGrateWig,which led to some significant changes: annoRow is now polymorphic (words[]
vs. wig float[]), annoFilter has a new function to apply filter(s) to a single
number, and annoFormatTab can print out per-base wiggle values or average
wiggle values (hardcoded to do per-base until a real config option is added).
One puny test case was verified against mysql & table browser output.

diff --git src/lib/annoFormatTab.c src/lib/annoFormatTab.c
index 9835d54..5ab4fa1 100644
--- src/lib/annoFormatTab.c
+++ src/lib/annoFormatTab.c
@@ -70,58 +70,136 @@
 /* Print columns in streamer's row (if NULL, print the right number of empty fields). */
 {
 struct annoColumn *col;
 int i;
 for (col = streamer->columns, i = 0;  col != NULL;  col = col->next, i++)
     {
     if (! col->included)
 	continue;
     if (!isFirst || i > 0)
 	fputc('\t', f);
     if (row != NULL)
 	fputs(row[i], f);
     }
 }
 
+static double wigRowAvg(struct annoRow *row)
+/* Return the average value of floats in row->data. */
+{
+float *vector = row->data;
+int len = row->end - row->start;
+double sum = 0.0;
+int i;
+for (i = 0;  i < len;  i++)
+    sum += vector[i];
+return sum / (double)len;
+}
+
+static char **wordsFromWigRowAvg(struct annoRow *row)
+/* Return an array of strings with a single string containing the average of values in row. */
+{
+double avg = wigRowAvg(row);
+char **words;
+AllocArray(words, 1);
+char avgStr[32];
+safef(avgStr, sizeof(avgStr), "%lf", avg);
+words[0] = cloneString(avgStr);
+return words;
+}
+
+static char **wordsFromWigRowVals(struct annoRow *row)
+/* Return an array of strings with a single string containing comma-sep per-base wiggle values. */
+{
+float *vector = row->data;
+int len = row->end - row->start;
+struct dyString *dy = dyStringNew(10*len);
+int i;
+for (i = 0;  i < len;  i++)
+    dyStringPrintf(dy, "%f,", vector[i]);
+char **words;
+AllocArray(words, 1);
+words[0] = dyStringCannibalize(&dy);
+return words;
+}
+
+static char **wordsFromRow(struct annoRow *row, boolean *retFreeWhenDone)
+/* If row->type is arWords, return its words.  Otherwise translate row->data into words. */
+{
+if (row == NULL)
+    return NULL;
+boolean freeWhenDone = FALSE;
+char **words = NULL;
+if (row->type == arWords)
+    words = row->data;
+else if (row->type == arWig)
+    {
+    freeWhenDone = TRUE;
+    //#*** config options: avg? more stats? list of values?
+    boolean doAvg = FALSE;
+    if (doAvg)
+	words = wordsFromWigRowAvg(row);
+    else
+	words = wordsFromWigRowVals(row);
+    }
+else
+    errAbort("annoFormatTab: unrecognized row type %d", row->type);
+if (retFreeWhenDone != NULL)
+    *retFreeWhenDone = freeWhenDone;
+return words;
+}
+
+INLINE void freeWords1(char **words)
+/* Free words and words[0] (alloc'd by wordsFromWig* above. */
+{
+freeMem(words[0]);
+freeMem(words);
+}
+
 static void aftFormatOne(struct annoFormatter *vSelf)
 /* Print out tab-separated columns that we have gathered in prior calls to aftCollect,
  * and start over fresh for the next line of output. */
 {
 struct annoFormatTab *self = (struct annoFormatTab *)vSelf;
 slReverse(&(self->gratorRowLists));
 // How many rows did each grator give us, and what's the largest # of rows?
 int maxRows = 1;
 int i;
 struct slRef *grRef;
 int numGrators = slCount(self->gratorRowLists);
 for (i = 0, grRef = self->gratorRowLists;  i < numGrators;  i++, grRef = grRef->next)
     {
     int gratorRowCount = slCount(grRef->val);
     if (gratorRowCount > maxRows)
 	maxRows = gratorRowCount;
     }
 // Print out enough rows to make sure that all grator rows are included.
 for (i = 0;  i < maxRows;  i++)
     {
-    printColumns(self->f, vSelf->query->primarySource, self->primaryRow->words, TRUE);
+    boolean freeWhenDone = FALSE;
+    char **primaryData = wordsFromRow(self->primaryRow, &freeWhenDone);
+    printColumns(self->f, vSelf->query->primarySource, primaryData, TRUE);
+    if (freeWhenDone)
+	freeWords1(primaryData);
     struct annoStreamer *grator = (struct annoStreamer *)self->formatter.query->integrators;
     for (grRef = self->gratorRowLists;  grRef != NULL;  grRef = grRef->next,
 	     grator = grator->next)
 	{
 	struct annoRow *gratorRow = slElementFromIx(grRef->val, i);
-	char **row = (gratorRow == NULL) ? NULL : gratorRow->words;
-	printColumns(self->f, grator, row, FALSE);
+	char **gratorWords = wordsFromRow(gratorRow, &freeWhenDone);
+	printColumns(self->f, grator, gratorWords, FALSE);
+	if (freeWhenDone)
+	    freeWords1(gratorWords);
 	}
     fputc('\n', self->f);
     }
 self->primaryRow = NULL;
 slFreeList(&(self->gratorRowLists));
 }
 
 static void aftClose(struct annoFormatter **pVSelf)
 /* Close file handle, free self. */
 {
 if (pVSelf == NULL)
     return;
 struct annoFormatTab *self = *(struct annoFormatTab **)pVSelf;
 freeMem(self->fileName);
 carefulClose(&(self->f));