void makeCactusTree_chain(Chain *chain, FILE *fileHandle,
        const char *parentNodeName, const char *parentEdgeColour) {
    //Write the flower nodes.
    char *chainNameString = cactusMisc_nameToString(chain_getName(chain));
    const char *edgeColour = graphViz_getColour();
    addNodeToGraph(chainNameString, fileHandle,
            chain_getAverageInstanceBaseLength(chain) / totalProblemSize,
            "box", chainNameString);
    //Write in the parent edge.
    if (parentNodeName != NULL) {
        graphViz_addEdgeToGraph(parentNodeName, chainNameString, fileHandle,
                "", parentEdgeColour, 10, 1, "forward");
    }
    //Create the linkers to the nested flowers.
    Link *link = chain_getFirst(chain);
    while(link != NULL) {
        Group *group = link_getGroup(link);
        assert(group != NULL);
        assert(!group_isLeaf(group));
        if (!group_isLeaf(group)) {
            makeCactusTree_flower(group_getNestedFlower(group), fileHandle,
                    chainNameString, edgeColour);
        }
        link = link_getNextLink(link);
    }
    free(chainNameString);
}
Example #2
0
void flower_checkRecursive(Flower *flower) {
    flower_check(flower);
    Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
    Group *group;
    while ((group = flower_getNextGroup(groupIt)) != NULL) {
        if (!group_isLeaf(group)) {
            flower_checkRecursive(group_getNestedFlower(group));
        }
    }
    flower_destructGroupIterator(groupIt);
}
Example #3
0
void testGroup_makeNonLeaf(CuTest *testCase) {
    cactusGroupTestSetup();
    CuAssertTrue(testCase, group_isLeaf(group2));
    end_setGroup(end4, group2);
    group_makeNestedFlower(group2);
    CuAssertTrue(testCase, !group_isLeaf(group2));
    Flower *nestedFlower = group_getNestedFlower(group2);
    CuAssertTrue(testCase, nestedFlower != NULL);
    CuAssertTrue(testCase, !flower_builtBlocks(flower));
    CuAssertTrue(testCase, !flower_builtTrees(flower));
    CuAssertTrue(testCase, !flower_builtFaces(flower));
    CuAssertTrue(testCase, flower_getName(nestedFlower) == group_getName(group2));
    CuAssertTrue(testCase, flower_getParentGroup(nestedFlower) == group2);
    CuAssertTrue(testCase, flower_getEndNumber(nestedFlower) == 1);
    End *nestedEnd = flower_getFirstEnd(nestedFlower);
    CuAssertTrue(testCase, end_getName(end4) == end_getName(nestedEnd));
    CuAssertTrue(testCase, end_getGroup(nestedEnd) != NULL);
    CuAssertTrue(testCase, flower_getGroupNumber(nestedFlower) == 1);
    CuAssertTrue(testCase, flower_isTerminal(nestedFlower));
    cactusGroupTestTeardown();
}
Example #4
0
bool flower_isLeaf(Flower *flower) {
    Group *group;
    Flower_GroupIterator *iterator = flower_getGroupIterator(flower);
    while ((group = flower_getNextGroup(iterator)) != NULL) {
        if (!group_isLeaf(group)) {
            flower_destructGroupIterator(iterator);
            return 0;
        }
    }
    flower_destructGroupIterator(iterator);
    return 1;
}
static void setAdjacencyLengthsAndRecoverNewCapsAndBrokenAdjacencies(Cap *cap, stList *recoveredCaps) {
    /*
     * Sets the coordinates of the caps to be equal to the length of the adjacency sequence between them.
     * Used to build the reference sequence bottom up.
     *
     * One complexity is that a reference thread between the two caps
     * in each flower f may be broken into two in the children of f.
     * Therefore, for each flower f first identify attached stub ends present in the children of f that are
     * not present in f and copy them into f, reattaching the reference caps as needed.
     */
    while (1) {
        Cap *adjacentCap = cap_getAdjacency(cap);
        assert(adjacentCap != NULL);
        assert(cap_getCoordinate(cap) == INT64_MAX);
        assert(cap_getCoordinate(adjacentCap) == INT64_MAX);
        assert(cap_getStrand(cap) == cap_getStrand(adjacentCap));
        assert(cap_getSide(cap) != cap_getSide(adjacentCap));
        Group *group = end_getGroup(cap_getEnd(cap));
        assert(group != NULL);
        if (!group_isLeaf(group)) { //Adjacency is not terminal, so establish its sequence.
            Flower *nestedFlower = group_getNestedFlower(group);
            Cap *nestedCap = flower_getCap(nestedFlower, cap_getName(cap));
            assert(nestedCap != NULL);
            Cap *nestedAdjacentCap = flower_getCap(nestedFlower, cap_getName(adjacentCap));
            assert(nestedAdjacentCap != NULL);
            Cap *breakerCap;
            int64_t adjacencyLength = traceThreadLength(nestedCap, &breakerCap);
            assert(cap_getOrientation(nestedAdjacentCap));
            if (cap_getPositiveOrientation(breakerCap) != nestedAdjacentCap) { //The thread is broken at the lower level.
                //Copy cap into higher level graph.
                breakerCap = copyCapToParent(breakerCap, recoveredCaps);
                assert(cap_getSide(breakerCap));
                cap_makeAdjacent(cap, breakerCap);
                setAdjacencyLength(cap, breakerCap, adjacencyLength);
                adjacencyLength = traceThreadLength(nestedAdjacentCap, &breakerCap);
                assert(cap_getPositiveOrientation(breakerCap) != cap);
                breakerCap = copyCapToParent(breakerCap, recoveredCaps);
                assert(!cap_getSide(breakerCap));
                cap_makeAdjacent(breakerCap, adjacentCap);
                setAdjacencyLength(adjacentCap, breakerCap, adjacencyLength);
            } else { //The thread is not broken at the lower level
                setAdjacencyLength(cap, adjacentCap, adjacencyLength);
            }
        } else {
            //Set the coordinates of the caps to the adjacency size
            setAdjacencyLength(cap, adjacentCap, 0);
        }
        if ((cap = cap_getOtherSegmentCap(adjacentCap)) == NULL) {
            break;
        }
    }
}
Example #6
0
bool flower_removeIfRedundant(Flower *flower) {
    if (!flower_isLeaf(flower) && flower_getParentGroup(flower) != NULL && flower_getBlockNumber(flower) == 0) { //We will remove this flower..
        Group *parentGroup = flower_getParentGroup(flower); //This group will be destructed
        //Deal with any parent chain..
        if (group_isLink(parentGroup)) {
            link_split(group_getLink(parentGroup));
        }
        Flower *parentFlower = group_getFlower(parentGroup); //We will add the groups in the flower to the parent

        /*
         * For each group in the flower we take its nested flower and attach it to the parent.
         */
        Group *group;
        Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
        while ((group = flower_getNextGroup(groupIt)) != NULL) {
            if (!group_isLeaf(group)) {
                //Copy the group into the parent..
                Flower *nestedFlower = group_getNestedFlower(group);
                assert(nestedFlower != NULL);
                Group *newParentGroup = group_construct(parentFlower, nestedFlower);
                flower_setParentGroup(nestedFlower, newParentGroup);
                group_constructChainForLink(newParentGroup);
            } else {
                Group *newParentGroup = group_construct2(parentFlower);
                End *end;
                Group_EndIterator *endIt = group_getEndIterator(group);
                while ((end = group_getNextEnd(endIt)) != NULL) {
                    End *parentEnd = flower_getEnd(parentFlower, end_getName(end));
                    assert(parentEnd != NULL);
                    end_setGroup(parentEnd, newParentGroup);
                }
                group_destructEndIterator(endIt);
                group_constructChainForLink(newParentGroup);
            }
        }
        flower_destructGroupIterator(groupIt);

        //The group attached to the flower should now be empty
        assert(group_getEndNumber(parentGroup) == 0);
        group_destruct(parentGroup);

        //Now wipe the flower out..
        cactusDisk_deleteFlowerFromDisk(flower_getCactusDisk(flower), flower);
        flower_destruct(flower, 0);
        return 1;
    }
    return 0;
}
Example #7
0
void flower_makeTerminalNormal(Flower *flower) {
    if (!flower_isTerminal(flower)) {
        Flower_GroupIterator *groupIterator;
        Group *group;
        groupIterator = flower_getGroupIterator(flower);
        while ((group = flower_getNextGroup(groupIterator)) != NULL) {
            if (group_isLeaf(group)) {
                //assert(group_getTotalBaseLength(group) == 0);
                Flower *nestedFlower = group_makeNestedFlower(group);
                flower_setBuiltBlocks(nestedFlower, flower_builtBlocks(flower));
                flower_setBuiltTrees(nestedFlower, flower_builtTrees(flower));
                flower_setBuildFaces(nestedFlower, flower_builtFaces(flower));
            }
        }
        flower_destructGroupIterator(groupIterator);
    }
}
Example #8
0
void flower_delete2(Flower *flower, bool isOnDisk) {
    Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
    Group *group;
    while ((group = flower_getNextGroup(groupIt)) != NULL) {
        if (!group_isLeaf(group)) {
            flower_delete2(group_getNestedFlower(group), isOnDisk);
        }
    }
    flower_destructGroupIterator(groupIt);
    Group *parentGroup = flower_getParentGroup(flower);
    if(parentGroup != NULL) {
        parentGroup->leafGroup = 1;
    }
    //This needs modification so that we don't do this directly..
    if(isOnDisk) {
        cactusDisk_deleteFlowerFromDisk(flower_getCactusDisk(flower), flower);
    }
    flower_destruct(flower, 0);
}
Example #9
0
void flower_checkNotEmpty(Flower *flower, bool recursive) {
    //First check the flower is not empty, unless it is the parent group.
    if (flower_hasParentGroup(flower)) {
        assert(flower_getGroupNumber(flower) > 0);
        assert(flower_getEndNumber(flower) > 0);
        assert(flower_getAttachedStubEndNumber(flower) > 0); //We must have some ends to tie us into the parent problem + flower_getBlockEndNumber(flower) > 0);
    }
    //Now Checks that each group contains at least one end and call recursive.
    Group *group;
    Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
    while ((group = flower_getNextGroup(groupIt)) != NULL) {
        assert(group_getEndNumber(group) > 0);
        assert(group_getAttachedStubEndNumber(group) + group_getBlockEndNumber(group) > 0);
        if (recursive && !group_isLeaf(group)) {
            flower_checkNotEmpty(group_getNestedFlower(group), 1);
        }
    }
    flower_destructGroupIterator(groupIt);
}
Example #10
0
bool flower_deleteIfEmpty(Flower *flower) {
    if (flower_getEndNumber(flower) == 0 && flower_getParentGroup(flower) != NULL) { //contains nothing useful..
        assert(flower_getChainNumber(flower) == 0);
        assert(flower_getBlockNumber(flower) == 0);
        while (flower_getGroupNumber(flower) > 0) {
            Group *group = flower_getFirstGroup(flower);
            if (!group_isLeaf(group)) {
                bool i = flower_deleteIfEmpty(group_getNestedFlower(group));
                (void) i;
                assert(i);
            }
        }
        assert(flower_getGroupNumber(flower) == 0);
        //This needs modification so that we don't do this directly..
        cactusDisk_deleteFlowerFromDisk(flower_getCactusDisk(flower), flower);
        Group *parentGroup = flower_getParentGroup(flower);
        group_destruct(parentGroup);
        flower_destruct(flower, 0);
        return 1;
    }
    return 0;
}
void topDown(Flower *flower, Name referenceEventName) {
    /*
     * Run on each flower, top down. Sets the coordinates of each reference cap to the correct
     * sequence, and sets the bases of the reference sequence to be consensus bases.
     */
    Flower_EndIterator *endIt = flower_getEndIterator(flower);
    End *end;
    while ((end = flower_getNextEnd(endIt)) != NULL) {
        Cap *cap = getCapForReferenceEvent(end, referenceEventName); //The cap in the reference
        if (cap != NULL) {
            cap = cap_getStrand(cap) ? cap : cap_getReverse(cap);
            if (!cap_getSide(cap)) {
                assert(cap_getCoordinate(cap) != INT64_MAX);
                Sequence *sequence = cap_getSequence(cap);
                assert(sequence != NULL);
                Group *group = end_getGroup(end);
                if (!group_isLeaf(group)) {
                    Flower *nestedFlower = group_getNestedFlower(group);
                    Cap *nestedCap = flower_getCap(nestedFlower, cap_getName(cap));
                    assert(nestedCap != NULL);
                    nestedCap = cap_getStrand(nestedCap) ? nestedCap : cap_getReverse(nestedCap);
                    assert(cap_getStrand(nestedCap));
                    assert(!cap_getSide(nestedCap));
                    int64_t endCoordinate = setCoordinates(nestedFlower, sequence_getMetaSequence(sequence),
                                                           nestedCap, cap_getCoordinate(cap));
                    (void) endCoordinate;
                    assert(endCoordinate == cap_getCoordinate(cap_getAdjacency(cap)));
                    assert(endCoordinate
                           == cap_getCoordinate(
                               flower_getCap(nestedFlower, cap_getName(cap_getAdjacency(cap)))));
                }
            }
        }
    }
    flower_destructEndIterator(endIt);
}
Example #12
0
void testGroup_isLeaf(CuTest *testCase) {
    cactusGroupTestSetup();
    CuAssertTrue(testCase, !group_isLeaf(group));
    CuAssertTrue(testCase, group_isLeaf(group2));
    cactusGroupTestTeardown();
}
Example #13
0
int main(int argc, char *argv[]) {
    /*
     * Open the database.
     * Construct a flower.
     * Construct an event tree representing the species tree.
     * For each sequence contruct two ends each containing an cap.
     * Make a file for the sequence.
     * Link the two caps.
     * Finish!
     */

    int64_t key, j;
    Group *group;
    Flower_EndIterator *endIterator;
    End *end;
    bool makeEventHeadersAlphaNumeric = 0;

    /*
     * Arguments/options
     */
    char * logLevelString = NULL;
    char * speciesTree = NULL;
    char * outgroupEvents = NULL;

    ///////////////////////////////////////////////////////////////////////////
    // (0) Parse the inputs handed by genomeCactus.py / setup stuff.
    ///////////////////////////////////////////////////////////////////////////

    while (1) {
        static struct option long_options[] = { { "logLevel", required_argument, 0, 'a' }, { "cactusDisk", required_argument, 0, 'b' }, {
                "speciesTree", required_argument, 0, 'f' }, { "outgroupEvents", required_argument, 0, 'g' },
                { "help", no_argument, 0, 'h' }, { "makeEventHeadersAlphaNumeric", no_argument, 0, 'i' }, { 0, 0, 0, 0 } };

        int option_index = 0;

        key = getopt_long(argc, argv, "a:b:f:hg:i", long_options, &option_index);

        if (key == -1) {
            break;
        }

        switch (key) {
            case 'a':
                logLevelString = optarg;
                break;
            case 'b':
                cactusDiskDatabaseString = optarg;
                break;
            case 'f':
                speciesTree = optarg;
                break;
            case 'g':
                outgroupEvents = optarg;
                break;
            case 'h':
                usage();
                return 0;
            case 'i':
                makeEventHeadersAlphaNumeric = 1;
                break;
            default:
                usage();
                return 1;
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // (0) Check the inputs.
    ///////////////////////////////////////////////////////////////////////////

    //assert(logLevelString == NULL || strcmp(logLevelString, "CRITICAL") == 0 || strcmp(logLevelString, "INFO") == 0 || strcmp(logLevelString, "DEBUG") == 0);
    assert(cactusDiskDatabaseString != NULL);
    assert(speciesTree != NULL);

    //////////////////////////////////////////////
    //Set up logging
    //////////////////////////////////////////////

    st_setLogLevelFromString(logLevelString);

    //////////////////////////////////////////////
    //Log (some of) the inputs
    //////////////////////////////////////////////

    st_logInfo("Flower disk name : %s\n", cactusDiskDatabaseString);

    for (j = optind; j < argc; j++) {
        st_logInfo("Sequence file/directory %s\n", argv[j]);
    }

    //////////////////////////////////////////////
    //Load the database
    //////////////////////////////////////////////

    stKVDatabaseConf *kvDatabaseConf = kvDatabaseConf = stKVDatabaseConf_constructFromString(cactusDiskDatabaseString);
    if (stKVDatabaseConf_getType(kvDatabaseConf) == stKVDatabaseTypeTokyoCabinet || stKVDatabaseConf_getType(kvDatabaseConf)
            == stKVDatabaseTypeKyotoTycoon) {
        assert(stKVDatabaseConf_getDir(kvDatabaseConf) != NULL);
        cactusDisk = cactusDisk_construct2(kvDatabaseConf, "cactusSequences");
    } else {
        cactusDisk = cactusDisk_construct(kvDatabaseConf, 1);
    }
    st_logInfo("Set up the flower disk\n");

    //////////////////////////////////////////////
    //Construct the flower
    //////////////////////////////////////////////

    if (cactusDisk_getFlower(cactusDisk, 0) != NULL) {
        cactusDisk_destruct(cactusDisk);
        st_logInfo("The first flower already exists\n");
        return 0;
    }
    flower = flower_construct2(0, cactusDisk);
    assert(flower_getName(flower) == 0);
    st_logInfo("Constructed the flower\n");

    //////////////////////////////////////////////
    //Construct the event tree
    //////////////////////////////////////////////

    st_logInfo("Going to build the event tree with newick string: %s\n", speciesTree);
    stTree *tree = stTree_parseNewickString(speciesTree);
    st_logInfo("Parsed the tree\n");
    if (makeEventHeadersAlphaNumeric) {
        makeEventHeadersAlphaNumericFn(tree);
    }
    stTree_setBranchLength(tree, INT64_MAX);
    checkBranchLengthsAreDefined(tree);
    eventTree = eventTree_construct2(flower); //creates the event tree and the root even
    totalEventNumber = 1;
    st_logInfo("Constructed the basic event tree\n");

    // Construct a set of outgroup names so that ancestral outgroups
    // get recognized.
    stSet *outgroupNameSet = stSet_construct3(stHash_stringKey,
                                              stHash_stringEqualKey,
                                              free);
    if(outgroupEvents != NULL) {
        stList *outgroupNames = stString_split(outgroupEvents);
        for(int64_t i = 0; i < stList_length(outgroupNames); i++) {
            char *outgroupName = stList_get(outgroupNames, i);
            stSet_insert(outgroupNameSet, stString_copy(outgroupName));
        }
        stList_destruct(outgroupNames);
    }

    //now traverse the tree
    j = optind;
    assignEventsAndSequences(eventTree_getRootEvent(eventTree), tree,
                             outgroupNameSet, argv, &j);

    char *eventTreeString = eventTree_makeNewickString(eventTree);
    st_logInfo(
            "Constructed the initial flower with %" PRIi64 " sequences and %" PRIi64 " events with string: %s\n",
            totalSequenceNumber, totalEventNumber, eventTreeString);
    assert(event_getSubTreeBranchLength(eventTree_getRootEvent(eventTree)) >= 0.0);
    free(eventTreeString);
    //assert(0);

    //////////////////////////////////////////////
    //Label any outgroup events.
    //////////////////////////////////////////////

    if (outgroupEvents != NULL) {
        stList *outgroupEventsList = stString_split(outgroupEvents);
        for (int64_t i = 0; i < stList_length(outgroupEventsList); i++) {
            char *outgroupEvent = makeEventHeadersAlphaNumeric ? makeAlphaNumeric(stList_get(outgroupEventsList, i)) : stString_copy(stList_get(outgroupEventsList, i));
            Event *event = eventTree_getEventByHeader(eventTree, outgroupEvent);
            if (event == NULL) {
                st_errAbort("Got an outgroup string that does not match an event, outgroup string %s", outgroupEvent);
            }
            assert(!event_isOutgroup(event));
            event_setOutgroupStatus(event, 1);
            assert(event_isOutgroup(event));
            free(outgroupEvent);
        }
        stList_destruct(outgroupEventsList);
    }

    //////////////////////////////////////////////
    //Construct the terminal group.
    //////////////////////////////////////////////

    if (flower_getEndNumber(flower) > 0) {
        group = group_construct2(flower);
        endIterator = flower_getEndIterator(flower);
        while ((end = flower_getNextEnd(endIterator)) != NULL) {
            end_setGroup(end, group);
        }
        flower_destructEndIterator(endIterator);
        assert(group_isLeaf(group));

        // Create a one link chain if there is only one pair of attached ends..
        group_constructChainForLink(group);
        assert(!flower_builtBlocks(flower));
    } else {
        flower_setBuiltBlocks(flower, 1);
    }

    ///////////////////////////////////////////////////////////////////////////
    // Write the flower to disk.
    ///////////////////////////////////////////////////////////////////////////

    //flower_check(flower);
    cactusDisk_write(cactusDisk);
    st_logInfo("Updated the flower on disk\n");

    ///////////////////////////////////////////////////////////////////////////
    // Cleanup.
    ///////////////////////////////////////////////////////////////////////////

    cactusDisk_destruct(cactusDisk);

    return 0; //Exit without clean up is quicker, enable cleanup when doing memory leak detection.

    stSet_destruct(outgroupNameSet);
    stTree_destruct(tree);
    stKVDatabaseConf_destruct(kvDatabaseConf);

    return 0;
}
void makeCactusTree_flower(Flower *flower, FILE *fileHandle, const char *parentNodeName,
        const char *parentEdgeColour) {
    if(flower_isTerminal(flower)) {
        makeCactusTree_terminalNode(flower, fileHandle, parentNodeName, parentEdgeColour);
    }
    else {
        //Write the flower nodes.
        char *flowerNameString = cactusMisc_nameToString(flower_getName(flower));
        const char *edgeColour = graphViz_getColour();
        addNodeToGraph(flowerNameString, fileHandle, flower_getTotalBaseLength(flower)
                / totalProblemSize, "ellipse", flowerNameString);
        //Write in the parent edge.
        if (parentNodeName != NULL) {
            graphViz_addEdgeToGraph(parentNodeName, flowerNameString, fileHandle, "",
                    parentEdgeColour, 10, 1, "forward");
        }
        //Create the chains.
        Flower_ChainIterator *chainIterator = flower_getChainIterator(flower);
        Chain *chain;
        while ((chain = flower_getNextChain(chainIterator)) != NULL) {
            makeCactusTree_chain(chain, fileHandle, flowerNameString, edgeColour);
        }
        flower_destructChainIterator(chainIterator);

        //Create the diamond node
        char *diamondNodeNameString = st_malloc(sizeof(char) * (strlen(
                flowerNameString) + 2));
        sprintf(diamondNodeNameString, "z%s", flowerNameString);
        const char *diamondEdgeColour = graphViz_getColour();
        //Create all the groups linked to the diamond.
        Flower_GroupIterator *groupIterator = flower_getGroupIterator(flower);
        Group *group;
        double size = 0.0; //get the size of the group organising node..
        int64_t nonTrivialGroupCount = 0;
        while ((group = flower_getNextGroup(groupIterator)) != NULL) {
            assert(!group_isLeaf(group));
            if (group_isTangle(group)) {
                size += group_getTotalBaseLength(group);
                nonTrivialGroupCount++;
            }
        }
        flower_destructGroupIterator(groupIterator);
        if(nonTrivialGroupCount == 0) {
            assert(flower_getParentGroup(flower) == 0);
        }
        else {
            //assert(nonTrivialGroupCount > 0);
            addNodeToGraph(diamondNodeNameString, fileHandle, size
                    / totalProblemSize, "diamond", "");
            graphViz_addEdgeToGraph(flowerNameString, diamondNodeNameString,
                    fileHandle, "", edgeColour, 10, 1, "forward");
            groupIterator = flower_getGroupIterator(flower);
            while ((group = flower_getNextGroup(groupIterator)) != NULL) {
                if (group_isTangle(group)) {
                    assert(!group_isLeaf(group));
                    makeCactusTree_flower(group_getNestedFlower(group), fileHandle,
                                                diamondNodeNameString, diamondEdgeColour);
                }
            }
            flower_destructGroupIterator(groupIterator);
        }

        free(flowerNameString);
        free(diamondNodeNameString);
    }
}
Example #15
0
void testFlower_removeIfRedundant(CuTest *testCase) {
    /*
     * Do a simple test to see if function can remove a redundant flower.
     */
    cactusFlowerTestSetup();
    endsSetup();

    //First construct a redundant flower from the root.
    Flower *flower2 = flower_construct(cactusDisk);
    Group *group = group_construct(flower, flower2);
    end_setGroup(end, group);
    end_setGroup(end2, group);

    //Now hang another couple of flowers of that.
    Flower *flower3 = flower_construct(cactusDisk);
    group_construct(flower2, flower3);

    //Now hang another flower of that.
    Group *group3b = group_construct2(flower2);

    //Finally hang one more flower on the end..
    Flower *flower4 = flower_construct(cactusDisk);
    group_construct(flower3, flower4);

    //Copy the ends into the flowers.
    end_copyConstruct(end, flower2);
    end_copyConstruct(end2, flower2);
    end_copyConstruct(end, flower3);
    end_setGroup(flower_getEnd(flower2, end_getName(end2)), group3b);
    end_copyConstruct(end, flower4);

    //st_uglyf("I got %" PRIi64 " %" PRIi64 " %" PRIi64 " %" PRIi64 "\n", flower_getName(flower), flower_getName(flower2), flower_getName(flower3), flower_getName(flower4));

    //Write the mess to disk.
    cactusDisk_write(cactusDisk);

    //Now test the removal function (check we get a negative on this leaf).
    CuAssertTrue(testCase, !flower_removeIfRedundant(flower4));
    //Check we can't remove the root..
    CuAssertTrue(testCase, !flower_removeIfRedundant(flower));

    //We will remove flower2

    //Before
    CuAssertTrue(testCase, flower_getGroupNumber(flower) == 1);
    CuAssertTrue(testCase, group_getFlower(flower_getParentGroup(flower2)) == flower);

    CuAssertTrue(testCase, flower_removeIfRedundant(flower2));

    //After, check the flower/group connections
    CuAssertTrue(testCase, flower_getGroupNumber(flower) == 2);
    CuAssertTrue(testCase, !flower_isLeaf(flower));
    CuAssertTrue(testCase, group_getFlower(flower_getParentGroup(flower3)) == flower);
    group3b = end_getGroup(end2);
    CuAssertTrue(testCase, group_getFlower(group3b) == flower);
    CuAssertTrue(testCase, group_isLeaf(group3b));
    CuAssertTrue(testCase, flower_getGroup(flower, flower_getName(flower3)) == flower_getParentGroup(flower3));
    //Check the ends..
    CuAssertTrue(testCase, flower_getEndNumber(flower) == 2);
    CuAssertTrue(testCase, flower_getEndNumber(flower3) == 1);
    CuAssertTrue(testCase, group_getEndNumber(group3b) == 1);
    CuAssertTrue(testCase, end_getGroup(end) == flower_getParentGroup(flower3));
    CuAssertTrue(testCase, end_getGroup(end2) == group3b);
    CuAssertTrue(testCase, flower_getEnd(flower3, end_getName(end)) != NULL);
    //Check the child of 3 is still okay..
    CuAssertTrue(testCase, group_getFlower(flower_getParentGroup(flower4)) == flower3);

    //Now do removal of flower3
    CuAssertTrue(testCase, !flower_removeIfRedundant(flower));
    CuAssertTrue(testCase, !flower_removeIfRedundant(flower4));
    CuAssertTrue(testCase, flower_removeIfRedundant(flower3));
    //Check groups again
    CuAssertTrue(testCase, flower_getGroupNumber(flower) == 2);
    CuAssertTrue(testCase, !flower_isLeaf(flower));
    CuAssertTrue(testCase, group_getFlower(flower_getParentGroup(flower4)) == flower);
    CuAssertTrue(testCase, group_getFlower(group3b) == flower);
    CuAssertTrue(testCase, flower_getGroup(flower, flower_getName(flower4)) == flower_getParentGroup(flower4));
    //Check the ends again..
    CuAssertTrue(testCase, flower_getEndNumber(flower) == 2);
    CuAssertTrue(testCase, flower_getEndNumber(flower4) == 1);
    CuAssertTrue(testCase, group_getEndNumber(group3b) == 1);
    CuAssertTrue(testCase, end_getGroup(end) == flower_getParentGroup(flower4));
    CuAssertTrue(testCase, end_getGroup(end2) == group3b);
    CuAssertTrue(testCase, flower_getEnd(flower4, end_getName(end)) != NULL);

    cactusFlowerTestTeardown();
}
int main(int argc, char *argv[]) {
    /*
     * Script for adding a reference genome to a flower.
     */

    /*
     * Arguments/options
     */
    char * logLevelString = NULL;
    char * cactusDiskDatabaseString = NULL;
    char * secondaryDatabaseString = NULL;
    char *referenceEventString = (char *) cactusMisc_getDefaultReferenceEventHeader();
    bool bottomUpPhase = 0;

    ///////////////////////////////////////////////////////////////////////////
    // (0) Parse the inputs handed by genomeCactus.py / setup stuff.
    ///////////////////////////////////////////////////////////////////////////

    while (1) {
        static struct option long_options[] = { { "logLevel", required_argument, 0, 'a' }, { "cactusDisk", required_argument, 0, 'b' }, { "secondaryDisk", required_argument, 0, 'd' }, { "referenceEventString", required_argument, 0, 'g' }, { "help", no_argument,
                0, 'h' }, { "bottomUpPhase", no_argument, 0, 'j' }, { 0, 0, 0, 0 } };

        int option_index = 0;

        int key = getopt_long(argc, argv, "a:b:c:d:e:g:hi:j", long_options, &option_index);

        if (key == -1) {
            break;
        }

        switch (key) {
            case 'a':
                logLevelString = stString_copy(optarg);
                break;
            case 'b':
                cactusDiskDatabaseString = stString_copy(optarg);
                break;
            case 'd':
                secondaryDatabaseString = stString_copy(optarg);
                break;
            case 'g':
                referenceEventString = stString_copy(optarg);
                break;
            case 'h':
                usage();
                return 0;
            case 'j':
                bottomUpPhase = 1;
                break;
            default:
                usage();
                return 1;
        }
    }

    ///////////////////////////////////////////////////////////////////////////
    // (0) Check the inputs.
    ///////////////////////////////////////////////////////////////////////////

    assert(cactusDiskDatabaseString != NULL);

    //////////////////////////////////////////////
    //Set up logging
    //////////////////////////////////////////////

    st_setLogLevelFromString(logLevelString);

    //////////////////////////////////////////////
    //Load the database
    //////////////////////////////////////////////

    st_logInfo("referenceEventString = %s\n", referenceEventString);
    st_logInfo("bottomUpPhase = %i\n", bottomUpPhase);

    stKVDatabaseConf *kvDatabaseConf = stKVDatabaseConf_constructFromString(cactusDiskDatabaseString);
    CactusDisk *cactusDisk = cactusDisk_construct(kvDatabaseConf, false, true);
    stKVDatabaseConf_destruct(kvDatabaseConf);
    st_logInfo("Set up the flower disk\n");

    stKVDatabase *sequenceDatabase = NULL;
    if (secondaryDatabaseString != NULL) {
        kvDatabaseConf = stKVDatabaseConf_constructFromString(secondaryDatabaseString);
        sequenceDatabase = stKVDatabase_construct(kvDatabaseConf, 0);
        stKVDatabaseConf_destruct(kvDatabaseConf);
    }

    FlowerStream *flowerStream = flowerWriter_getFlowerStream(cactusDisk, stdin);
    Flower *flower;
    while ((flower = flowerStream_getNext(flowerStream)) != NULL) {
        st_logDebug("Processing flower %" PRIi64 "\n", flower_getName(flower));

        ///////////////////////////////////////////////////////////////////////////
        // Get the appropriate event names
        ///////////////////////////////////////////////////////////////////////////

        st_logInfo("%s\n", eventTree_makeNewickString(flower_getEventTree(flower)));
        Event *referenceEvent = eventTree_getEventByHeader(flower_getEventTree(flower), referenceEventString);
        if (referenceEvent == NULL) {
            st_errAbort("Reference event %s not found in tree. Check your "
                        "--referenceEventString option", referenceEventString);
        }
        Name referenceEventName = event_getName(referenceEvent);

        ///////////////////////////////////////////////////////////////////////////
        // Now do bottom up or top down, depending
        ///////////////////////////////////////////////////////////////////////////
        stList *flowers = stList_construct();
        stList_append(flowers, flower);
        preCacheNestedFlowers(cactusDisk, flowers);
        if (bottomUpPhase) {
            assert(sequenceDatabase != NULL);

            cactusDisk_preCacheSegmentStrings(cactusDisk, flowers);
            bottomUp(flowers, sequenceDatabase, referenceEventName, !flower_hasParentGroup(flower), generateJukesCantorMatrix);

            // Unload the nested flowers to save memory. They haven't
            // been changed, so we don't write them to the cactus
            // disk.
            Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
            Group *group;
            while ((group = flower_getNextGroup(groupIt)) != NULL) {
                if (!group_isLeaf(group)) {
                    flower_unload(group_getNestedFlower(group));
                }
            }
            flower_destructGroupIterator(groupIt);
            assert(!flower_isParentLoaded(flower));

            // Write this flower to disk.
            cactusDisk_addUpdateRequest(cactusDisk, flower);
        } else {
            topDown(flower, referenceEventName);

            // We've changed the nested flowers, but not this
            // flower. We write the nested flowers to disk, then
            // unload them to save memory. This flower will be
            // unloaded by the flower-stream code.
            Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
            Group *group;
            while ((group = flower_getNextGroup(groupIt)) != NULL) {
                if (!group_isLeaf(group)) {
                    cactusDisk_addUpdateRequest(cactusDisk, group_getNestedFlower(group));
                    flower_unload(group_getNestedFlower(group));
                }
            }
            flower_destructGroupIterator(groupIt);
        }
        stList_destruct(flowers);
    }

    ///////////////////////////////////////////////////////////////////////////
    // Write the flower(s) back to disk.
    ///////////////////////////////////////////////////////////////////////////

    cactusDisk_write(cactusDisk);
    st_logInfo("Updated the flower on disk\n");

    ///////////////////////////////////////////////////////////////////////////
    //Clean up.
    ///////////////////////////////////////////////////////////////////////////

    if (sequenceDatabase != NULL) {
        stKVDatabase_destruct(sequenceDatabase);
    }

    cactusDisk_destruct(cactusDisk);

    return 0; //Exit without clean up is quicker, enable cleanup when doing memory leak detection.

    free(cactusDiskDatabaseString);
    free(referenceEventString);
    free(logLevelString);

    st_logInfo("Cleaned stuff up and am finished\n");

    return 0;
}