afa49f8318fdcd16205bc6cbc55d293d208fc5bd angie Tue May 10 11:37:29 2011 -0700 Feature #3711 bugfix: handle 0 or 1 items correctly in hacTree andVCF track handler's haplotype clustering. diff --git src/lib/hacTree.c src/lib/hacTree.c index eda012f..f7e4bdc 100644 --- src/lib/hacTree.c +++ src/lib/hacTree.c @@ -52,33 +52,36 @@ leafWraps[i].node = &(leafNodes[i]); leafWraps[i].cmpF = cmpF; leafWraps[i].extraData = extraData; } qsort(leafWraps, itemCount, sizeof(struct sortWrapper), sortWrapCmp); return leafWraps; } INLINE void initNode(struct hacTree *node, const struct hacTree *left, const struct hacTree *right, hacDistanceFunction *distF, hacMergeFunction *mergeF, void *extraData) /* Initialize node to have left and right as its children. Leave parent pointers * alone -- they would be unstable during tree construction. */ { node->left = (struct hacTree *)left; node->right = (struct hacTree *)right; +if (left != NULL && right != NULL) + { node->childDistance = distF(left->itemOrCluster, right->itemOrCluster, extraData); node->itemOrCluster = mergeF(left->itemOrCluster, right->itemOrCluster, extraData); } +} INLINE struct hacTree preClusterNodes(const struct sortWrapper *leafWraps, int i, int runLength, hacDistanceFunction *distF, hacMergeFunction *mergeF, void *extraData, struct lm *localMem) /* Caller has allocated a node, and this returns what to store there: * a recursively constructed cluster of nodes extracted from wrapped * leafNodes (leafWraps) starting at i, for runLength items. */ { struct hacTree ret = {NULL, NULL, NULL, NULL, 0, NULL}; if (runLength > 2) { struct hacTree *newClusters = lmAlloc(localMem, 2 * sizeof(struct hacTree)); int halfLength = runLength/2; newClusters[0] = preClusterNodes(leafWraps, i, halfLength, distF, mergeF, extraData, localMem); @@ -123,36 +126,42 @@ return newLeaves; } static struct hacTree *pairUpItems(const struct slList *itemList, int itemCount, int *retPairCount, struct lm *localMem, hacDistanceFunction *distF, hacMergeFunction *mergeF, hacCmpFunction *cmpF, void *extraData) /* Allocate & initialize leaf nodes and all possible pairings of leaf nodes * which will be our seed clusters. If cmpF is given, pre-sort the leaf nodes * and pre-cluster identical leaves before generating seed clusters. */ { struct hacTree *leafNodes = leafNodesFromItems(itemList, itemCount, localMem); if (cmpF != NULL) leafNodes = sortAndPreCluster(leafNodes, &itemCount, localMem, distF, mergeF, cmpF, extraData); -int pairCount = itemCount * (itemCount-1) / 2; +int pairCount = (itemCount == 1) ? 1 : (itemCount * (itemCount-1) / 2); struct hacTree *pairPool = lmAlloc(localMem, pairCount * sizeof(struct hacTree)); +if (itemCount == 1) + initNode(pairPool, leafNodes, NULL, distF, mergeF, extraData); +else + { int i, j, pairIx; for (i=0, pairIx=0; i < itemCount-1; i++) for (j=i+1; j < itemCount; j++, pairIx++) - initNode(&(pairPool[pairIx]), &(leafNodes[i]), &(leafNodes[j]), distF, mergeF, extraData); + initNode(&(pairPool[pairIx]), &(leafNodes[i]), &(leafNodes[j]), distF, mergeF, + extraData); + } *retPairCount = pairCount; return pairPool; } struct hacTree *hacTreeFromItems(const struct slList *itemList, struct lm *localMem, hacDistanceFunction *distF, hacMergeFunction *mergeF, hacCmpFunction *cmpF, void *extraData) /* Using distF, mergeF, optionally cmpF and binary tree operations, * perform a hierarchical agglomerative (bottom-up) clustering of * items. To free the resulting tree, lmCleanup(&localMem). */ // // Implementation: // // Create a pool containing all pairs of items (N*(N-1)/2), and build // a hierarchical binary tree of items from the bottom up. In each