Exemple #1
0
static void getMetaSequencesForEventsP(stSortedSet *metaSequences,
        Flower *flower, stList *eventStrings) {
    //Iterate over the sequences in the flower.
    Flower_SequenceIterator *seqIt = flower_getSequenceIterator(flower);
    Sequence *sequence;
    while ((sequence = flower_getNextSequence(seqIt)) != NULL) {
        MetaSequence *metaSequence = sequence_getMetaSequence(sequence);
        if (stringIsInList(event_getHeader(sequence_getEvent(sequence)),
                eventStrings) == 0) {
            if (stSortedSet_search(metaSequences, metaSequence) == NULL) {
                stSortedSet_insert(metaSequences, metaSequence);
            }
        }
    }
    flower_destructSequenceIterator(seqIt);
    //Recurse over the flowers
    Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
    Group *group;
    while ((group = flower_getNextGroup(groupIt)) != NULL) {
        if (group_getNestedFlower(group) != NULL) {
            getMetaSequencesForEventsP(metaSequences,
                    group_getNestedFlower(group), eventStrings);
        }
    }
    flower_destructGroupIterator(groupIt);
}
static void getMaximalHaplotypePathsCheck(Flower *flower,
        stSortedSet *segmentSet, const char *eventString, stList *eventStrings) {
    /*
     * Do debug checks that the haplotypes paths are well formed.
     */
    Flower_SegmentIterator *segmentIt = flower_getSegmentIterator(flower);
    Segment *segment;
    while ((segment = flower_getNextSegment(segmentIt)) != NULL) {
        if (strcmp(event_getHeader(segment_getEvent(segment)), eventString) == 0) {
            if (hasCapInEvents(cap_getEnd(segment_get5Cap(segment)), eventStrings)) { //isHaplotypeEnd(cap_getEnd(segment_get5Cap(segment)))) {
                assert(stSortedSet_search(segmentSet, segment) != NULL
                        || stSortedSet_search(segmentSet, segment_getReverse(
                                segment)) != NULL);
            }
        }
    }
    flower_destructSegmentIterator(segmentIt);

    Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
    Group *group;
    while ((group = flower_getNextGroup(groupIt)) != NULL) {
        if (group_getNestedFlower(group) != NULL) {
            getMaximalHaplotypePathsCheck(group_getNestedFlower(group),
                    segmentSet, eventString, eventStrings);
        }
    }
    flower_destructGroupIterator(groupIt);
}
static void recoverBrokenAdjacencies(Flower *flower, stList *recoveredCaps, Name referenceEventName) {
    /*
     * Find reference intervals that are book-ended by stubs created in a child flower.
     */
    Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
    Group *group;
    while((group = flower_getNextGroup(groupIt)) != NULL) {
        Flower *nestedFlower;
        if((nestedFlower = group_getNestedFlower(group)) != NULL) {
            Flower_EndIterator *endIt = flower_getEndIterator(nestedFlower);
            End *childEnd;
            while((childEnd = flower_getNextEnd(endIt)) != NULL) {
                if(end_isStubEnd(childEnd) && flower_getEnd(flower, end_getName(childEnd)) == NULL) { //We have a thread we need to promote
                    Cap *childCap = getCapForReferenceEvent(childEnd, referenceEventName); //The cap in the reference
                    assert(childCap != NULL);
                    assert(!end_isAttached(childEnd));
                    childCap = cap_getStrand(childCap) ? childCap : cap_getReverse(childCap);
                    if (!cap_getSide(childCap)) {
                        Cap *adjacentChildCap = NULL;
                        int64_t adjacencyLength = traceThreadLength(childCap, &adjacentChildCap);
                        Cap *cap = copyCapToParent(childCap, recoveredCaps);
                        assert(adjacentChildCap != NULL);
                        assert(!end_isAttached(cap_getEnd(adjacentChildCap)));
                        assert(!cap_getSide(cap));
                        Cap *adjacentCap = copyCapToParent(adjacentChildCap, recoveredCaps);
                        cap_makeAdjacent(cap, adjacentCap);
                        setAdjacencyLength(cap, adjacentCap, adjacencyLength);
                    }
                }
            }
            flower_destructEndIterator(endIt);
        }
    }
    flower_destructGroupIterator(groupIt);
}
void testGroup_serialisation(CuTest* testCase) {
    cactusGroupTestSetup();
    int64_t i;
    Name name = group_getName(group);
    void
            *vA =
                    binaryRepresentation_makeBinaryRepresentation(group,
                            (void(*)(void *, void(*)(const void *, size_t,
                                    size_t))) group_writeBinaryRepresentation,
                            &i);
    CuAssertTrue(testCase, i > 0);
    group_destruct(group);
    void *vA2 = vA;
    group = group_loadFromBinaryRepresentation(&vA2, flower);
    free(vA);
    CuAssertTrue(testCase, group_getName(group) == name);
    CuAssertTrue(testCase, group_getFlower(group) == flower);
    CuAssertTrue(testCase, group_getNestedFlower(group) == nestedFlower);
    Group_EndIterator *iterator = group_getEndIterator(group);
    CuAssertTrue(testCase, group_getNextEnd(iterator) == end1);
    CuAssertTrue(testCase, group_getNextEnd(iterator) == end2);
    CuAssertTrue(testCase, group_getNextEnd(iterator) == NULL);
    group_destructEndIterator(iterator);

    cactusGroupTestTeardown();
}
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);
}
Exemple #6
0
void flower_destruct(Flower *flower, int64_t recursive) {
    Flower_GroupIterator *iterator;
    Sequence *sequence;
    End *end;
    Block *block;
    Group *group;
    Chain *chain;
    Flower *nestedFlower;

    if (recursive) {
        iterator = flower_getGroupIterator(flower);
        while ((group = flower_getNextGroup(iterator)) != NULL) {
            nestedFlower = group_getNestedFlower(group);
            if (nestedFlower != NULL) {
                flower_destruct(nestedFlower, recursive);
            }
        }
        flower_destructGroupIterator(iterator);
    }

    cactusDisk_removeFlower(flower->cactusDisk, flower);

    flower_destructFaces(flower);
    stSortedSet_destruct(flower->faces);

    assert(flower_getEventTree(flower) != NULL);
    eventTree_destruct(flower_getEventTree(flower));

    while ((sequence = flower_getFirstSequence(flower)) != NULL) {
        sequence_destruct(sequence);
    }
    stSortedSet_destruct(flower->sequences);

    while ((chain = flower_getFirstChain(flower)) != NULL) {
        chain_destruct(chain);
    }
    stSortedSet_destruct(flower->chains);

    while ((end = flower_getFirstEnd(flower)) != NULL) {
        end_destruct(end);
    }
    stSortedSet_destruct(flower->caps);
    stSortedSet_destruct(flower->ends);

    while ((block = flower_getFirstBlock(flower)) != NULL) {
        block_destruct(block);
    }
    stSortedSet_destruct(flower->segments);
    stSortedSet_destruct(flower->blocks);

    while ((group = flower_getFirstGroup(flower)) != NULL) {
        group_destruct(group);
    }
    stSortedSet_destruct(flower->groups);

    free(flower);
}
Cap *getTerminalCap(Cap *cap) {
    Flower *nestedFlower = group_getNestedFlower(end_getGroup(cap_getEnd(cap)));
    if (nestedFlower != NULL) {
        Cap *nestedCap = flower_getCap(nestedFlower, cap_getName(cap));
        assert(nestedCap != NULL);
        return getTerminalCap(cap_getOrientation(cap) ? nestedCap : cap_getReverse(nestedCap));
    }
    return cap;
}
Exemple #8
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);
}
static void getMaximalHaplotypePathsP(Flower *flower,
        stList *maximalHaplotypePaths, stSortedSet *segmentSet,
        const char *eventString,
        stList *eventStrings) {
    /*
     *  Iterate through the segments in this flower.
     */
    Flower_SegmentIterator *segmentIt = flower_getSegmentIterator(flower);
    Segment *segment;
    while ((segment = flower_getNextSegment(segmentIt)) != NULL) {
        if (stSortedSet_search(segmentSet, segment) == NULL
                && stSortedSet_search(segmentSet, segment_getReverse(segment))
                        == NULL) { //Check we haven't yet seen this segment
            if (strcmp(event_getHeader(segment_getEvent(segment)), eventString)
                    == 0) { //Check if the segment is in the assembly
                if (hasCapInEvents(cap_getEnd(segment_get5Cap(segment)), eventStrings)) { //Is a block in a haplotype segment
                    assert(hasCapInEvents(cap_getEnd(segment_get3Cap(segment)), eventStrings)); //isHaplotypeEnd(cap_getEnd(segment_get3Cap(segment))));
                    stList *maximalHaplotypePath = stList_construct();
                    stList_append(maximalHaplotypePaths, maximalHaplotypePath);
                    getMaximalHaplotypePathsP2(segment, maximalHaplotypePath,
                            segmentSet, eventStrings);
                } else {
                    assert(!hasCapInEvents(cap_getEnd(segment_get3Cap(segment)), eventStrings));//assert(!isHaplotypeEnd(cap_getEnd(segment_get3Cap(segment))));
                }
            }
        }
    }
    flower_destructSegmentIterator(segmentIt);
    /*
     * Now recurse on the contained flowers.
     */
    Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
    Group *group;
    while ((group = flower_getNextGroup(groupIt)) != NULL) {
        if (group_getNestedFlower(group) != NULL) {
            getMaximalHaplotypePathsP(group_getNestedFlower(group),
                    maximalHaplotypePaths, segmentSet, eventString, eventStrings);
        }
    }
    flower_destructGroupIterator(groupIt);
}
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;
        }
    }
}
Exemple #11
0
static void getOrderedSegmentsP(Flower *flower,
        stSortedSet *segments) {
    Flower_SegmentIterator *segmentIt = flower_getSegmentIterator(flower);
    Segment *segment;
    while ((segment = flower_getNextSegment(segmentIt)) != NULL) {
            if (!segment_getStrand(segment)) {
                segment = segment_getReverse(segment);
            }
            assert(stSortedSet_search(segments, segment) == NULL);
            stSortedSet_insert(segments, segment);
    }
    flower_destructSegmentIterator(segmentIt);
    //Recurse over the flowers
    Flower_GroupIterator *groupIt = flower_getGroupIterator(flower);
    Group *group;
    while ((group = flower_getNextGroup(groupIt)) != NULL) {
        if (group_getNestedFlower(group) != NULL) {
            getOrderedSegmentsP(group_getNestedFlower(group),
                    segments);
        }
    }
    flower_destructGroupIterator(groupIt);
}
Exemple #12
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;
}
Exemple #13
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);
}
Exemple #14
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);
}
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();
}
Exemple #16
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);
}
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;
}
void testGroup_getNestedFlower(CuTest* testCase) {
    cactusGroupTestSetup();
    CuAssertTrue(testCase, group_getNestedFlower(group) == nestedFlower);
    cactusGroupTestTeardown();
}
int mapGene(Cap *cap, int level, int exon, struct bed *gene, FILE *fileHandle){
   /*
    *Following cactus adjacencies, starting from 'cap', find regions that overlap with 
    *exons of input gene. Report chain relations of these regions with the exons.
    *cap: current cap. Level = chain level. exon = exon number. gene = bed record of gene
    */
   int64_t exonStart, exonEnd;
   if(isStubCap(cap)){
      Group *group = end_getGroup(cap_getEnd(cap));
      Flower *nestedFlower = group_getNestedFlower(group);
      if(nestedFlower != NULL){//recursive call
         Cap *childCap = flower_getCap(nestedFlower, cap_getName(cap));
         assert(childCap != NULL);
         exon = mapGene(childCap, level + 1, exon, gene, fileHandle);
         exonStart = gene->chromStarts->list[exon] + gene->chromStart;
         exonEnd = exonStart + gene->blockSizes->list[exon];
      }
   }

   cap = cap_getAdjacency(cap);
   Cap *nextcap;
   int64_t capCoor;
   exonStart = gene->chromStarts->list[exon] + gene->chromStart;
   exonEnd = exonStart + gene->blockSizes->list[exon];
   Block *block = end_getBlock(cap_getEnd(cap));  
 
   if(block == NULL){
      moveCapToNextBlock(&cap);
   }
   while(!isStubCap(cap) && exon < gene->blockCount){
      End *cend = cap_getEnd(cap);
      capCoor = cap_getCoordinate(cap);//Cap coordinate is always the coordinate on + strand
      nextcap = cap_getAdjacency(cap_getOtherSegmentCap(cap));
      st_logInfo("capCoor: %d, nextCap: %d, eStart: %d, eEnd: %d. Exon: %d\n", 
                  capCoor, cap_getCoordinate(nextcap), exonStart, exonEnd, exon);

      //keep moving if nextBlock Start is still upstream of current exon
      if(cap_getCoordinate(nextcap) <= exonStart){
         moveCapToNextBlock(&cap);
         st_logInfo("Still upstream, nextcap <= exonStart. Move to next chainBlock\n");
      }else if(capCoor >= exonEnd){//Done with current exon, move to next
         st_logInfo("Done with current exon, move to next one\n\n");
         fprintf(fileHandle, "\t\t</exon>\n");//end previous exon
         exon++;
         if(exon < gene->blockCount){
            exonStart = gene->chromStarts->list[exon] + gene->chromStart;
            exonEnd = exonStart + gene->blockSizes->list[exon];
            fprintf(fileHandle, "\t\t<exon id=\"%d\" start=\"%" PRIi64 "\" end=\"%" PRIi64 "\">\n", exon, exonStart, exonEnd);
         }
      }else{//current exon overlaps with current block Or with lower level flower
         Cap *oppcap = cap_getOtherSegmentCap(cap);
         st_logInfo("Current exon overlaps with current block or with lower flower\n");
         if(cap_getCoordinate(oppcap) >= exonStart && exonEnd > capCoor){
            mapBlockToExon(cap, level, fileHandle);
            if(exonEnd <= cap_getCoordinate(oppcap) + 1){
               st_logInfo("Done with current exon, move to next one\n\n");
               fprintf(fileHandle, "\t\t</exon>\n");//end previous exon
               exon++;
	       if(exon < gene->blockCount){
		  exonStart = gene->chromStarts->list[exon] + gene->chromStart;
		  exonEnd = exonStart + gene->blockSizes->list[exon];
		  fprintf(fileHandle, "\t\t<exon id=\"%d\" start=\"%" PRIi64 "\" end=\"%" PRIi64 "\">\n", exon, exonStart, exonEnd);
	       }
               continue;
            }
         }
         //Traverse lower level flowers if exists
         Group *group = end_getGroup(end_getOtherBlockEnd(cend));
         Flower *nestedFlower = group_getNestedFlower(group);
         if(nestedFlower != NULL){//recursive call
            Cap *childCap = flower_getCap(nestedFlower, cap_getName(cap_getOtherSegmentCap(cap)));
            assert(childCap != NULL);
            exon = mapGene(childCap, level + 1, exon, gene, fileHandle);
            exonStart = gene->chromStarts->list[exon] + gene->chromStart;
            exonEnd = exonStart + gene->blockSizes->list[exon];
         }
         moveCapToNextBlock(&cap);
      }
   }
   return exon;
}
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);
    }
}