ed9b395fe7bf7d31563df571c790a182b6a69731
angie
  Wed Jul 8 10:44:51 2015 -0700
When averaging wig values, skip over NAN values so that they don't
cause the sum and average to be NAN.  If all values in range are NAN,
just return NULL words so that nothing is output -- there are no valid
overlapping values.
refs #15675

diff --git src/lib/annoFormatTab.c src/lib/annoFormatTab.c
index d80f3a3..8971be0 100644
--- src/lib/annoFormatTab.c
+++ src/lib/annoFormatTab.c
@@ -107,56 +107,68 @@
 	fprintf(self->f, "# Header from primary input:\n%s", primaryHeader);
     printHeaderColumns(self, primary, TRUE);
     struct annoStreamer *grator;
     for (grator = integrators;  grator != NULL;  grator = grator->next)
 	printHeaderColumns(self, grator, FALSE);
     fputc('\n', self->f);
     self->needHeader = FALSE;
     }
 }
 
 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;
+int count = 0;
 double sum = 0.0;
 int i;
 for (i = 0;  i < len;  i++)
+    {
+    // skip NAN values so they don't convert sum to a NAN:
+    if (! isnan(vector[i]))
+        {
         sum += vector[i];
-return sum / (double)len;
+        count++;
+        }
+    }
+// I expected "double avg = sum / (double)count" to yield NAN if count is 0 --
+// but avg was negative NAN!  Avoid the fp exception and weird value by testing count:
+return (count > 0) ? sum / (double)count : NAN;
 }
 
 static char **bed4WordsFromAnnoRow(struct annoRow *row, char *fourth)
 /* Return an array of 4 words with row's chrom, chromStart, and chromEnd, and cloned fourth. */
 {
 char **words;
 AllocArray(words, 4);
 words[0] = cloneString(row->chrom);
 char buf[PATH_LEN];
 safef(buf, sizeof(buf), "%u", row->start);
 words[1] = cloneString(buf);
 safef(buf, sizeof(buf), "%u", row->end);
 words[2] = cloneString(buf);
 words[3] = cloneString(fourth);
 return words;
 }
 
 static char **wordsFromWigRowAvg(struct annoRow *row)
 /* Return chrom, chromStart, chromEnd and a string containing the average of values in row. */
 {
 double avg = wigRowAvg(row);
+if (isnan(avg))
+    return NULL;
 char avgStr[32];
 safef(avgStr, sizeof(avgStr), "%lf", avg);
 return bed4WordsFromAnnoRow(row, avgStr);
 }
 
 static char **wordsFromWigRowVals(struct annoRow *row)
 /* Return chrom, chromStart, chromEnd and a 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, "%g,", vector[i]);
 char **words = bed4WordsFromAnnoRow(row, dy->string);
@@ -164,35 +176,36 @@
 return words;
 }
 
 static char **wordsFromRow(struct annoRow *row, struct annoStreamer *source,
 			   boolean *retFreeWhenDone)
 /* If source->rowType is arWords, return its words.  Otherwise translate row->data into words. */
 {
 if (row == NULL)
     return NULL;
 boolean freeWhenDone = FALSE;
 char **words = NULL;
 if (source->rowType == arWords)
     words = row->data;
 else if (source->rowType == arWig)
     {
-    freeWhenDone = TRUE;
     if (doAvg)
 	words = wordsFromWigRowAvg(row);
     else
 	words = wordsFromWigRowVals(row);
+    if (words != NULL)
+        freeWhenDone = TRUE;
     }
 else
     errAbort("annoFormatTab: unrecognized row type %d from source %s",
 	     source->rowType, source->name);
 if (retFreeWhenDone != NULL)
     *retFreeWhenDone = freeWhenDone;
 return words;
 }
 
 static void printColumns(struct annoFormatTab *self, struct annoStreamer *streamer,
 			 struct annoRow *row, boolean isFirst)
 /* Print columns in streamer's row (if NULL, print the right number of empty fields). */
 {
 FILE *f = self->f;
 char *sourceName = streamer->name;