Esempio n. 1
0
static void sequenceSetup() {
    metaSequence = metaSequence_construct(0, 10, "ACTGACTGAC", ">one",
            event_getName(eventTree_getRootEvent(eventTree)), cactusDisk);
    sequence = sequence_construct(metaSequence, flower);
    metaSequence2 = metaSequence_construct(0, 10, "ACTGACTGAC", ">two",
            event_getName(eventTree_getRootEvent(eventTree)), cactusDisk);
    sequence2 = sequence_construct(metaSequence2, flower);
}
Esempio n. 2
0
void testEventTree_getEvent(CuTest* testCase) {
	cactusEventTreeTestSetup();
	CuAssertTrue(testCase, eventTree_getEvent(eventTree, event_getName(rootEvent)) == rootEvent);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree, event_getName(internalEvent)) == internalEvent);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree, event_getName(leafEvent1)) == leafEvent1);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree, event_getName(leafEvent2)) == leafEvent2);
	cactusEventTreeTestTeardown();
}
Esempio n. 3
0
void testEvent_getName(CuTest* testCase) {
	cactusEventTestSetup();
	CuAssertTrue(testCase, event_getName(rootEvent) != NULL_NAME);
	CuAssertTrue(testCase, event_getName(internalEvent) != NULL_NAME);
	CuAssertTrue(testCase, event_getName(leafEvent1) != NULL_NAME);
	CuAssertTrue(testCase, event_getName(leafEvent2) != NULL_NAME);
	cactusEventTestTeardown();
}
Esempio n. 4
0
void testEnd_getCapForEvent(CuTest* testCase) {
    cactusEndTestSetup();

    CuAssertPtrEquals(testCase, end_getCapForEvent(end_getReverse(end), event_getName(rootEvent)), rootCap);
    Cap *cap = end_getCapForEvent(end, event_getName(leafEvent));
    CuAssertTrue(testCase, cap == cap_getReverse(leaf1Cap) || cap == leaf2Cap || cap == cap_getReverse(leaf3Cap));
    CuAssertTrue(testCase, end_getCapForEvent(end, NULL_NAME) == NULL);

    cactusEndTestTeardown();
}
Esempio n. 5
0
void event_writeBinaryRepresentation(Event *event, void(*writeFn)(
        const void * ptr, size_t size, size_t count)) {
    binaryRepresentation_writeElementType(CODE_EVENT, writeFn);
    binaryRepresentation_writeName(event_getName(event_getParent(event)),
            writeFn);
    binaryRepresentation_writeName(event_getName(event), writeFn);
    binaryRepresentation_writeFloat(event_getBranchLength(event), writeFn);
    binaryRepresentation_writeString(event_getHeader(event), writeFn);
    binaryRepresentation_writeBool(event_isOutgroup(event), writeFn);
}
Esempio n. 6
0
void testBlock_getSegmentForEvent(CuTest* testCase) {
    cactusBlockTestSetup();

    CuAssertPtrEquals(testCase, block_getSegmentForEvent(block_getReverse(block), event_getName(rootEvent)), rootSegment);
    Segment *segment = block_getSegmentForEvent(block, event_getName(leafEvent));
    CuAssertTrue(testCase, segment == leaf1Segment || segment == segment_getReverse(leaf2Segment));
    CuAssertTrue(testCase, block_getSegmentForEvent(block, NULL_NAME) == NULL);

    cactusBlockTestTeardown();
}
Esempio n. 7
0
void testEventTree_copyConstruct(CuTest* testCase) {
	cactusEventTreeTestSetup();
	Flower *flower2 = flower_construct(cactusDisk);
	EventTree *eventTree2 = eventTree_copyConstruct(eventTree, flower2, unaryEventFunction);
	CuAssertIntEquals(testCase, eventTree_getEventNumber(eventTree), eventTree_getEventNumber(eventTree2));
	CuAssertTrue(testCase, event_getName(eventTree_getEvent(eventTree2, event_getName(rootEvent))) == event_getName(rootEvent));
	CuAssertTrue(testCase, event_getName(eventTree_getEvent(eventTree2, event_getName(internalEvent))) == event_getName(internalEvent));
	CuAssertTrue(testCase, event_getName(eventTree_getEvent(eventTree2, event_getName(leafEvent1))) == event_getName(leafEvent1));
	CuAssertTrue(testCase, event_getName(eventTree_getEvent(eventTree2, event_getName(leafEvent2))) == event_getName(leafEvent2));
	CuAssertTrue(testCase, event_isOutgroup(eventTree_getEvent(eventTree2, event_getName(leafEvent1))));
	CuAssertTrue(testCase, !event_isOutgroup(eventTree_getEvent(eventTree2, event_getName(leafEvent2))));
	cactusEventTreeTestTeardown();
}
Esempio n. 8
0
void sequence_check(Sequence *sequence) {
	Flower *flower = sequence_getFlower(sequence);
	cactusCheck(flower_getSequence(flower, sequence_getName(sequence)) == sequence); //properly connected to the flower..

	Group *parentGroup = flower_getParentGroup(flower);
	if(parentGroup != NULL) {
		Flower *parentFlower = group_getFlower(parentGroup);
		Sequence *parentSequence = flower_getSequence(parentFlower, sequence_getName(sequence));
		if(parentSequence != NULL) {
			cactusCheck(event_getName(sequence_getEvent(sequence)) == event_getName(sequence_getEvent(parentSequence)));
		}
	}
}
Esempio n. 9
0
void eventTree_copyConstructP(EventTree *eventTree, Event *event,
		int64_t (unaryEventFilterFn)(Event *event)) {
	int64_t i;
	Event *event2;
	for(i=0; i<event_getChildNumber(event); i++) {
		event2 = event_getChild(event, i);
		while(event_getChildNumber(event2) == 1 && unaryEventFilterFn != NULL && !unaryEventFilterFn(event2)) {
			//skip the event
			event2 = event_getChild(event2, 0);
		}
		event_setOutgroupStatus(event_construct(event_getName(event2), event_getHeader(event2), event_getBranchLength(event2),
						eventTree_getEvent(eventTree, event_getName(event)), eventTree), event_isOutgroup(event2));
		eventTree_copyConstructP(eventTree, event2, unaryEventFilterFn);
	}
}
Esempio n. 10
0
void event_check(Event *event) {
    EventTree *eventTree = event_getEventTree(event);
    Event *ancestorEvent = event_getParent(event);

    //Check event and eventree properly linked
    cactusCheck(eventTree_getEvent(event_getEventTree(event), event_getName(event)) == event);

    //Event has parent, unless it is root.
    if (eventTree_getRootEvent(eventTree) == event) {
        cactusCheck(ancestorEvent == NULL);
    } else { //not root, so must have ancestor.
        cactusCheck(ancestorEvent != NULL);
    }

    //Each child event has event as parent.
    int64_t i = 0;
    for (i = 0; i < event_getChildNumber(event); i++) {
        Event *childEvent = event_getChild(event, i);
        cactusCheck(event_getParent(childEvent) == event);
    }

    //Ancestor-event --> event edge is consistent with any event tree that is in the parent of the containing flower.
    Group *parentGroup = flower_getParentGroup(eventTree_getFlower(
            event_getEventTree(event)));
    if (parentGroup != NULL) {
        EventTree *parentEventTree = flower_getEventTree(group_getFlower(
                parentGroup));
        Event *parentEvent = eventTree_getEvent(parentEventTree, event_getName(
                event));
        if (parentEvent != NULL) {
            if (ancestorEvent == NULL) { //the case where they are both root.
                cactusCheck(eventTree_getRootEvent(parentEventTree) == parentEvent);
            } else {
                //Check edge ancestorEvent --> event is in parent event tree.
                while (1) {
                    Event *parentAncestorEvent = eventTree_getEvent(
                            parentEventTree, event_getName(ancestorEvent));
                    if (parentAncestorEvent != NULL) {
                        cactusCheck(event_isAncestor(parentEvent, parentAncestorEvent));
                        break;
                    }
                    ancestorEvent = event_getParent(ancestorEvent);
                    cactusCheck(ancestorEvent != NULL);
                }
            }
        }
    }
}
Esempio n. 11
0
EventTree *eventTree_copyConstruct(EventTree *eventTree, int64_t (unaryEventFilterFn)(Event *event)) {
	EventTree *eventTree2;
	eventTree2 = eventTree_construct(eventTree_getCactusDisk(eventTree),
                                         event_getName(eventTree_getRootEvent(eventTree)));
	eventTree_copyConstructP(eventTree2, eventTree_getRootEvent(eventTree), unaryEventFilterFn);
	return eventTree2;
}
Esempio n. 12
0
static stTree *eventTree_getStTree_R(Event *event) {
    stTree *ret = stTree_construct();
    stTree_setLabel(ret, stString_print("%" PRIi64, event_getName(event)));
    stTree_setBranchLength(ret, event_getBranchLength(event));
    for(int64_t i = 0; i < event_getChildNumber(event); i++) {
        Event *child = event_getChild(event, i);
        stTree *childStTree = eventTree_getStTree_R(child);
        stTree_setParent(childStTree, ret);
    }
    return ret;
}
Esempio n. 13
0
void eventTree_writeBinaryRepresentation(EventTree *eventTree, void (*writeFn)(const void * ptr, size_t size, size_t count)) {
	int64_t i;
	Event *event;
	event = eventTree_getRootEvent(eventTree);
	binaryRepresentation_writeElementType(CODE_EVENT_TREE, writeFn);
	binaryRepresentation_writeName(event_getName(event), writeFn);
	for(i=0; i<event_getChildNumber(event); i++) {
		eventTree_writeBinaryRepresentationP(event_getChild(event, i), writeFn);
	}
	binaryRepresentation_writeElementType(CODE_EVENT_TREE, writeFn);
}
static MetaSequence *addMetaSequence(Flower *flower, Cap *cap, int64_t index, char *string, bool trivialString) {
    /*
     * Adds a meta sequence representing a top level thread to the cactus disk.
     * The sequence is all 'N's at this stage.
     */
    Event *referenceEvent = cap_getEvent(cap);
    assert(referenceEvent != NULL);
    char *sequenceName = stString_print("%srefChr%" PRIi64 "", event_getHeader(referenceEvent), index);
    //char *sequenceName = stString_print("refChr%" PRIi64 "", index);
    MetaSequence *metaSequence = metaSequence_construct3(1, strlen(string), string, sequenceName,
            event_getName(referenceEvent), trivialString, flower_getCactusDisk(flower));
    free(sequenceName);
    return metaSequence;
}
Esempio n. 15
0
Segment *block_getSegmentForEvent(Block *block, Name eventName) {
    /*
     * Get the segment for a given event.
     */
    Block_InstanceIterator *it = block_getInstanceIterator(block);
    Segment *segment;
    while ((segment = block_getNext(it)) != NULL) {
        if (event_getName(segment_getEvent(segment)) == eventName) {
            block_destructInstanceIterator(it);
            return segment;
        }
    }
    block_destructInstanceIterator(it);
    return NULL;
}
Cap *getCapForReferenceEvent(End *end, Name referenceEventName) {
    /*
     * Get the cap for a given event.
     */
    End_InstanceIterator *it = end_getInstanceIterator(end);
    Cap *cap;
    while ((cap = end_getNext(it)) != NULL) {
        if (event_getName(cap_getEvent(cap)) == referenceEventName) {
            end_destructInstanceIterator(it);
            return cap;
        }
    }
    end_destructInstanceIterator(it);
    //assert(0);
    return NULL;
}
Esempio n. 17
0
void processSequence(const char *fastaHeader, const char *string, int64_t length) {
    /*
     * Processes a sequence by adding it to the flower disk.
     */
    End *end1;
    End *end2;
    Cap *cap1;
    Cap *cap2;
    MetaSequence *metaSequence;
    Sequence *sequence;

    //Now put the details in a flower.
    metaSequence = metaSequence_construct(2, length, string, fastaHeader, event_getName(event), cactusDisk);
    sequence = sequence_construct(metaSequence, flower);

    end1 = end_construct2(0, isComplete, flower);
    end2 = end_construct2(1, isComplete, flower);
    cap1 = cap_construct2(end1, 1, 1, sequence);
    cap2 = cap_construct2(end2, length + 2, 1, sequence);
    cap_makeAdjacent(cap1, cap2);
    totalSequenceNumber++;
}
Esempio n. 18
0
int eventTree_constructP(const void *o1, const void *o2) {
	return cactusMisc_nameCompare(event_getName((Event *)o1), event_getName((Event *)o2));
}
Esempio n. 19
0
void testEventTree_addSiblingUnaryEvent(CuTest *testCase) {
	cactusEventTreeTestSetup();
	//Create two sibling flowers with the basic event tree..
	//then try adding events from on into the other.
	Group *group1 = group_construct2(flower);
	Group *group2 = group_construct2(flower);
	Flower *flower2 = flower_construct(cactusDisk);
	Flower *flower3 = flower_construct(cactusDisk);
	flower_setParentGroup(flower2, group1);
	flower_setParentGroup(flower3, group2);
	EventTree *eventTree2 = eventTree_copyConstruct(flower_getEventTree(flower), flower2, NULL);
	Event *parentUnaryEvent1 = event_construct4("UNARY1", 0.1, internalEvent, leafEvent1, eventTree);
	Event *parentUnaryEvent2 = event_construct4("UNARY2", 0.1, parentUnaryEvent1, leafEvent1, eventTree);
	Event *parentUnaryEvent3 = event_construct4("UNARY3", 0.1, internalEvent, leafEvent2, eventTree);
	//now event tree contains the added unary events.
	EventTree *eventTree3 = eventTree_copyConstruct(flower_getEventTree(flower), flower3, NULL);
	//add a couple of denovo events into the new event tree
	Event *internalEventChild = eventTree_getEvent(eventTree3, event_getName(internalEvent));
	Event *unaryEvent1 = eventTree_getEvent(eventTree3, event_getName(parentUnaryEvent1));
	Event *unaryEvent2 = eventTree_getEvent(eventTree3, event_getName(parentUnaryEvent2));
	Event *unaryEvent3 = eventTree_getEvent(eventTree3, event_getName(parentUnaryEvent3));
	Event *unaryEvent4 = event_construct4("UNARY4", 0.1,
			internalEventChild, unaryEvent3, eventTree3);
	Event *unaryEvent5 = event_construct4("UNARY5", 0.1,
				internalEventChild, unaryEvent4, eventTree3);
	//Now event-tree 2 does not contain the unary events but event-tree 3 does..

	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent1)) == NULL);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent2)) == NULL);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent3)) == NULL);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent4)) == NULL);
	CuAssertTrue(testCase, eventTree_getEvent(eventTree2, event_getName(unaryEvent5)) == NULL);

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent1);
	Event *unaryEvent12 = eventTree_getEvent(eventTree2, event_getName(unaryEvent1));
	CuAssertTrue(testCase, unaryEvent12 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent12)) == event_getName(internalEvent));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent12) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent12, 0)) == event_getName(leafEvent1));

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent2);
	Event *unaryEvent22 = eventTree_getEvent(eventTree2, event_getName(unaryEvent2));
	CuAssertTrue(testCase, unaryEvent22 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent22)) == event_getName(unaryEvent1));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent22) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent22, 0)) == event_getName(leafEvent1));

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent3);
	Event *unaryEvent32 = eventTree_getEvent(eventTree2, event_getName(unaryEvent3));
	CuAssertTrue(testCase, unaryEvent32 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent32)) == event_getName(internalEvent));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent32) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent32, 0)) == event_getName(leafEvent2));

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent4);
	Event *unaryEvent42 = eventTree_getEvent(eventTree2, event_getName(unaryEvent4));
	CuAssertTrue(testCase, unaryEvent42 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent42)) == event_getName(internalEvent));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent42) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent42, 0)) == event_getName(unaryEvent3));

	eventTree_addSiblingUnaryEvent(eventTree2, unaryEvent5);
	Event *unaryEvent52 = eventTree_getEvent(eventTree2, event_getName(unaryEvent5));
	CuAssertTrue(testCase, unaryEvent52 != NULL);
	CuAssertTrue(testCase, event_getName(event_getParent(unaryEvent52)) == event_getName(internalEvent));
	CuAssertTrue(testCase, event_getChildNumber(unaryEvent52) == 1);
	CuAssertTrue(testCase, event_getName(event_getChild(unaryEvent52, 0)) == event_getName(unaryEvent4));

	//uglyf("Event-tree-1 %s\n", eventTree_makeNewickString(eventTree));
	//uglyf("Event-tree-2 %s\n", eventTree_makeNewickString(eventTree3));
	//uglyf("Event-tree-3 %s\n", eventTree_makeNewickString(eventTree2));

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

    /*
     * Arguments/options
     */
    char * logLevelString = NULL;
    char * cactusDiskDatabaseString = NULL;
    char *referenceEventString =
            (char *) cactusMisc_getDefaultReferenceEventHeader();
    char *outputFile = NULL;
    Name flowerName = NULL_NAME;

    ///////////////////////////////////////////////////////////////////////////
    // (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, 'c' },  { "flowerName", required_argument,
                        0, 'd' },
                { "referenceEventString", required_argument, 0, 'g' }, {
                        "help", no_argument, 0, 'h' }, { "outputFile",
                        required_argument, 0, 'k' },
                { 0, 0, 0, 0 } };

        int option_index = 0;

        int key = getopt_long(argc, argv, "a:c:d:g:hk:", long_options,
                &option_index);

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

        switch (key) {
            case 'a':
                logLevelString = stString_copy(optarg);
                break;
            case 'c':
                cactusDiskDatabaseString = stString_copy(optarg);
                break;
            case 'd':
                flowerName = cactusMisc_stringToName(optarg);
                break;
            case 'g':
                referenceEventString = stString_copy(optarg);
                break;
            case 'h':
                usage();
                return 0;
            case 'k':
                outputFile = stString_copy(optarg);
                break;
            default:
                usage();
                return 1;
        }
    }

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

    assert(cactusDiskDatabaseString != NULL);

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

    st_setLogLevelFromString(logLevelString);

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

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


    ///////////////////////////////////////////////////////////////////////////
    // Get the set of flowers to manipulate
    ///////////////////////////////////////////////////////////////////////////

    Flower *flower = cactusDisk_getFlower(cactusDisk, flowerName);

    ///////////////////////////////////////////////////////////////////////////
    // Get the reference event name
    ///////////////////////////////////////////////////////////////////////////

    Event *referenceEvent = eventTree_getEventByHeader(
            flower_getEventTree(flower), referenceEventString);
    assert(referenceEvent != NULL);
    Name referenceEventName = event_getName(referenceEvent);

    ///////////////////////////////////////////////////////////////////////////
    // Now process each flower in turn.
    ///////////////////////////////////////////////////////////////////////////
    
    if(outputFile == NULL) {
        st_errAbort("No output file specified\n");
    }
    FILE *fileHandle = fopen(outputFile, "w");
    printFastaSequences(flower, fileHandle, referenceEventName);
    if(fileHandle != NULL) {
        fclose(fileHandle);
    }

    ///////////////////////////////////////////////////////////////////////////
    //Clean up memory
    ///////////////////////////////////////////////////////////////////////////

    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");
    //while(1);
    return 0;
}
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;
}