b8cb0221d6798d0fbebbf5de3b75a46ad795174b
angie
  Mon Nov 5 11:40:14 2012 -0800
Feature #6152 (Variant Annotation Integrator): added annoStreamBigBed.
diff --git src/lib/annoStreamBigBed.c src/lib/annoStreamBigBed.c
new file mode 100644
index 0000000..7a29771
--- /dev/null
+++ src/lib/annoStreamBigBed.c
@@ -0,0 +1,119 @@
+/* annoStreamBigBed -- subclass of annoStreamer for bigBed file or URL */
+
+#include "annoStreamBigBed.h"
+#include "annoGratorQuery.h"
+#include "bigBed.h"
+#include "localmem.h"
+#include "sqlNum.h"
+
+struct annoStreamBigBed
+    {
+    struct annoStreamer streamer;	// Parent class members & methods
+    // Private members
+    struct bbiFile *bbi;		// bbi handle for bigBed file/URL.
+    struct lm *intervalQueryLm;		// localmem object for bigBedIntervalQuery
+    struct bigBedInterval *intervalList;	// results of bigBedIntervalQuery
+    struct bigBedInterval *nextInterval;	// next result to be translated into row
+    int maxItems;			// max items returned from bigBedIntervalQuery
+    char **row;				// storage for results of bigBedIntervalToRow
+    char *startBuf;			// storage for stringified start from bigBedIntervalToRow
+    char *endBuf;			// storage for stringified end from bigBedIntervalToRow
+    };
+
+static void asbbSetRegion(struct annoStreamer *vSelf, char *chrom, uint regionStart, uint regionEnd)
+/* Set region -- and free localmem from previous query if necessary. */
+{
+annoStreamerSetRegion(vSelf, chrom, regionStart, regionEnd);
+struct annoStreamBigBed *self = (struct annoStreamBigBed *)vSelf;
+self->intervalList = NULL;
+lmCleanup(&(self->intervalQueryLm));
+}
+
+static void asbbDoQuery(struct annoStreamBigBed *self)
+/* Store results of an interval query. [Would be nice to make a streaming version of this.] */
+{
+struct annoStreamer *streamer = &(self->streamer);
+if (self->intervalQueryLm == NULL)
+    self->intervalQueryLm = lmInit(0);
+self->intervalList = bigBedIntervalQuery(self->bbi, streamer->chrom,
+					 streamer->regionStart, streamer->regionEnd,
+					 self->maxItems, self->intervalQueryLm);
+self->nextInterval = self->intervalList;
+}
+
+static char **nextRowUnfiltered(struct annoStreamBigBed *self)
+/* Convert the next available interval into a row of words, or return NULL. */
+{
+struct annoStreamer *streamer = &(self->streamer);
+if (self->nextInterval == NULL)
+    return NULL;
+int fieldCount = bigBedIntervalToRow(self->nextInterval, streamer->chrom,
+				     self->startBuf, self->endBuf,
+				     self->row, streamer->numCols+1);
+if (fieldCount != streamer->numCols)
+    errAbort("annoStreamBigBed: expected %d columns, got %d", streamer->numCols, fieldCount);
+self->nextInterval = self->nextInterval->next;
+return self->row;
+}
+
+static struct annoRow *asbbNextRow(struct annoStreamer *vSelf)
+/* Return a single annoRow, or NULL if there are no more items. */
+{
+struct annoStreamBigBed *self = (struct annoStreamBigBed *)vSelf;
+if (self->intervalList == NULL)
+    asbbDoQuery(self);
+char **row = nextRowUnfiltered(self);
+if (row == NULL)
+    return NULL;
+// Skip past any left-join failures until we get a right-join failure, a passing row, or EOF.
+boolean rightFail = FALSE;
+while (annoFilterRowFails(vSelf->filters, row, vSelf->numCols, &rightFail))
+    {
+    if (rightFail)
+	break;
+    row = nextRowUnfiltered(self);
+    if (row == NULL)
+	return NULL;
+    }
+uint chromStart = sqlUnsigned(row[1]);
+uint chromEnd = sqlUnsigned(row[2]);
+return annoRowFromStringArray(vSelf->chrom, chromStart, chromEnd, rightFail, row, vSelf->numCols);
+}
+
+static void asbbClose(struct annoStreamer **pVSelf)
+/* Close bbi handle and free self. */
+{
+if (pVSelf == NULL)
+    return;
+struct annoStreamBigBed *self = *(struct annoStreamBigBed **)pVSelf;
+bigBedFileClose(&(self->bbi));
+self->intervalList = NULL;
+lmCleanup(&(self->intervalQueryLm));
+freeMem(self->row);
+freeMem(self->startBuf);
+freeMem(self->endBuf);
+annoStreamerFree(pVSelf);
+}
+
+struct annoStreamer *annoStreamBigBedNew(char *fileOrUrl, int maxItems)
+/* Create an annoStreamer (subclass) object from a file or URL; if
+ * maxItems is 0, all items from a query will be returned, otherwise
+ * each query is limited to maxItems. */
+{
+struct bbiFile *bbi = bigBedFileOpen(fileOrUrl);
+struct asObject *asObj = bigBedAsOrDefault(bbi);
+struct annoStreamBigBed *self = NULL;
+AllocVar(self);
+struct annoStreamer *streamer = &(self->streamer);
+annoStreamerInit(streamer, asObj);
+streamer->rowType = arWords;
+streamer->setRegion = asbbSetRegion;
+streamer->nextRow = asbbNextRow;
+streamer->close = asbbClose;
+self->bbi = bbi;
+self->maxItems = maxItems;
+AllocArray(self->row, streamer->numCols + 1);
+self->startBuf = needMem(32);
+self->endBuf = needMem(32);
+return (struct annoStreamer *)self;
+}