src/lib/metaWig.c 1.1

1.1 2010/06/03 16:51:55 kent
Moving metaWig stuff from wigCorrelate to library.
Index: src/lib/metaWig.c
===================================================================
RCS file: src/lib/metaWig.c
diff -N src/lib/metaWig.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ src/lib/metaWig.c	3 Jun 2010 16:51:55 -0000	1.1
@@ -0,0 +1,184 @@
+#include "common.h"
+#include "hash.h"
+#include "linefile.h"
+#include "localmem.h"
+#include "bigWig.h"
+#include "bwgInternal.h"
+#include "metaWig.h"
+
+static struct hash *hashSectionChroms(struct bwgSection *sectionList)
+/* Return hash keyed by chromosome name with values that are the
+ * first section in the chromosome. */
+{
+struct hash *hash = hashNew(0);
+struct bwgSection *section;
+for (section = sectionList; section != NULL; section = section->next)
+    {
+    if (!hashLookup(hash, section->chrom))
+        hashAdd(hash, section->chrom, section);
+    }
+return hash;
+}
+
+struct metaWig *metaWigOpen(char *fileName, struct lm *lm)
+/* Wrap self around file.  Read all of it if it's wig, just header if bigWig. */
+{
+struct metaWig *mw;
+lmAllocVar(lm, mw);
+if (isBigWig(fileName))
+    {
+    mw->type = mwtBigWig;
+    mw->bwf = bigWigFileOpen(fileName);
+    }
+else
+    {
+    mw->sectionList = bwgParseWig(fileName, FALSE, NULL, 512, lm);
+    mw->chromHash = hashSectionChroms(mw->sectionList);
+    mw->type = mwtSections;
+    }
+return mw;
+}
+
+void metaWigClose(struct metaWig **pMw)
+/* Close up metaWig file */
+{
+struct metaWig *mw = *pMw;
+if (mw != NULL)
+    {
+    bigWigFileClose(&mw->bwf);
+    *pMw = NULL;
+    /* note mw is in local memory. */
+    }
+}
+
+struct slName *metaWigChromList(struct metaWig *mw)
+/* Return list of chromosomes covered in wig. */
+{
+struct slName *list = NULL;
+switch (mw->type)
+    {
+    case mwtSections:
+        {
+	struct hashEl *chrom, *chromList = hashElListHash(mw->chromHash);
+	for (chrom = chromList; chrom != NULL; chrom = chrom->next)
+	    slNameAddHead(&list, chrom->name);
+	hashElFreeList(&chromList);
+	break;
+	}
+    case mwtBigWig:
+        {
+	struct bbiChromInfo *chrom, *chromList = bbiChromList(mw->bwf);
+	for (chrom = chromList; chrom != NULL; chrom = chrom->next)
+	    slNameAddHead(&list, chrom->name);
+	bbiChromInfoFreeList(&chromList);
+	break;
+	}
+    }
+slSort(&list, slNameCmpStringsWithEmbeddedNumbers);
+return list;
+}
+
+static void bedGraphSectionToIntervals(struct bwgSection *section, struct lm *lm,
+	struct bbiInterval **pList)
+/* Convert bedGraph section to interval format. */
+{
+struct bwgBedGraphItem *item;
+for (item = section->items.bedGraphList; item != NULL; item = item->next)
+    {
+    struct bbiInterval *el;
+    lmAllocVar(lm, el);
+    el->start = item->start;
+    el->end = item->end;
+    el->val = item->val;
+    slAddHead(pList, el);
+    }
+}
+
+static void varStepSectionToIntervals(struct bwgSection *section, struct lm *lm,
+	struct bbiInterval **pList)
+/* Convert bedGraph section to interval format. */
+{
+struct bwgVariableStepPacked *array = section->items.variableStepPacked;
+int i, count = section->itemCount;
+bits32 span = section->itemSpan;
+for (i=0; i<count; ++i)
+    {
+    struct bwgVariableStepPacked *item = &array[i];
+    struct bbiInterval *el;
+    lmAllocVar(lm, el);
+    el->start = item->start;
+    el->end = item->start + span;
+    el->val = item->val;
+    slAddHead(pList, el);
+    }
+}
+
+static void fixedStepSectionToIntervals(struct bwgSection *section, struct lm *lm,
+	struct bbiInterval **pList)
+/* Convert bedGraph section to interval format. */
+{
+struct bwgFixedStepPacked *array = section->items.fixedStepPacked;
+int i, count = section->itemCount;
+bits32 span = section->itemSpan;
+bits32 step = section->itemStep;
+bits32 start = section->start;
+for (i=0; i<count; ++i)
+    {
+    struct bwgFixedStepPacked *item = &array[i];
+    struct bbiInterval *el;
+    lmAllocVar(lm, el);
+    el->start = start;
+    el->end = start + span;
+    el->val = item->val;
+    start += step;
+    slAddHead(pList, el);
+    }
+}
+
+static void addIntervals(struct bwgSection *section, struct lm *lm, struct bbiInterval **pList)
+/* Convert section to list of allocated in lm */
+{
+switch (section->type)
+    {
+    case bwgTypeBedGraph:
+        bedGraphSectionToIntervals(section, lm, pList);
+        break;
+    case bwgTypeVariableStep:
+	varStepSectionToIntervals(section, lm, pList);
+        break;
+    case bwgTypeFixedStep:
+	fixedStepSectionToIntervals(section, lm, pList);
+	break;
+    default:
+        errAbort("unknown section type %d in addIntervals", section->type);
+	break;
+    }
+}
+
+struct bbiInterval *metaIntervalsForChrom(struct metaWig *mw, char *chrom, struct lm *lm)
+/* Get sorted list of all intervals with data on chromosome. */
+{
+struct bbiInterval *list = NULL;
+switch (mw->type)
+    {
+    case mwtSections:
+        {
+	struct bwgSection *section, *sectionList = hashFindVal(mw->chromHash, chrom);
+	for (section = sectionList; section != NULL; section = section->next)
+	   {
+	   if (!sameString(section->chrom, chrom))
+	       break;
+	   addIntervals(section, lm, &list);
+	   }
+	slReverse(&list);
+	break;
+	}
+    case mwtBigWig:
+        {
+	list = bigWigIntervalQuery(mw->bwf, chrom, 0, bbiChromSize(mw->bwf, chrom), lm);
+	break;
+	}
+    }
+return list;
+}
+