fc13db4566f67eda0bb8d608c8cd691b559a1930 angie Fri May 22 16:32:00 2015 -0700 Add chrom, chromStart, chromEnd back into the autoSql for wig and bigWig annoStreamers. Now the columns can be selected/deselected the usual way instead of being fudged into the output with no choice. refs #14579 diff --git src/lib/annoFormatTab.c src/lib/annoFormatTab.c index dde5d8f..9df06f0 100644 --- src/lib/annoFormatTab.c +++ src/lib/annoFormatTab.c @@ -47,58 +47,44 @@ char fullName[PATH_LEN]; makeFullColumnName(fullName, sizeof(fullName), sourceName, colName); int vis = hashIntValDefault(self->columnVis, fullName, 1); if (vis == 0) return FALSE; } return TRUE; } static void printHeaderColumns(struct annoFormatTab *self, struct annoStreamer *source, boolean isFirst) /* Print names of included columns from this source. */ { FILE *f = self->f; char *sourceName = source->name; -char fullName[PATH_LEN]; -if (source->rowType == arWig) - { - // Fudge in the row's chrom, start, end as output columns even though they're not in autoSql - if (isFirst) - { - makeFullColumnName(fullName, sizeof(fullName), sourceName, "chrom"); - fprintf(f, "#%s", fullName); - isFirst = FALSE; - } - makeFullColumnName(fullName, sizeof(fullName), sourceName, "start"); - fprintf(f, "\t%s", fullName); - makeFullColumnName(fullName, sizeof(fullName), sourceName, "end"); - fprintf(f, "\t%s", fullName); - } struct asColumn *col; int i; for (col = source->asObj->columnList, i = 0; col != NULL; col = col->next, i++) { if (columnIsIncluded(self, sourceName, col->name)) { if (isFirst) { fputc('#', f); isFirst = FALSE; } else fputc('\t', f); + char fullName[PATH_LEN]; makeFullColumnName(fullName, sizeof(fullName), sourceName, col->name); fputs(fullName, f); } } } static void aftInitialize(struct annoFormatter *vSelf, struct annoStreamer *primary, struct annoStreamer *integrators) /* Print header, regardless of whether we get any data after this. */ { struct annoFormatTab *self = (struct annoFormatTab *)vSelf; if (self->needHeader) { char *primaryHeader = primary->getHeader(primary); if (isNotEmpty(primaryHeader)) @@ -112,54 +98,65 @@ } } 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 **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 an array of strings with a single string containing the average of values in row. */ +/* Return chrom, chromStart, chromEnd and a 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; +return bed4WordsFromAnnoRow(row, avgStr); } static char **wordsFromWigRowVals(struct annoRow *row) -/* Return an array of strings with a single string containing comma-sep per-base wiggle values. */ +/* 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; -AllocArray(words, 1); -words[0] = dyStringCannibalize(&dy); +char **words = bed4WordsFromAnnoRow(row, dy->string); +dyStringFree(&dy); 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) { @@ -175,61 +172,49 @@ 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; boolean freeWhenDone = FALSE; char **words = wordsFromRow(row, streamer, &freeWhenDone); -if (streamer->rowType == arWig) - { - // Fudge in the row's chrom, start, end as output columns even though they're not in autoSql - if (isFirst) - { - if (row != NULL) - fputs(row->chrom, f); - isFirst = FALSE; - } - if (row != NULL) - fprintf(f, "\t%u\t%u", row->start, row->end); - else - fputs("\t\t", f); - } struct asColumn *col; int i; for (col = streamer->asObj->columnList, i = 0; col != NULL; col = col->next, i++) { if (columnIsIncluded(self, sourceName, col->name)) { if (isFirst) isFirst = FALSE; else fputc('\t', f); if (words != NULL) fputs((words[i] ? words[i] : ""), f); } } +int wordCount = i; if (freeWhenDone) { - freeMem(words[0]); + for (i = 0; i < wordCount; i++) + freeMem(words[i]); freeMem(words); } } static void aftComment(struct annoFormatter *fSelf, char *content) /* Print out a comment line. */ { if (strchr(content, '\n')) errAbort("aftComment: no multi-line input"); struct annoFormatTab *self = (struct annoFormatTab *)fSelf; fprintf(self->f, "# %s\n", content); } static void aftFormatOne(struct annoFormatter *vSelf, struct annoStreamRows *primaryData, struct annoStreamRows *gratorData, int gratorCount)