6.3 Test building trees

(Linux version)

< 6.2 | 6.3 | 7.0 >

To test both the buildFromNewick and the makeNewick function, change main.cpp to look like this:

#include &lt;iostream&gt; 
#include &lt;string&gt;
#include "node.hpp"
#include "tree.hpp"
#include "tree_manip.hpp"
#include "xstrom.hpp"

using namespace strom;

const double Node::_smallest_edge_length = 1.0e-12;

int main(int argc, const char * argv[]) {
    std::cout &lt;&lt; "Starting..." &lt;&lt; std::endl;
    TreeManip tm;
    std::string newick = std::string("(1:0.3,2:0.3,(3:0.2,(4:0.1,5:0.1):0.1):0.1)");
    std::cout &lt;&lt; "Input: " &lt;&lt; newick &lt;&lt; std::endl;
    try {
        tm.buildFromNewick(newick, false, false);
        std::cout &lt;&lt; "Output: " &lt;&lt; tm.makeNewick(3) &lt;&lt; std::endl;
        tm.rerootAtNodeNumber(4);                                   
        std::cout &lt;&lt; "Output: " &lt;&lt; tm.makeNewick(3) &lt;&lt; std::endl;   
    }
    catch (XStrom x) {
        std::cout &lt;&lt; "Error: " &lt;&lt; x.what() &lt;&lt; std::endl;
    }
    std::cout &lt;&lt; "\nFinished!" &lt;&lt; std::endl;

    return 0;
}   

The main function now creates a tree from the newick string

(1:0.3,2:0.3,(3:0.2,(4:0.1,5:0.1):0.1):0.1)

and then uses the makeNewick function to turn the tree in memory into a newick string, which is output. The program is working correctly if the output string represents the same tree as the input string (note that the number of decimal places used to depict edge lengths will differ, but the tree descriptions should depict exactly the same tree topology and edge lengths).

Test of rerootAtNodeNumber function

These two lines in main.cpp test whether the rerootAtNodeNumber function works correctly.

        tm.rerootAtNodeNumber(4);                                   
        std::cout &lt;&lt; "Output: " &lt;&lt; tm.makeNewick(3) &lt;&lt; std::endl;   

These lines ask the program to reroot using the node having _number equal to 4, which is actually the number labeled 5 in the newick string.

Expected output

Here is the output that your program should produce. See the next section if you have problems running the program.

Starting...
Constructing a TreeManip
Input: (1:0.3,2:0.3,(3:0.2,(4:0.1,5:0.1):0.1):0.1)
Constructing a Tree
Creating Node object
Creating Node object
Creating Node object
Creating Node object
Creating Node object
Creating Node object
Creating Node object
Creating Node object
Output: (1:0.300,2:0.300,(3:0.200,(4:0.100,5:0.100):0.100):0.100)
Output: (5:0.100,4:0.100,(3:0.200,(2:0.300,1:0.300):0.100):0.100)

Finished!
Destroying a TreeManip
Destroying a Tree
Destroying Node object
Destroying Node object
Destroying Node object
Destroying Node object
Destroying Node object
Destroying Node object
Destroying Node object
Destroying Node object

If your program halts at assert(!nd->_left_child)

Assert statements test assumptions that you are making as you write source code. Any time you find yourself thinking “I’m pretty sure that will never happen”, then it is probably time to use an assert statement to ensure that, if it does happen, you know about it and can find where it happened and under what circumstances it happened. Assert statements disappear in optimized code, so you will only see these trip if you are running the debug (non-optimized) version of your program (usually inside the IDE).

The fact that assert statements do not end up in the optimized (non-debug) version of your program means that you should use exceptions rather than asserts for assumptions you are making about the behavior of users of your program. Asserts help protect your program from yourself; exceptions help protect your program from your users.

If your program trips the assert(!nd->_left_child); inside the TreeManip::buildFromNewick function, then almost certainly what has happened is that you’ve not removed all traces of Tree::createTestTree(), which you were instructed to do in the very last (“Before moving on…”) section of the page Create the TreeManip class. The problem is that your Tree constructor is building a default tree every time it is called, so you are never starting from a clean slate with respect to the tree that you are building. Thus, you must remove the call to createTestTree() in the Tree::Tree constructor and reinstate the clear() function there.

Handling exceptions

If you would like to test the exception mechanism, try introducing an error in the newick tree description. For example, changing taxon “3” to “Z”. This will create an exception because only newick descriptions with taxon names that can be converted to positive integers are allowed:

std::string newick = std::string("(1:0.3,2:0.3,(Z:0.2,(4:0.1,5:0.1):0.1):0.1)");

Running the program now should produce the following error message:

Error: node name (Z) not interpretable as a positive integer

(Be sure to change the “Z” back to a “3” before continuing.)

< 6.2 | 6.3 | 7.0 >