Bio::Tools::CodonTable and Bio::Tools::IUPAC: prepare with dzil.
[bioperl-live.git] / t / Tree / Tree.t
blobb955131ed9a5854cf8fd56489a03d99f86adae73
1 # -*-Perl-*- Test Harness script for Bioperl
2 # $Id$
4 use strict;
6 BEGIN { 
7     use Bio::Root::Test;
8     test_begin(-tests => 66);
9     use_ok('Bio::TreeIO');
12 my $verbose = test_debug();
14 my $treeio = Bio::TreeIO->new(-verbose => $verbose,
15                               -format => 'nhx',
16                               -file   => test_input_file('test.nhx'));
17 my $tree = $treeio->next_tree;
19 # tests for tags
20 ok ! $tree->has_tag('test');
21 is $tree->add_tag_value('test','a'), 1;
22 ok $tree->has_tag('test');
23 is $tree->add_tag_value('test','b'), 2;
24 my @tags = $tree->get_tag_values('test');
25 is scalar @tags, 2;
26 is scalar $tree->get_tag_values('test'), 'a', 'retrieve the first value';
27 is $tree->remove_tag('test2'), 0;
28 is $tree->remove_tag('test'), 1;
29 ok ! $tree->has_tag('test');
30 is $tree->set_tag_value('test',('a','b','c')), 3;
31 is $tree->remove_all_tags(), undef;
32 ok ! $tree->has_tag('test');
35 my @nodes = $tree->find_node('ADH2');
36 is(@nodes, 2,'Number of nodes that have ADH2 as name');
38 if( $verbose ) {
39     $treeio = Bio::TreeIO->new(-verbose => $verbose,
40                                -format => 'nhx',
41                               );
42     $treeio->write_tree($tree);
43     print "nodes are: \n",
44     join(", ", map {  $_->id . ":". (defined $_->branch_length ? 
45                                      $_->branch_length : '' ) } @nodes), "\n";
48 $treeio = Bio::TreeIO->new(-format => 'newick',
49                            -file   => test_input_file('test.nh'));
50 $tree = $treeio->next_tree;
53 if( $verbose ) { 
54     my $out = Bio::TreeIO->new(-format => 'tabtree');
55     
56     $out->write_tree($tree);
59 my @hADH = ( $tree->find_node('hADH1'),
60              $tree->find_node('hADH2') );
61 my ($n4) = $tree->find_node('yADH4');
63 is($tree->is_monophyletic(-nodes    => \@hADH,
64                           -outgroup => $n4),1,'Test Monophyly');
66 my @mixgroup = ( $tree->find_node('hADH1'),
67                  $tree->find_node('yADH2'),
68                  $tree->find_node('yADH3'),
69                  );
71 my ($iADHX) = $tree->find_node('iADHX');
73 # test height
74 is($iADHX->height, 0,'Height');
75 is($iADHX->depth,0.22,'Depth');
76 isnt( $tree->is_monophyletic(-nodes   => \@mixgroup,
77                              -outgroup=> $iADHX),1, 'non-monophyletic group');
79 # binary tree?
80 is $tree->is_binary, 0, 'not a binary tree';
81 is scalar $tree->get_nodes, 12, '12 nodes';
82 $tree->verbose(-1);
83 $tree->force_binary;
84 is $tree->is_binary, 1, 'after force_binary() it is';
85 is scalar $tree->get_nodes, 17, 'and there are more nodes (17)';
87 my $in = Bio::TreeIO->new(-format => 'newick',
88                           -fh     => \*DATA);
89 $tree = $in->next_tree;
90 my ($a,$b,$c,$d) = ( $tree->find_node('A'),
91                      $tree->find_node('B'),
92                      $tree->find_node('C'),
93                      $tree->find_node('D'));
95 is($tree->is_monophyletic(-nodes => [$b,$c],
96                           -outgroup => $d),1, 'B,C are Monophyletic');
98 is($tree->is_monophyletic(-nodes => [$b,$a],
99                           -outgroup => $d),1,'A,B are Monophyletic');
101 $tree = $in->next_tree;
102 my ($e,$f,$i);
103 ($a,$b,$c,$d,$e,$f,$i) = ( $tree->find_node('A'),
104                            $tree->find_node('B'),
105                            $tree->find_node('C'),
106                            $tree->find_node('D'),
107                            $tree->find_node('E'),
108                            $tree->find_node('F'),
109                            $tree->find_node('I'),
110                            );
111 isnt( $tree->is_monophyletic(-nodes => [$b,$f],
112                              -outgroup => $d),1,'B,F are not Monophyletic' );
114 is($tree->is_monophyletic(-nodes => [$b,$a],
115                           -outgroup => $f),1, 'A,B are Monophyletic');
117 # test for paraphyly
119 isnt(  $tree->is_paraphyletic(-nodes => [$a,$b,$c],
120                               -outgroup => $d), 1,'A,B,C are not Monophyletic w D as outgroup');
122 is(  $tree->is_paraphyletic(-nodes => [$a,$f,$e],
123                             -outgroup => $i), 1, 'A,F,E are monophyletic with I as outgroup');
126 # test for rerooting the tree
127 my $out = Bio::TreeIO->new(-format => 'newick', 
128                            -fh => \*STDERR, 
129                            -noclose => 1);
130 $tree = $in->next_tree;
131 $tree->verbose( -1 ) unless $verbose;
132 my $node_cnt_orig = scalar($tree->get_nodes);
133 # reroot on an internal node: should work fine
134 $a = $tree->find_node('A');
135 # removing node_count checks because re-rooting can change the
136 # number of internal nodes (if it is done correctly)
137 my $total_length_orig = $tree->total_branch_length;
138 is $tree->total_branch_length, $tree->subtree_length, 
139     "subtree_length() without attributes is an alias to total_branch_lenght()";
140 cmp_ok($total_length_orig, '>',$tree->subtree_length($a->ancestor), 
141        'Length of the tree is larger that lenght of a subtree');
142 $out->write_tree($tree) if $verbose;
143 is($tree->reroot($a),1, 'Can re-root with A as outgroup');
144 $out->write_tree($tree) if $verbose;
145 is($node_cnt_orig, scalar($tree->get_nodes), 'Count the number of nodes');
146 my $total_length_new = $tree->total_branch_length;
147 my $eps = 0.001 * $total_length_new; # tolerance for checking length
148 warn("orig total len ", $total_length_orig, "\n") if $verbose;
149 warn("new  total len ", $tree->total_branch_length,"\n") if $verbose;
150 # according to retree in phylip these branch lengths actually get larger
151 # go figure...
152 # this should be fixed now/maj
153 ok(($total_length_orig >= $tree->total_branch_length - $eps) &&
154    ($total_length_orig <= $tree->total_branch_length + $eps),'same length');
156 # prob with below: rerooted tree on node A at line 146; so $a IS root
157 #/maj is($tree->get_root_node, $a->ancestor, "Root node is A's ancestor");
158 is($tree->get_root_node, $a, "Root node is A");
160 # former test expected the old behavior of reroot; here is the new
161 # test/maj
162 my $desc = ($a->each_Descendent)[0];
163 my $newroot = $desc->create_node_on_branch(-FRACTION=>0.5, -ANNOT=>{-id=>'newroot'});
164 $tree->reroot($newroot);
165 is($tree->get_root_node, $a->ancestor, "Root node is A's ancestor");
167 # try to reroot on an internal, will result in there being 1 less node
168 # Rerooting should be an invariant operation with respect to node number!/maj
169 # the test show that it now is, because the secret removal of nodes 
170 # no longer occurs
172 $a = $tree->find_node('C')->ancestor;
173 $out->write_tree($tree) if $verbose;
174 is($tree->reroot($a),1, "Can reroot with C's ancsestor");
175 $out->write_tree($tree) if $verbose;
176 #/maj is($node_cnt_orig, scalar($tree->get_nodes), 'Check to see that node count is correct after an internal node was removed after this re-rooting');
177 # but we did add a new node at line 166, so
178 is($node_cnt_orig+1, scalar($tree->get_nodes), 'Node count correct');
179 warn("orig total len ", $total_length_orig, "\n") if $verbose;
180 warn("new  total len ", $tree->total_branch_length,"\n") if $verbose;
181 cmp_ok($total_length_orig, '>=', $tree->total_branch_length - $eps, 
182        'Total original branch length is what it is supposed to be');
183 # branch length should also be invariant w/r to rerooting...
184 cmp_ok($total_length_orig, '<=',$tree->total_branch_length + $eps, 
185        'Updated total branch length after the reroot');
186 # again, we rerooted ON THE NODE, so $a IS the root./maj
187 is($tree->get_root_node, $a, 'Make sure root is really what we asked for');
189 # try to reroot on new root: should fail
190 #/maj  $a = $tree->get_root_node;
191 isnt( $tree->reroot($a),1, 'Testing for failed re-rerooting');
193 # try a more realistic tree
194 $tree = $in->next_tree;
195 $a = $tree->find_node('VV');
196 $node_cnt_orig = scalar($tree->get_nodes);
197 $total_length_orig = $tree->total_branch_length;
198 $out->write_tree($tree) if $verbose;
199 is($tree->reroot($a),1, 'Test that rooting succeeded'); #mod /maj
200 $out->write_tree($tree) if $verbose;
201 # node number should be invariant after reroot/maj
202 is($node_cnt_orig, scalar($tree->get_nodes), 'Test that re-rooted tree has proper number of nodes after re-rooting'); #mod /maj
203 $total_length_new = $tree->total_branch_length;
204 $eps = 0.001 * $total_length_new;    # tolerance for checking length
205 cmp_ok($total_length_orig, '>=', $tree->total_branch_length - $eps, 'Branch length before rerooting');
206 cmp_ok($total_length_orig, '<=', $tree->total_branch_length + $eps, 
207        'Branch length after rerooting');
208 is($tree->get_root_node, $a,'Root is really the ancestor we asked for'); #mod /maj
210 # BFS and DFS search testing
211 $treeio = Bio::TreeIO->new(-verbose => $verbose,
212                            -format  => 'newick',
213                            -file    => test_input_file('test.nh'));
214 $tree = $treeio->next_tree;
215 my ($ct,$n) = (0);
216 my $let = ord('A');
217 for $n (  $tree->get_leaf_nodes ) {
218     $n->id(chr($let++));
221 for $n ( grep {! $_->is_Leaf } $tree->get_nodes ) {
222     $n->id($ct++);
224 # enable for debugging
225 Bio::TreeIO->new(-format => 'newick')->write_tree($tree) if( $verbose );
227 my $BFSorder = join(",", map { $_->id } ( $tree->get_nodes(-order => 'b')));
228 is($BFSorder, '0,1,3,2,C,D,E,F,G,H,A,B', 'BFS traversal order');
229 my $DFSorder = join(",", map { $_->id } ( $tree->get_nodes(-order => 'd')));
230 is($DFSorder, '0,1,2,A,B,C,D,3,E,F,G,H', 'DFS travfersal order');
233 # test some Bio::Tree::TreeFunctionI methods
234 #find_node tested extensively already
235 $tree->remove_Node('H');
236 $DFSorder = join(",", map { $_->id } ( $tree->get_nodes(-order => 'd')));
237 is($DFSorder, '0,1,2,A,B,C,D,3,E,F,G', 'DFS traversal after removing H');
238 $tree->splice(-remove_id => 'G');
239 $DFSorder = join(",", map { $_->id } ( $tree->get_nodes(-order => 'd')));
240 is($DFSorder, '0,1,2,A,B,C,D,3,E,F', 'DFS traversal after removing G');
241 $tree->splice(-remove_id => [('E', 'F')], -keep_id => 'F');
242 $DFSorder = join(",", map { $_->id } ( $tree->get_nodes(-order => 'd')));
243 # the node '3' is not explicitly removed, so it should still be there
244 # I suspect that it disappeared before was due to the previously
245 # automatic removal of internal degree 2 nodes../maj
246 is($DFSorder, '0,1,2,A,B,C,D,3,F', 'DFS traversal after removing E');
247 $tree->splice(-keep_id => [qw(0 1 2 A B C D)]);
248 $DFSorder = join(",", map { $_->id } ( $tree->get_nodes(-order => 'd')));
249 is($DFSorder, '0,1,2,A,B,C,D', 'DFS after removing all but 0,1,2,A,B,C,D');
250 #get_lineage_nodes, get_lineage_string, get_lca, merge_lineage, contract_linear_paths tested in Taxonomy.t
253 # try out the id to bootstrap copy method
254 $treeio = Bio::TreeIO->new(-format => 'newick',
255                            -file   => test_input_file('bootstrap.tre'));
256 $tree = $treeio->next_tree;
257 my ($test_node) = $tree->find_node(-id => 'A');
258 is($test_node->ancestor->id, 90,'Testing bootstrap copy');
259 is($test_node->ancestor->ancestor->id, '25','Testing bootstrap copy');
260 is($test_node->ancestor->ancestor->ancestor->id, '0','Testing bootstrap copy');
261 $tree->move_id_to_bootstrap;
262 is($test_node->ancestor->id, '','Testing bootstrap copy');
263 is($test_node->ancestor->bootstrap, '90', 'Testing bootstrap copy');
264 is($test_node->ancestor->ancestor->id, '', 'Testing bootstrap copy');
265 is($test_node->ancestor->ancestor->bootstrap, '25', 'Testing bootstrap copy');
266 is($test_node->ancestor->ancestor->ancestor->bootstrap, '0','Testing bootstrap copy');
268 # change TreeIO to parse 
269 $treeio = Bio::TreeIO->new(-format => 'newick',
270                            -file   => test_input_file('bootstrap.tre'),
271                            -internal_node_id => 'bootstrap');
272 $tree = $treeio->next_tree;
273 ($test_node) = $tree->find_node(-id => 'A');
274 is($test_node->ancestor->id, '','Testing auto-boostrap copy during parse');
275 is($test_node->ancestor->ancestor->id, '',
276    'Testing auto-boostrap copy during parse');
277 is($test_node->ancestor->bootstrap, '90',
278    'Testing auto-boostrap copy during parse');
279 is($test_node->ancestor->ancestor->bootstrap, '25', 
280    'Testing auto-boostrap copy during parse');
282 # return an empty array when no nodes are found
283 ok $tree = Bio::Tree::Tree->new();
284 @nodes = $tree->get_nodes;
285 is scalar @nodes, 0;
288 __DATA__
289 (D,(C,(A,B)));
290 (I,((D,(C,(A,B)x)y),(E,(F,G))));
291 (((A:0.3,B:2.1):0.45,C:0.7),D:4);
292 (A:0.031162,((((((B:0.022910,C:0.002796):0.010713,(D:0.015277,E:0.020484):0.005336):0.005588,((F:0.013293,(G:0.018374,H:0.003108):0.005318):0.006047,I:0.014607):0.001677):0.004196,(((((J:0.003307,K:0.001523):0.011884,L:0.006960):0.006514,((M:0.001683,N:0.000100):0.002226,O:0.007085):0.014649):0.008004,P:0.037422):0.005201,(Q:0.000805,R:0.000100):0.015280):0.005736):0.004612,S:0.042283):0.017979,(T:0.006883,U:0.016655):0.040226):0.014239,((((((V:0.000726,W:0.000100):0.028490,((((X:0.011182,Y:0.001407):0.005293,Z:0.011175):0.004701,AA:0.007825):0.016256,BB:0.029618):0.008146):0.004279,CC:0.035012):0.060215,((((((DD:0.014933,(EE:0.008148,FF:0.000100):0.015458):0.003891,GG:0.010996):0.001489,(HH:0.000100,II:0.000100):0.054265):0.003253,JJ:0.019722):0.013796,((KK:0.001960,LL:0.004924):0.013034,MM:0.010071):0.043273):0.011912,(NN:0.031543,OO:0.018307):0.059182):0.026517):0.011087,((PP:0.000100,QQ:0.002916):0.067214,(RR:0.064486,SS:0.013444):0.011613):0.050846):0.015644,((TT:0.000100,UU:0.009287):0.072710,(VV:0.009242,WW:0.009690):0.035346):0.042993):0.060365);