72d5004d94ad220eecb2868ee1d58d6257ab051d
kent
  Mon Jan 20 12:05:23 2014 -0800
Improving handling of empty data sets by bedToBigBed and bigBedInfo.
diff --git src/lib/cirTree.c src/lib/cirTree.c
index 84f3687..afc1419 100644
--- src/lib/cirTree.c
+++ src/lib/cirTree.c
@@ -150,30 +150,32 @@
 struct rTree *el;
 for (el = tree; el != NULL; el = el->next)
     {
     levelSizes[level] += 1;
     if (level < maxLevel)
         calcLevelSizes(el->children, levelSizes, level+1, maxLevel);
     }
 }
 
 static struct rTree *rTreeFromChromRangeArray( struct lm *lm, int blockSize, int itemsPerSlot,
 	void *itemArray, int itemSize, bits64 itemCount,  void *context,
 	struct cirTreeRange (*fetchKey)(const void *va, void *context),
 	bits64 (*fetchOffset)(const void *va, void *context), bits64 endFileOffset,
 	int *retLevelCount)
 {
+if (itemCount == 0)
+    return NULL;
 char *items = itemArray;
 struct rTree *el, *list=NULL, *tree = NULL;
 
 /* Make first level above leaf. */
 bits64 i;
 bits64 nextOffset = (*fetchOffset)(items, context);
 int oneSize = 0;
 for (i=0; i<itemCount; i += oneSize)
     {
 
     /* Allocate element and put on list. */
     lmAllocVar(lm, el);
     slAddHead(&list, el);
 
     /* Fill out most of element from first item in element. */
@@ -332,47 +334,51 @@
 /* Write out leaf level. */
 int leafLevel = levelCount - 2;
 writeLeaves(blockSize, leafNodeSize(blockSize), tree, leafLevel, f);
 }
 
 void cirTreeFileBulkIndexToOpenFile(
 	void *itemArray, int itemSize, bits64 itemCount, 
 	bits32 blockSize, bits32 itemsPerSlot,
 	void *context,
 	struct cirTreeRange (*fetchKey)(const void *va, void *context),
 	bits64 (*fetchOffset)(const void *va, void *context), 
 	bits64 endFileOffset, FILE *f)
 /* Create a r tree index from a sorted array, writing output starting at current position
  * of an already open file.  See rTreeFileCreate for explanation of parameters. */
 {
-int levelCount;
+int levelCount = 0;
 struct lm *lm = lmInit(0);
 struct rTree *tree = rTreeFromChromRangeArray(lm, blockSize, itemsPerSlot,
 	itemArray, itemSize, itemCount, context, fetchKey, fetchOffset, endFileOffset,
 	&levelCount);
+struct rTree dummyTree = {.startBase=0};
+if (tree == NULL) 
+    tree = &dummyTree;	// Work for empty files....
 bits32 magic = cirTreeSig;
 bits32 reserved = 0;
 writeOne(f, magic);
 writeOne(f, blockSize);
 writeOne(f, itemCount);
 writeOne(f, tree->startChromIx);
 writeOne(f, tree->startBase);
 writeOne(f, tree->endChromIx);
 writeOne(f, tree->endBase);
 writeOne(f, endFileOffset);
 writeOne(f, itemsPerSlot);
 writeOne(f, reserved);
+if (tree != &dummyTree)
     writeTreeToOpenFile(tree, blockSize, levelCount, f);
 lmCleanup(&lm);
 }
 
 void cirTreeFileCreate(
 	void *itemArray, 	/* Sorted array of things to index. */
 	int itemSize, 		/* Size of each element in array. */
 	bits64 itemCount, 	/* Number of elements in array. */
 	bits32 blockSize,	/* R tree block size - # of children for each node. */
 	bits32 itemsPerSlot,	/* Number of items to put in each index slot at lowest level. */
 	void *context,		/* Context pointer for use by fetch call-back functions. */
 	struct cirTreeRange (*fetchKey)(const void *va, void *context),/* Given item, return key. */
 	bits64 (*fetchOffset)(const void *va, void *context), /* Given item, return file offset */
 	bits64 endFileOffset,				 /* Last position in file we index. */
 	char *fileName)                                  /* Name of output file. */