###################################################### # TaxaBlock.pm ###################################################### # Author: Chengzhi Liang, Weigang Qiu, Eugene Melamud, Peter Yang, Thomas Hladish # $Id: TaxaBlock.pm,v 1.43 2007/09/24 04:52:14 rvos Exp $ #################### START POD DOCUMENTATION ################## =head1 NAME Bio::NEXUS::TaxaBlock - Represents TAXA block of a NEXUS file =head1 SYNOPSIS if ( $type =~ /taxa/i ) { $block_object = new Bio::NEXUS::TaxaBlock($type, $block, $verbose); } =head1 DESCRIPTION If a NEXUS block is a taxa block, this module parses the block and stores the taxonomic data. =head1 FEEDBACK All feedback (bugs, feature enhancements, etc.) are greatly appreciated. =head1 AUTHORS Chengzhi Liang (liangc@umbi.umd.edu) Weigang Qiu (weigang@genectr.hunter.cuny.edu) Eugene Melamud (melamud@carb.nist.gov) Peter Yang (pyang@rice.edu) Thomas Hladish (tjhladish at yahoo) =head1 VERSION $Revision: 1.43 $ =head1 METHODS =cut package Bio::NEXUS::TaxaBlock; use strict; #use Carp;# XXX this is not used, might as well not import it! #use Data::Dumper; # XXX this is not used, might as well not import it! use Bio::NEXUS::Functions; use Bio::NEXUS::Node; use Bio::NEXUS::Block; use Bio::NEXUS::TaxUnit; use Bio::NEXUS::Util::Logger; use Bio::NEXUS::Util::Exceptions 'throw'; use vars qw(@ISA $VERSION $AUTOLOAD); use Bio::NEXUS; $VERSION = $Bio::NEXUS::VERSION; @ISA = qw(Bio::NEXUS::Block); my $logger = Bio::NEXUS::Util::Logger->new(); =head2 new Title : new Usage : block_object = new Bio::NEXUS::TaxaBlock($block_type, $commands, $verbose); Function: Creates a new Bio::NEXUS::TaxaBlock object Returns : Bio::NEXUS::TaxaBlock object Args : type (string), the commands/comments to parse (array ref), and a verbose flag (0 or 1; optional) =cut sub new { my ( $class, $type, $commands, $verbose ) = @_; if ( not $type ) { ( $type = lc $class ) =~ s/Bio::NEXUS::(.+)Block/$1/i; } my $self = { 'type' => $type, }; bless $self, $class; if ( defined $commands and @$commands ) { $self->_parse_block( $commands, $verbose ); } return $self; } =head2 is_taxon Title : is_taxon Usage : $block->is_taxon($query_taxonlabel); Function: Validates OTU names/taxlabels Returns : Returns taxlabel if true, undef if false Args : Query taxon label =cut sub is_taxon { my ( $self, $query_taxon, $verbose ) = @_; my $taxlabels = $self->get_taxlabels(); for my $taxlabel (@$taxlabels) { if ( $taxlabel eq $query_taxon ) { return $taxlabel } } $logger->info("$query_taxon is not a valid OTU name"); return undef; } =head2 get_ntax Title : get_ntax Usage : $block->get_ntax(); Function: Returns the dimensions (that is, ntax) of the block Returns : dimensions (integer) Args : none =cut sub get_ntax { my ($self) = @_; return scalar @{ $self->get_taxlabels() }; } =head2 rename_otus Title : rename_otus Usage : $block->rename_otus(\%translation); Function: Renames all the OTUs to something else Returns : none Args : hash containing translation =cut sub rename_otus { my ( $self, $translate ) = @_; my $taxlabels = $self->get_taxlabels(); my $newtaxlabels; for my $taxlabel (@$taxlabels) { $taxlabel = $$translate{$taxlabel} if $$translate{$taxlabel}; push( @$newtaxlabels, $taxlabel ); } $self->set_taxlabels($newtaxlabels); } =head2 add_otu_clone Title : add_otu_clone Usage : ... Function: ... Returns : ... Args : ... =cut sub add_otu_clone { # todo: # rename the method my ( $self, $original_otu_name, $copy_otu_name ) = @_; # print "Warning: Bio::NEXUS::TaxaBlock::add_otu_clone() method not fully implemented\n"; if (defined $self->{'dimensions'}{'ntax'}) { $self->{'dimensions'}{'ntax'}++; } else { # the execution should never reach this point, # b/c if an OTU is being cloned, ntax should # be > or = '1' throw 'BadArgs' => "add_otu_clone(): at least 1 otu exists, but 'ntax' is not initialized"; } $self->add_taxlabel($copy_otu_name); } =head2 equals Name : equals Usage : $taxa->equals($another); Function: compare if two Bio::NEXUS::TaxaBlock objects are equal Returns : boolean Args : a Bio::NEXUS::TaxaBlock object =cut sub equals { my ( $self, $block ) = @_; if ( ! $self->SUPER::equals( $block ) ) { return 0; } my @labels1 = @{ $self->get_taxlabels() }; my @labels2 = @{ $block->get_taxlabels() }; if ( @labels1 != @labels2 ) { return 0; } @labels1 = sort { $a cmp $b } @labels1; @labels2 = sort { $a cmp $b } @labels2; for my $i ( 0 .. $#labels1 ) { if ( $labels1[$i] ne $labels2[$i] ) { return 0; } } return 1; } =begin comment Name : _write Usage : $taxa->_write($filehandle, $verbose); Function: Writes NEXUS block from stored data Returns : none Args : none =end comment =cut sub _write { my ( $self, $fh, $verbose ) = @_; $fh ||= \*STDOUT; my $ntax = $self->get_ntax(); $self->SUPER::_write($fh); print $fh "\tDIMENSIONS ntax=$ntax;\n"; print $fh "\tTAXLABELS "; for my $OTU ( @{ $self->get_taxlabels() } ) { $OTU = _nexus_formatted($OTU); print $fh " $OTU"; } print $fh ";\nEND;\n"; } sub AUTOLOAD { return if $AUTOLOAD =~ /DESTROY$/; my $package_name = __PACKAGE__ . '::'; # The following methods are deprecated and are temporarily supported # via a warning and a redirection my %synonym_for = ( "${package_name}parse_labels" => "${package_name}_parse_taxlabels", ); if ( defined $synonym_for{$AUTOLOAD} ) { $logger->warn("$AUTOLOAD() is deprecated; use $synonym_for{$AUTOLOAD}() instead"); goto &{ $synonym_for{$AUTOLOAD} }; } else { throw 'UnkownMethod' => "Unknown method $AUTOLOAD called"; } } 1;