1 # -*-Perl-*- Test Harness script for Bioperl
10 test_begin(-tests => 98,
11 -requires_modules => [qw(XML::LibXML XML::LibXML::Reader)]);
13 use_ok('Bio::TreeIO');
16 my $verbose = test_debug();
20 skip("Reader interface only supported in Perl >= 5.8",96);
21 } elsif (XML::LibXML::LIBXML_VERSION() <= 20620) {
22 skip("Reader not supported for libxml2 <= 2.6.20",96);
24 use_ok('Bio::TreeIO::phyloxml');
27 diag("libxml version: ", XML::LibXML::LIBXML_VERSION());
30 ok my $treeio = Bio::TreeIO->new(
32 -format => 'phyloxml',
33 -file => test_input_file('phyloxml_examples.xml'));
35 # tree1: clade and attribute
36 # <phylogeny> <clade> <name>
39 diag("\ntree1: clade and attribute");
41 my $tree = $treeio->next_tree;
42 isa_ok($tree, 'Bio::Tree::TreeI');
43 is($tree->id, 'example from Prof. Joe Felsenstein\'s book "Inferring Phylogenies"');
44 is($tree->get_tag_values('description'), 'phyloXML allows to use either a "branch_length" attribute or element to indicate branch lengths.');
46 diag("tree id: ",$tree->id);
47 diag("tree description: ", $tree->get_tag_values('description'));
49 is($tree->get_tag_values('rooted'), 'true');
50 my @nodes = $tree->get_nodes;
52 my ($A) = $tree->find_node('A');
54 is($A->branch_length, '0.102');
56 diag("node A: branch_length ", $A->branch_length);
58 is($A->ancestor->id, '');
59 is($A->ancestor->branch_length, '0.06');
60 my $leaves_string = $tree->simplify_to_leaves_string();
64 is($leaves_string, '((A,B),C)');
68 diag("\ntest write_tree");
70 my $FILE1 = test_output_file();
71 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
72 -format => 'phyloxml',
74 $treeout->write_tree($tree);
81 # tree2: branch_length
85 diag("\ntree2: branch_length");
87 my $tree = $treeio->next_tree;
88 isa_ok($tree, 'Bio::Tree::TreeI');
90 diag("tree id: ",$tree->id);
92 my @nodes = $tree->get_nodes;
94 my $A = $tree->find_node('A');
96 is($A->branch_length, '0.102');
98 diag("node A: branch_length ", $A->branch_length);
100 is($A->ancestor->id, '');
101 is($A->ancestor->branch_length, '0.06');
102 my $leaves_string = $tree->simplify_to_leaves_string();
104 diag($leaves_string);
106 is($leaves_string, '((A,B),C)');
110 diag("\ntest write_tree");
112 my $FILE1 = test_output_file();
113 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
114 -format => 'phyloxml',
116 $treeout->write_tree($tree);
123 # tree3: confidence (bootstrap)
127 diag("\ntree3: confidence (bootstrap)");
129 my $tree = $treeio->next_tree;
130 isa_ok($tree, 'Bio::Tree::TreeI');
132 diag("tree id: ",$tree->id);
134 my $AB = $tree->find_node('AB');
136 is($AB->bootstrap, '89');
138 diag("node AB: bootstrap ", $AB->bootstrap);
140 my $leaves_string = $tree->simplify_to_leaves_string();
142 diag($leaves_string);
144 is($leaves_string, '((A,B),C)');
148 diag("\ntest write_tree");
150 my $FILE1 = test_output_file();
151 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
152 -format => 'phyloxml',
154 $treeout->write_tree($tree);
161 # tree4: species and sequence
162 # <taxonomy> <scientific_name> <sequence> <annotation>
165 diag("\ntree4: taxonomy and sequence");
167 my $tree = $treeio->next_tree;
168 isa_ok($tree, 'Bio::Tree::TreeI');
170 diag("tree id: ",$tree->id);
172 my $C = $tree->find_node('C');
173 my ($ac) = $C->annotation->get_Annotations('taxonomy');
174 isa_ok( $ac, 'Bio::Annotation::Collection');
175 my ($ac2) = $ac->get_Annotations('scientific_name');
176 isa_ok( $ac2, 'Bio::Annotation::Collection');
177 my ($scientificname) = $ac2->get_Annotations('_text');
178 is($scientificname->value, 'C. elegans');
180 diag( "Node C Scientific Name: ",$scientificname->value);
182 my ($ac3) = $C->annotation->get_nested_Annotations(-keys=>['scientific_name'], -recursive=>1);
183 isa_ok( $ac3, 'Bio::Annotation::Collection');
184 ($scientificname) = $ac2->get_Annotations('_text');
185 is($scientificname->value, 'C. elegans');
187 diag( "Node C Scientific Name: ",$scientificname->value);
189 my ($seq) = @{$C->sequence};
190 isa_ok( $seq, 'Bio::SeqI');
191 my ($seqac) = $seq->annotation;
192 isa_ok( $seqac, 'Bio::Annotation::Collection');
193 my ($descac) = $seqac->get_nested_Annotations(-keys=>['desc'], -recursive=>1);
194 my ($desc) = $descac->get_Annotations('_text');
195 is($desc->value, 'alcohol dehydrogenase');
197 diag( "Node C Sequence description: ",$desc->value);
199 ($descac) = $seqac->get_nested_Annotations(-keys=>['desc'], -recursive=>1);
203 diag("\ntest write_tree");
205 my $FILE1 = test_output_file();
206 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
207 -format => 'phyloxml',
209 $treeout->write_tree($tree);
216 # tree5: homolog relationship and sequence relationship
217 # <events> <speciations> <duplications> <symbol> <accession>
218 # <sequence_relation>
221 diag("\ntree5: events and relations");
223 my $tree = $treeio->next_tree;
224 isa_ok($tree, 'Bio::Tree::TreeI');
226 diag("tree id: ",$tree->id);
228 my $node = $tree->get_root_node;
229 my ($speciationsac) = $node->annotation->get_nested_Annotations(-keys=>['speciations'], -recursive=>1);
230 my ($speciationval) = $speciationsac->get_Annotations('_text');
231 is($speciationval->value, '1');
233 diag("root node speciation event: ", $speciationval->value);
235 my @children = ($node);
237 push @children, $_->each_Descendent();
241 push @leaves, $_ if $_->is_Leaf;
243 my ($z) = $leaves[0];
244 my $z_seq = $z->sequence->[0];
245 isa_ok ($z_seq, 'Bio::SeqI');
246 my ($z_id) = $z_seq->annotation->get_nested_Annotations('-keys'=>['id_source'], '-recursive'=>1);
247 my ($z_id_text) = $z_id->value;
248 my @seq_rels = $z_seq->annotation->get_nested_Annotations('-keys'=>['sequence_relation'], '-recursive'=>1);
249 foreach my $rel (@seq_rels) {
250 isa_ok($rel, 'Bio::Annotation::Relation');
251 is ($rel->tagname, 'sequence_relation');
252 my $seqto = $rel->to;
253 isa_ok ($seqto, 'Bio::SeqI');
254 my ($seqto_id) = $seqto->annotation->get_nested_Annotations('-keys'=>['id_source'], '-recursive'=>1);
255 my $seqto_text = $seqto_id->value;
257 diag( "node ", $z_id_text, " has ", $rel->type, " relation to ", $seqto_text);
260 my ($x) = $leaves[1];
265 diag("\ntest write_tree");
267 my $FILE1 = test_output_file();
268 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
269 -format => 'phyloxml',
271 $treeout->write_tree($tree);
278 # tree6: detailed sequence data
279 # <mol_seq> <annotation> <code>
282 diag("\ntree6: detailed sequence annotation");
284 my $tree = $treeio->next_tree;
285 isa_ok($tree, 'Bio::Tree::TreeI');
287 diag("tree id: ",$tree->id);
289 my @children = ($tree->get_root_node);
291 push @children, $_->each_Descendent();
295 push @leaves, $_ if $_->is_Leaf;
297 my ($z) = $leaves[0];
298 my $z_seq = $z->sequence->[0];
299 isa_ok ($z_seq, 'Bio::SeqI');
300 my ($z_seqname) = $z_seq->annotation->get_nested_Annotations('-keys'=>['name'], '-recursive'=>1);
301 my ($z_seqname_text) = $z_seqname->get_Annotations('_text');
302 is ($z_seqname_text->value, 'NADH-dependent butanol dehydrogenase B');
303 my ($z_molseq) = $z_seq->seq;
304 is ($z_molseq, 'MVDFEYSIPTRIFFGKDKINVLGRELKKYGSKVLIVYGGGSIKRNGIYDK');
306 diag("Sequence ", $z_seqname_text->value, " is ", $z_molseq);
308 my ($z_seqname_text2) = $treeio->read_annotation('-obj'=>$z_seq, '-path'=>'name');
309 is ($z_seqname_text->value, $z_seqname_text2);
310 my ($y) = $leaves[1];
311 my $y_seq = $y->sequence->[0];
312 isa_ok ($y_seq, 'Bio::SeqI');
314 # add attribute id_source
315 $treeio->add_attribute(
317 '-attr' => "id_source = \"A\""
319 $treeio->add_attribute(
321 '-attr' => "id_source = \"B\""
324 # add sequence relation
325 $treeio->add_phyloXML_annotation(
327 '-xml'=>'<sequence_relation id_ref_0="A" id_ref_1="B" type="orthology"/>'
332 diag("\ntest write_tree");
334 my $FILE1 = test_output_file();
335 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
336 -format => 'phyloxml',
338 $treeout->write_tree($tree);
346 # <clade_relation> @id_source & @id_ref
349 diag("\ntree7: network using id_source/id_ref");
351 my $tree = $treeio->next_tree;
352 isa_ok($tree, 'Bio::Tree::TreeI');
354 diag("tree id: ",$tree->id);
356 my @children = ($tree->get_root_node);
358 push @children, $_->each_Descendent();
362 push @leaves, $_ if $_->is_Leaf;
364 my ($c) = $leaves[0];
365 my ($c_id) = $c->annotation->get_nested_Annotations('-keys'=>['id_source'], '-recursive'=>1);
366 my @clade_rels = $c->annotation->get_nested_Annotations('-keys'=>['clade_relation'], '-recursive'=>1);
367 foreach my $rel (@clade_rels) {
368 isa_ok($rel, 'Bio::Annotation::Relation');
369 is ($rel->tagname, 'clade_relation');
370 my $nodeto = $rel->to;
371 isa_ok ($nodeto, 'Bio::Tree::AnnotatableNode');
372 my ($nodeto_id) = $nodeto->annotation->get_nested_Annotations('-keys'=>['id_source'], '-recursive'=>1);
373 is ($nodeto_id->value, 'b');
374 my ($nodeto_id2) = $treeio->read_annotation('-obj'=>$nodeto, '-path'=>'id_source', '-attr'=>1);
375 is ($nodeto_id->value, $nodeto_id2);
377 diag( "node ", $c_id->value, " has ", $rel->type, " relation to ", $nodeto_id->value);
383 diag("\ntest write_tree");
385 my $FILE1 = test_output_file();
386 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
387 -format => 'phyloxml',
389 $treeout->write_tree($tree);
396 # tree8: property elements
400 diag("\ntree8: property");
402 my $tree = $treeio->next_tree;
403 isa_ok($tree, 'Bio::Tree::TreeI');
405 diag("tree id: ",$tree->id);
407 my ($A) = $tree->find_node('A');
408 isa_ok($A, 'Bio::Tree::AnnotatableNode');
409 my ($ac) = $A->annotation();
410 isa_ok($ac, 'Bio::AnnotationCollectionI');
411 my (@annotations) = $ac->get_Annotations('property');
412 isa_ok( $annotations[0], 'Bio::Annotation::Collection');
413 diag("property:",$annotations[0]) if $verbose;
414 my (@keys) = $annotations[0]->get_all_annotation_keys();
415 diag("keys:",@keys) if $verbose;
416 my (@value) = $annotations[0]->get_Annotations('_text');
417 is($value[0]->value, ' 1200 ');
419 diag( "Annotation NOAA:depth ",$value[0]->value);
421 my $leaves_string = $tree->simplify_to_leaves_string();
423 diag($leaves_string);
425 is($leaves_string, '((A,B),C)');
429 diag("\ntest write_tree");
431 my $FILE1 = test_output_file();
432 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
433 -format => 'phyloxml',
435 $treeout->write_tree($tree);
442 # tree9: property outside tree topology using id refs
443 # <property> @id_source @id_ref
446 diag("\ntree9: property using id_source/id_ref");
448 my $tree = $treeio->next_tree;
449 isa_ok($tree, 'Bio::Tree::TreeI');
451 diag("tree id: ",$tree->id);
453 my $A = $tree->find_node('A');
454 isa_ok($A, 'Bio::Tree::AnnotatableNode');
455 my $ac = $A->annotation();
456 isa_ok($ac, 'Bio::AnnotationCollectionI');
457 my @annotations = $ac->get_Annotations('property');
458 isa_ok( $annotations[0], 'Bio::Annotation::Collection');
459 my @value = $annotations[0]->get_Annotations('_text');
460 is($value[0]->value, ' 1200 ');
462 diag( "Annotation NOAA:depth ",$value[0]->value);
464 my $leaves_string = $tree->simplify_to_leaves_string();
466 diag($leaves_string);
468 is($leaves_string, '((A,B),C)');
472 diag("\ntest write_tree");
474 my $FILE1 = test_output_file();
475 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
476 -format => 'phyloxml',
478 $treeout->write_tree($tree);
485 # tree10: detailed taxonomy and distribution
486 # <id> <rank> <uri> <common_name> <distribution>
489 diag("\ntree10: taxonomy and distribution");
491 my $tree = $treeio->next_tree;
492 isa_ok($tree, 'Bio::Tree::TreeI');
494 diag("tree id: ",$tree->id);
496 my $node = $tree->get_root_node;
498 my @children = ($node);
500 push @children, $_->each_Descendent();
503 push @leaves, $_ if $_->is_Leaf;
505 my ($A) = $leaves[0];
506 my ($scientificname) = $A->annotation->get_nested_Annotations('-keys'=>['scientific_name'], '-recursive'=>1);
507 my ($scientificname_text) = $scientificname->get_Annotations('_text');
508 my ($commonname) = $A->annotation->get_nested_Annotations('-keys'=>['common_name'], '-recursive'=>1);
509 my ($commonname_text) = $commonname->get_Annotations('_text');
510 my ($rank) = $A->annotation->get_nested_Annotations('-keys'=>['rank'], '-recursive'=>1);
511 my ($rank_text) = $rank->get_Annotations('_text');
513 diag("node rank is ", $rank_text->value);
514 diag("node scientific name is ", $scientificname_text->value);
515 diag("node common name is ", $commonname_text->value);
517 my ($distribution) = $A->annotation->get_nested_Annotations('-keys'=>['distribution'], '-recursive'=>1);
518 my ($desc) = $distribution->get_Annotations('desc');
519 my ($desc_text) = $desc->get_Annotations('_text');
521 diag("node distribution is ", $desc_text->value);
526 diag("\ntest write_tree");
528 my $FILE1 = test_output_file();
529 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
530 -format => 'phyloxml',
532 $treeout->write_tree($tree);
539 # tree11: phylogeographic information
540 # <distribution> <point> <lat> <long> <alt>
543 diag("\ntree11: phylogenographic information");
545 my $tree = $treeio->next_tree;
546 isa_ok($tree, 'Bio::Tree::TreeI');
548 diag("tree id: ",$tree->id);
550 my $node = $tree->get_root_node;
552 my @children = ($node);
554 push @children, $_->each_Descendent();
557 push @leaves, $_ if $_->is_Leaf;
559 my ($D) = $leaves[0];
560 my ($point) = $treeio->read_annotation('-obj'=>$D, '-path'=>'distribution/point/geodetic_datum', '-attr'=>1);
561 is ($point, 'WGS84');
562 my ($lat) = $treeio->read_annotation('-obj'=>$D, '-path'=>'distribution/point/lat');
563 my ($long) = $treeio->read_annotation('-obj'=>$D, '-path'=>'distribution/point/long');
564 my ($alt) = $treeio->read_annotation('-obj'=>$D, '-path'=>'distribution/point/alt');
565 is ($lat, '32.880933');
566 is ($long, '-117.217543');
569 diag("node distribution lat: $lat long $long alt $alt");
575 diag("\ntest write_tree");
577 my $FILE1 = test_output_file();
578 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
579 -format => 'phyloxml',
581 $treeout->write_tree($tree);
588 # tree12: date information
589 # <date> <desc> <value>
592 diag("\ntree12: date");
594 my $tree = $treeio->next_tree;
595 isa_ok($tree, 'Bio::Tree::TreeI');
597 diag("tree id: ",$tree->id);
599 my $node = $tree->get_root_node;
601 my @children = ($node);
603 push @children, $_->each_Descendent();
606 push @leaves, $_ if $_->is_Leaf;
608 my ($D) = $tree->find_node(-id => 'A');
609 my ($dateunit) = $treeio->read_annotation('-obj'=>$D, '-path'=>'date/unit', '-attr'=>1);
610 my ($datemin) = $treeio->read_annotation('-obj'=>$D, '-path'=>'date/minimum' );
611 my ($datemax) = $treeio->read_annotation('-obj'=>$D, '-path'=>'date/maximum' );
612 my ($datevalue) = $treeio->read_annotation('-obj'=>$D, '-path'=>'date/value');
613 is ($dateunit, 'mya');
614 is ($datemin, '416.0');
615 is ($datemax, '443.7');
616 is ($datevalue, '425');
618 diag("node date unit: $dateunit min $datemin max $datemax value $datevalue");
623 diag("\ntest write_tree");
625 my $FILE1 = test_output_file();
626 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
627 -format => 'phyloxml',
629 $treeout->write_tree($tree);
636 # tree13: alignment outside <phylogeny>
637 # <align:alignment> <seq>
640 diag("\ntree13: alignment outside <phylogeny>");
642 my $tree = $treeio->next_tree;
643 isa_ok($tree, 'Bio::Tree::TreeI');
645 diag("tree id: ",$tree->id);
647 my $leaves_string = $tree->simplify_to_leaves_string();
649 diag($leaves_string);
651 is($leaves_string, '((A,B),C)');
653 # add annotation in phyloxml
655 diag("test add annotation in phyloXML format");
657 my $node = $tree->get_root_node;
659 my @children = ($node);
661 push @children, $_->each_Descendent();
664 push @leaves, $_ if $_->is_Leaf;
666 my ($D) = $leaves[0];
667 isa_ok($D, 'Bio::Tree::AnnotatableNode');
668 $treeio->add_phyloXML_annotation(
670 -xml => " <name>D</name>
673 <value>manymany million years</value>
677 my ($dateunit) = $treeio->read_annotation('-obj'=>$D, '-path'=>'date/unit', '-attr'=>1);
678 my ($datevalue) = $treeio->read_annotation('-obj'=>$D, '-path'=>'date/value');
679 is ($dateunit, 'mya');
680 is ($datevalue, 'manymany million years');
684 diag("\ntest write_tree");
686 my $FILE1 = test_output_file();
687 my $treeout = Bio::TreeIO->new(-verbose => $verbose,
688 -format => 'phyloxml',
690 $treeout->write_tree($tree);
698 # tree14: convert between nhx and phyloxml
699 # convert between nhx-phyloxml
702 diag("\n test translation between nhx and phyloxml");
704 ok my $nhxio = Bio::TreeIO->new(
705 -verbose => $verbose,
707 -file => test_input_file('test.nhx'));
708 my $tree = $nhxio->next_tree;
709 isa_ok($tree, 'Bio::Tree::TreeI');
710 my $FILE1 = test_output_file();
711 my $phyloxmlio = Bio::TreeIO->new(-verbose => $verbose,
712 -format => 'phyloxml',
714 $phyloxmlio->write_tree($tree);
721 # to-do 1. validation
723 local $TODO = 'validation not implemented yet';
725 my $xsd = "http://www.phyloxml.org/1.10/phyloxml.xsd";
726 # for my $XSD ($xsd, XML::LibXML::Schema->new(location => $xsd)) {
728 # my $reader = new XML::LibXML::Reader(
729 # location => "test/schema/demo.xml",
732 # ok($reader->finish, "validate using ".(ref($XSD) ? 'XML::LibXML::Schema' : 'Schema file'));
735 # my $reader = new XML::LibXML::Reader(
736 # location => "test/schema/invaliddemo.xml",
739 # eval { $reader->finish };
740 # ok($@, "catch validation error for ".(ref($XSD) ? 'XML::LibXML::Schema' : 'Schema file'));