File Coverage

blib/lib/Bio/Phylo/Taxa.pm
Criterion Covered Total %
statement 54 111 48.6
branch 3 22 13.6
condition 4 7 57.1
subroutine 13 21 61.9
pod 11 11 100.0
total 85 172 49.4


line stmt bran cond sub pod time code
1             package Bio::Phylo::Taxa;
2 15     15   65656 use strict;
  15         31  
  15         412  
3 15     15   70 use warnings;
  15         27  
  15         394  
4 15     15   229 use base 'Bio::Phylo::Listable';
  15         99  
  15         2936  
5 15     15   186 use Bio::Phylo::Util::CONSTANT qw':objecttypes /looks_like/ :namespaces';
  15         72  
  15         4766  
6 15     15   99 use Bio::Phylo::Util::Exceptions 'throw';
  15         29  
  15         594  
7 15     15   84 use Bio::Phylo::Mediators::TaxaMediator;
  15         26  
  15         409  
8 15     15   73 use Bio::Phylo::Factory;
  15         26  
  15         84  
9              
10             =begin comment
11              
12             This class has no internal state, no cleanup is necessary.
13              
14             =end comment
15              
16             =cut
17              
18             {
19             my $logger = __PACKAGE__->get_logger;
20             my $mediator = 'Bio::Phylo::Mediators::TaxaMediator';
21             my $factory = Bio::Phylo::Factory->new;
22             my $CONTAINER = _PROJECT_;
23             my $TYPE = _TAXA_;
24             my $MATRIX = _MATRIX_;
25             my $FOREST = _FOREST_;
26              
27             =head1 NAME
28              
29             Bio::Phylo::Taxa - Container of taxon objects
30              
31             =head1 SYNOPSIS
32              
33             use Bio::Phylo::Factory;
34             my $fac = Bio::Phylo::Factory->new;
35              
36             # A mesquite-style default
37             # taxa block for 10 taxa.
38             my $taxa = $fac->create_taxa;
39             for my $i ( 1 .. 10 ) {
40             $taxa->insert( $fac->create_taxon( '-name' => "taxon_${i}" ) );
41             }
42            
43             # prints a taxa block in nexus format
44             print $taxa->to_nexus;
45              
46             =head1 DESCRIPTION
47              
48             The Bio::Phylo::Taxa object models a set of operational taxonomic units. The
49             object subclasses the Bio::Phylo::Listable object, and so the filtering
50             methods of that class are available.
51              
52             A taxa object can link to multiple forest and matrix objects.
53              
54             =head1 METHODS
55              
56             =head2 CONSTRUCTOR
57              
58             =over
59              
60             =item new()
61              
62             Taxa constructor.
63              
64             Type : Constructor
65             Title : new
66             Usage : my $taxa = Bio::Phylo::Taxa->new;
67             Function: Instantiates a Bio::Phylo::Taxa object.
68             Returns : A Bio::Phylo::Taxa object.
69             Args : none.
70              
71             =cut
72              
73             # sub new {
74             # # could be child class
75             # my $class = shift;
76             #
77             # # notify user
78             # $logger->info("constructor called for '$class'");
79             #
80             # # recurse up inheritance tree, get ID
81             # my $self = $class->SUPER::new( '-tag' => __PACKAGE__->_tag, @_ );
82             #
83             # # local fields would be set here
84             #
85             # return $self;
86             # }
87              
88             =back
89              
90             =head2 MUTATORS
91              
92             =over
93              
94             =item set_forest()
95              
96             Sets associated Bio::Phylo::Forest object.
97              
98             Type : Mutator
99             Title : set_forest
100             Usage : $taxa->set_forest( $forest );
101             Function: Associates forest with the
102             invocant taxa object (i.e.
103             creates reference).
104             Returns : Modified object.
105             Args : A Bio::Phylo::Forest object
106             Comments: A taxa object can link to multiple
107             forest and matrix objects.
108              
109             =cut
110              
111             sub set_forest {
112 0     0 1 0 my ( $self, $forest ) = @_;
113 0         0 $logger->debug("setting forest $forest");
114 0 0       0 if ( looks_like_object $forest, $FOREST ) {
115 0         0 $forest->set_taxa($self);
116             }
117 0         0 return $self;
118             }
119              
120             =item set_matrix()
121              
122             Sets associated Bio::Phylo::Matrices::Matrix object.
123              
124             Type : Mutator
125             Title : set_matrix
126             Usage : $taxa->set_matrix($matrix);
127             Function: Associates matrix with the
128             invocant taxa object (i.e.
129             creates reference).
130             Returns : Modified object.
131             Args : A Bio::Phylo::Matrices::Matrix object
132             Comments: A taxa object can link to multiple
133             forest and matrix objects.
134              
135             =cut
136              
137             sub set_matrix {
138 0     0 1 0 my ( $self, $matrix ) = @_;
139 0         0 $logger->debug("setting matrix $matrix");
140 0 0       0 if ( looks_like_object $matrix, $MATRIX ) {
141 0         0 $matrix->set_taxa($self);
142             }
143 0         0 return $self;
144             }
145              
146             =item unset_forest()
147              
148             Removes association with argument Bio::Phylo::Forest object.
149              
150             Type : Mutator
151             Title : unset_forest
152             Usage : $taxa->unset_forest($forest);
153             Function: Disassociates forest from the
154             invocant taxa object (i.e.
155             removes reference).
156             Returns : Modified object.
157             Args : A Bio::Phylo::Forest object
158              
159             =cut
160              
161             sub unset_forest {
162 0     0 1 0 my ( $self, $forest ) = @_;
163 0         0 $logger->debug("unsetting forest $forest");
164 0 0       0 if ( looks_like_object $forest, $FOREST ) {
165 0         0 $forest->unset_taxa();
166             }
167 0         0 return $self;
168             }
169              
170             =item unset_matrix()
171              
172             Removes association with Bio::Phylo::Matrices::Matrix object.
173              
174             Type : Mutator
175             Title : unset_matrix
176             Usage : $taxa->unset_matrix($matrix);
177             Function: Disassociates matrix from the
178             invocant taxa object (i.e.
179             removes reference).
180             Returns : Modified object.
181             Args : A Bio::Phylo::Matrices::Matrix object
182              
183             =cut
184              
185             sub unset_matrix {
186 0     0 1 0 my ( $self, $matrix ) = @_;
187 0         0 $logger->debug("unsetting matrix $matrix");
188 0 0       0 if ( looks_like_object $matrix, $MATRIX ) {
189 0         0 $matrix->unset_taxa();
190             }
191 0         0 return $self;
192             }
193              
194             =back
195              
196             =head2 ACCESSORS
197              
198             =over
199              
200             =item get_forests()
201              
202             Gets all associated Bio::Phylo::Forest objects.
203              
204             Type : Accessor
205             Title : get_forests
206             Usage : @forests = @{ $taxa->get_forests };
207             Function: Retrieves forests associated
208             with the current taxa object.
209             Returns : An ARRAY reference of
210             Bio::Phylo::Forest objects.
211             Args : None.
212              
213             =cut
214              
215             sub get_forests {
216 0     0 1 0 my $self = shift;
217 0         0 return $mediator->get_link(
218             '-source' => $self,
219             '-type' => $FOREST,
220             );
221             }
222              
223             =item get_matrices()
224              
225             Gets all associated Bio::Phylo::Matrices::Matrix objects.
226              
227             Type : Accessor
228             Title : get_matrices
229             Usage : @matrices = @{ $taxa->get_matrices };
230             Function: Retrieves matrices associated
231             with the current taxa object.
232             Returns : An ARRAY reference of
233             Bio::Phylo::Matrices::Matrix objects.
234             Args : None.
235              
236             =cut
237              
238             sub get_matrices {
239 0     0 1 0 my $self = shift;
240 0         0 return $mediator->get_link(
241             '-source' => $self,
242             '-type' => $MATRIX,
243             );
244             }
245              
246             =item get_ntax()
247              
248             Gets number of contained Bio::Phylo::Taxa::Taxon objects.
249              
250             Type : Accessor
251             Title : get_ntax
252             Usage : my $ntax = $taxa->get_ntax;
253             Function: Retrieves the number of taxa for the invocant.
254             Returns : INT
255             Args : None.
256             Comments:
257              
258             =cut
259              
260             sub get_ntax {
261 22     22 1 47 my $self = shift;
262 22         32 return scalar @{ $self->get_entities };
  22         84  
263             }
264              
265             =back
266              
267             =head2 METHODS
268              
269             =over
270              
271             =item merge_by_name()
272              
273             Merges argument Bio::Phylo::Taxa object with invocant.
274              
275             Type : Method
276             Title : merge_by_name
277             Usage : $merged = $taxa->merge_by_name($other_taxa);
278             Function: Merges two or more taxa objects such that
279             internally different taxon objects
280             with the same name become a single
281             object with the combined references
282             to datum objects and node objects
283             contained by the two.
284             Returns : A merged Bio::Phylo::Taxa object.
285             Args : Bio::Phylo::Taxa objects.
286              
287             =cut
288              
289             sub merge_by_name {
290 0     0 1 0 my $merged = $factory->create_taxa( '-name' => 'Merged' );
291 0         0 for my $taxa (@_) {
292            
293             # build a hash of what we have so far
294 0         0 my %taxon_by_name = map { $_->get_name => $_ } @{ $merged->get_entities };
  0         0  
  0         0  
295            
296             # iterate over focal taxa block
297 0         0 for my $taxon ( @{ $taxa->get_entities } ) {
  0         0  
298 0         0 my $name = $taxon->get_name;
299            
300             # retrieve or create target taxon
301 0         0 my $target;
302 0 0       0 if ( $taxon_by_name{$name} ) {
303 0         0 $target = $taxon_by_name{$name};
304             }
305             else {
306 0         0 $target = $factory->create_taxon( '-name' => $name );
307 0         0 $merged->insert($target);
308 0         0 $taxon_by_name{$name} = $target;
309             }
310            
311             # copy over data, metadata and node links
312 0         0 $_->set_taxon($target) for @{ $taxon->get_data };
  0         0  
313 0         0 $_->set_taxon($target) for @{ $taxon->get_nodes };
  0         0  
314 0         0 $target->add_meta($_) for @{ $taxon->get_meta };
  0         0  
315             }
316             }
317 0         0 return $merged;
318             }
319              
320             =item merge_by_meta()
321              
322             Merges argument Bio::Phylo::Taxa object with invocant.
323              
324             Type : Method
325             Title : merge_by_meta
326             Usage : $taxa->merge_by_name('dc:identifier',$other_taxa);
327             Function: Merges two taxa objects such that
328             internally different taxon objects
329             with the same annotation value become
330             a single object with the combined references
331             to datum objects, node objects and
332             metadata annotations contained by
333             the two.
334             Returns : A merged Bio::Phylo::Taxa object.
335             Args : a CURIE predicate and Bio::Phylo::Taxa objects.
336              
337             =cut
338              
339             sub merge_by_meta {
340 1     1 1 9 my ( $self, $predicate, @others ) = @_;
341 1         4 push @others, $self;
342 1         6 my $merged = $factory->create_taxa;
343 1         4 for my $taxa ( @others ) {
344            
345             my %object_by_value =
346 10         23 map { $_->get_meta_object($predicate) => $_ }
347 2         5 @{ $merged->get_entities };
  2         6  
348            
349 2         4 for my $taxon ( @{ $taxa->get_entities } ) {
  2         6  
350            
351             # instantiate or fetch taxon based on predicate value
352 20         46 my $value = $taxon->get_meta_object($predicate);
353 20   66     84 my $target = $object_by_value{$value} || $factory->create_taxon();
354            
355             # copy links and metadata
356 20         23 $_->set_taxon($target) for @{ $taxon->get_data };
  20         50  
357 20         26 $_->set_taxon($target) for @{ $taxon->get_nodes };
  20         40  
358 20         26 $target->add_meta($_) for @{ $taxon->get_meta };
  20         38  
359            
360             # copy name to bp:contributing_name
361 20 50       45 if ( my $name = $taxon->get_name ) {
362 0         0 $target->add_meta(
363             $factory->create_meta(
364             '-namespaces' => { 'bp' => _NS_BIOPHYLO_ },
365             '-triple' => { 'bp:contributing_name' => $name }
366             )
367             );
368             }
369            
370             # add to hash and block if newly created
371 20 100       43 if ( not exists $object_by_value{$value} ) {
372 10         27 $merged->insert($target);
373 10         24 $object_by_value{$value} = $target;
374             }
375             }
376             }
377 1         3 return $merged;
378             }
379              
380             =item prune_taxa()
381              
382             Removes taxa by name or object
383              
384             Type : Method
385             Title : prune_taxa
386             Usage : $taxa->prune_taxa([$t1, $t2]);
387             Function: Prunes taxa from the taxa object
388             Returns : A pruned Bio::Phylo::Taxa object.
389             Args : An array reference of taxa, either by name or as taxon objects
390              
391             =cut
392              
393             sub prune_taxa {
394 0     0 1 0 my ( $self, $arrayref ) = @_;
395 0 0       0 if ( ref($arrayref) eq 'ARRAY' ) {
396 0         0 for my $t ( @{ $arrayref } ) {
  0         0  
397 0 0       0 if ( not ref $t ) {
    0          
398 0 0       0 if ( my $obj = $self->get_by_name($t) ) {
399 0         0 $self->delete($obj);
400             }
401             else {
402 0         0 $logger->warn("Couldn't find taxon with name '$t'");
403             }
404             }
405             elsif ( looks_like_object $t, _TAXON_ ) {
406 0         0 $self->delete($t);
407             }
408             }
409             }
410             else {
411 0         0 throw 'BadArgs' => 'Argument is not an array reference';
412             }
413 0         0 return $self;
414             }
415              
416              
417             =item to_nexus()
418              
419             Serializes invocant to nexus format.
420              
421             Type : Format convertor
422             Title : to_nexus
423             Usage : my $block = $taxa->to_nexus;
424             Function: Converts $taxa into a nexus taxa block.
425             Returns : Nexus taxa block (SCALAR).
426             Args : -links => 1 (optional, adds 'TITLE' token)
427             Comments:
428              
429             =cut
430              
431             sub to_nexus {
432 2     2 1 6 my ( $self, %args ) = @_;
433             my %m = (
434             'header' => ( $args{'-header'} && '#NEXUS' ) || '',
435             'title' =>
436             ( $args{'-links'} && sprintf 'TITLE %s;', $self->get_nexus_name )
437             || '',
438             'version' => $self->VERSION,
439             'ntax' => $self->get_ntax,
440             'class' => ref $self,
441             'time' => my $time = localtime(),
442             'taxlabels' => join "\n\t\t",
443 2   50     62 map { $_->get_nexus_name } @{ $self->get_entities }
  22   50     47  
  2         8  
444             );
445 2         37 return <<TEMPLATE;
446             $m{header}
447             BEGIN TAXA;
448             [! Taxa block written by $m{class} $m{version} on $m{time} ]
449             $m{title}
450             DIMENSIONS NTAX=$m{ntax};
451             TAXLABELS
452             $m{taxlabels}
453             ;
454             END;
455             TEMPLATE
456             }
457              
458             =begin comment
459              
460             Type : Internal method
461             Title : _container
462             Usage : $taxa->_container;
463             Function:
464             Returns : CONSTANT
465             Args :
466              
467             =end comment
468              
469             =cut
470              
471 23     23   44 sub _container { $CONTAINER }
472              
473             =begin comment
474              
475             Type : Internal method
476             Title : _type
477             Usage : $taxa->_type;
478             Function:
479             Returns : SCALAR
480             Args :
481              
482             =end comment
483              
484             =cut
485              
486 565     565   949 sub _type { $TYPE }
487 1     1   3 sub _tag { 'otus' }
488              
489             =back
490              
491             =cut
492              
493             # podinherit_insert_token
494              
495             =head1 SEE ALSO
496              
497             There is a mailing list at L<https://groups.google.com/forum/#!forum/bio-phylo>
498             for any user or developer questions and discussions.
499              
500             =over
501              
502             =item L<Bio::Phylo::Listable>
503              
504             The L<Bio::Phylo::Taxa> object inherits from the L<Bio::Phylo::Listable>
505             object. Look there for more methods applicable to the taxa object.
506              
507             =item L<Bio::Phylo::Manual>
508              
509             Also see the manual: L<Bio::Phylo::Manual> and L<http://rutgervos.blogspot.com>.
510              
511             =back
512              
513             =head1 CITATION
514              
515             If you use Bio::Phylo in published research, please cite it:
516              
517             B<Rutger A Vos>, B<Jason Caravas>, B<Klaas Hartmann>, B<Mark A Jensen>
518             and B<Chase Miller>, 2011. Bio::Phylo - phyloinformatic analysis using Perl.
519             I<BMC Bioinformatics> B<12>:63.
520             L<http://dx.doi.org/10.1186/1471-2105-12-63>
521              
522             =cut
523              
524             }
525             1;