e1a373956ea8f5a93f7c63208e1ee39a1aceb4de braney Wed Aug 31 11:44:17 2011 -0700 fix bug in bigWigMerge #4561. Add test that would have found it. diff --git src/utils/bigWigMerge/bigWigMerge.c src/utils/bigWigMerge/bigWigMerge.c index 58ce49f..5eda7e2 100644 --- src/utils/bigWigMerge/bigWigMerge.c +++ src/utils/bigWigMerge/bigWigMerge.c @@ -24,57 +24,69 @@ " -clip=NNN.N - values higher than this are clipped to this value\n" ); } double clThreshold = 0.0; double clAdjust = 0.0; double clClip = BIGDOUBLE; static struct optionSpec options[] = { {"threshold", OPTION_DOUBLE}, {"adjust", OPTION_DOUBLE}, {"clip", OPTION_DOUBLE}, {NULL, 0}, }; -struct slName *getAllChroms(struct bbiFile *fileList) + +static int bbiChromInfoCmpStringsWithEmbeddedNumbers(const void *va, const void *vb) +/* Compare strings such as gene names that may have embedded numbers, + * so that bmp4a comes before bmp14a */ +{ +const struct bbiChromInfo *a = *((struct bbiChromInfo **)va); +const struct bbiChromInfo *b = *((struct bbiChromInfo **)vb); +return cmpStringsWithEmbeddedNumbers(a->name, b->name); +} + +struct bbiChromInfo *getAllChroms(struct bbiFile *fileList) /* Read chromosomes from all files and make sure they agree, and return merged list. */ { struct bbiFile *file; struct hash *hash = hashNew(0); -struct slName *nameList = NULL; +struct bbiChromInfo *nameList = NULL; for (file = fileList; file != NULL; file = file->next) { - struct bbiChromInfo *info, *infoList = bbiChromList(file); - for (info = infoList; info != NULL; info = info->next) + struct bbiChromInfo *info, *next, *infoList = bbiChromList(file); + for (info = infoList; info != NULL; info = next) { + next = info->next; + struct bbiChromInfo *oldInfo = hashFindVal(hash, info->name); if (oldInfo != NULL) { if (info->size != oldInfo->size) errAbort("ERROR: Merging from different assemblies? " "Chromosome %s is %d in %s but %d in another file", info->name, (int)(info->size), file->fileName, (int)oldInfo->size); } else { hashAdd(hash, info->name, info); - slNameAddHead(&nameList, info->name); + slAddHead(&nameList, info); } } } -slSort(&nameList, slNameCmpStringsWithEmbeddedNumbers); +slSort(&nameList, bbiChromInfoCmpStringsWithEmbeddedNumbers); return nameList; } boolean allStartEndSame(struct bbiInterval *ivList) /* Return true if all items in list start and end the same place. */ { int start = ivList->start, end = ivList->end; struct bbiInterval *iv; for (iv = ivList->next; iv != NULL; iv = iv->next) { if (iv->start != start || iv->end != end) return FALSE; } return TRUE; } @@ -96,41 +108,41 @@ void bigWigMerge(int inCount, char *inFiles[], char *outFile) /* bigWigMerge - Merge together multiple bigWigs into a single one.. */ { /* Make a list of open bigWig files. */ struct bbiFile *inFile, *inFileList = NULL; int i; for (i=0; i<inCount; ++i) { inFile = bigWigFileOpen(inFiles[i]); slAddTail(&inFileList, inFile); } FILE *f = mustOpen(outFile, "w"); -struct slName *chrom, *chromList = getAllChroms(inFileList); +struct bbiChromInfo *chrom, *chromList = getAllChroms(inFileList); verbose(1, "Got %d chromosomes from %d bigWigs\nProcessing", slCount(chromList), slCount(inFileList)); double *mergeBuf = NULL; int mergeBufSize = 0; for (chrom = chromList; chrom != NULL; chrom = chrom->next) { struct lm *lm = lmInit(0); /* Make sure merge buffer is big enough. */ - int chromSize = bbiChromSize(inFileList, chrom->name); + int chromSize = chrom->size; verboseDot(); verbose(2, "Processing %s (%d bases)\n", chrom->name, chromSize); if (chromSize > mergeBufSize) { mergeBufSize = chromSize; freeMem(mergeBuf); mergeBuf = needHugeMem(mergeBufSize * sizeof(double)); } int i; for (i=0; i<chromSize; ++i) mergeBuf[i] = 0.0; /* Loop through each input file grabbing data and merging it in. */ for (inFile = inFileList; inFile != NULL; inFile = inFile->next) {