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. */