3 # BioPerl module for Bio::TreeIO::TreeEventBuilder
5 # Cared for by Jason Stajich <jason@bioperl.org>
7 # Copyright Jason Stajich
9 # You may distribute this module under the same terms as perl itself
11 # POD documentation - main docs before the code
15 Bio::TreeIO::TreeEventBuilder - Build Bio::Tree::Tree's and
16 Bio::Tree::Node's from Events
24 This object will take events and build a Bio::Tree::TreeI compliant
25 object makde up of Bio::Tree::NodeI objects.
31 User feedback is an integral part of the evolution of this and other
32 Bioperl modules. Send your comments and suggestions preferably to
33 the Bioperl mailing list. Your participation is much appreciated.
35 bioperl-l@bioperl.org - General discussion
36 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
40 Report bugs to the Bioperl bug tracking system to help us keep track
41 of the bugs and their resolution. Bug reports can be submitted via the
44 http://bugzilla.open-bio.org/
46 =head1 AUTHOR - Jason Stajich
48 Email jason-at-bioperl.org
52 The rest of the documentation details each of the object methods.
53 Internal methods are usually preceded with a _
58 # Let the code begin...
61 package Bio
::TreeIO
::TreeEventBuilder
;
67 use base
qw(Bio::Root::Root Bio::Event::EventHandlerI);
72 Usage : my $obj = Bio::TreeIO::TreeEventBuilder->new();
73 Function: Builds a new Bio::TreeIO::TreeEventBuilder object
74 Returns : Bio::TreeIO::TreeEventBuilder
81 my($class,@args) = @_;
83 my $self = $class->SUPER::new
(@args);
84 my ($treetype, $nodetype) = $self->_rearrange([qw(TREETYPE
86 $treetype ||= 'Bio::Tree::Tree';
87 $nodetype ||= 'Bio::Tree::Node';
90 $self->_load_module($treetype);
91 $self->_load_module($nodetype);
95 $self->throw("Could not load module $treetype or $nodetype. \n$@\n")
97 $self->treetype($treetype);
98 $self->nodetype($nodetype);
99 $self->{'_treelevel'} = 0;
106 Usage : $obj->treetype($newval)
108 Returns : value of treetype
109 Args : newvalue (optional)
115 my ($self,$value) = @_;
116 if( defined $value) {
117 $self->{'treetype'} = $value;
119 return $self->{'treetype'};
125 Usage : $obj->nodetype($newval)
127 Returns : value of nodetype
128 Args : newvalue (optional)
134 my ($self,$value) = @_;
135 if( defined $value) {
136 $self->{'nodetype'} = $value;
138 return $self->{'nodetype'};
146 =head2 start_document
148 Title : start_document
149 Usage : $handler->start_document
150 Function: Begins a Tree event cycle
158 $self->{'_lastitem'} = {};
159 $self->{'_currentitems'} = [];
160 $self->{'_currentnodes'} = [];
167 Usage : my @trees = $parser->end_document
168 Function: Finishes a Phylogeny cycle
169 Returns : An array Bio::Tree::TreeI
175 my ($self,$label) = @_;
176 my $root = $self->nodetype->new(
178 -verbose
=> $self->verbose);
179 # aggregate the nodes into trees basically ad-hoc.
180 while ( @
{$self->{'_currentnodes'}} ) {
181 my ($node) = ( shift @
{$self->{'_currentnodes'}});
182 $root->add_Descendent($node);
185 $self->debug("Root node is " . $root->to_string()."\n");
186 if( $self->verbose > 0 ) {
187 foreach my $node ( $root->get_Descendents ) {
188 $self->debug("node is ". $node->to_string(). "\n");
191 my $tree = $self->treetype->new(-verbose
=> $self->verbose,
198 Title : start_element
203 Args : $data => hashref with key 'Name'
208 my ($self,$data) =@_;
209 $self->{'_lastitem'}->{$data->{'Name'}}++;
211 $self->debug("starting element: $data->{Name}\n");
212 push @
{$self->{'_lastitem'}->{'current'}},$data->{'Name'};
216 if( $data->{'Name'} eq 'node' ) {
217 push @
{$self->{'_currentitems'}}, \
%data;
218 } elsif ( $data->{Name
} eq 'tree' ) {
219 $self->{'_treelevel'}++;
229 Args : $data => hashref with key 'Name'
234 my ($self,$data) = @_;
236 $self->debug("end of element: $data->{Name}\n");
237 # this is the stack where we push/pop items from it
238 my $curcount = scalar @
{$self->{'_currentnodes'}};
239 my $level = $self->{'_treelevel'};
240 my $levelct = $self->{'_nodect'}->[$self->{'_treelevel'}+1] || 0;
242 if( $data->{'Name'} eq 'node' ) {
244 my $node = pop @
{$self->{'_currentitems'}};
246 $tnode = $self->nodetype->new( -verbose
=> $self->verbose,
248 $self->debug( "new node will be ".$tnode->to_string."\n");
249 if ( !$node->{'-leaf'} && $levelct > 0) {
250 $self->debug(join(',', map { $_->to_string }
251 @
{$self->{'_currentnodes'}}). "\n");
252 $self->throw("something wrong with event construction treelevel ".
253 "$level is recorded as having $levelct nodes ".
254 "but current nodes at this level is $curcount\n")
255 if( $levelct > $curcount);
256 for ( splice( @
{$self->{'_currentnodes'}}, - $levelct)) {
257 $self->debug("adding desc: " . $_->to_string . "\n");
258 $tnode->add_Descendent($_);
260 $self->{'_nodect'}->[$self->{'_treelevel'}+1] = 0;
262 push @
{$self->{'_currentnodes'}}, $tnode;
263 $self->{'_nodect'}->[$self->{'_treelevel'}]++;
265 $self->debug ("added node: nodes in stack is $curcount, treelevel: $level, nodect: $levelct\n");
267 } elsif( $data->{'Name'} eq 'tree' ) {
268 $self->debug("end of tree: nodes in stack is $curcount\n");
269 $self->{'_treelevel'}--;
272 $self->{'_lastitem'}->{ $data->{'Name'} }--;
274 pop @
{$self->{'_lastitem'}->{'current'}};
293 return 0 if ! defined $self->{'_lastitem'} ||
294 ! defined $self->{'_lastitem'}->{'current'}->[-1];
295 return ($e eq $self->{'_lastitem'}->{'current'}->[-1]);
299 =head2 within_element
301 Title : within_element
313 return $self->{'_lastitem'}->{$e};
319 Usage : $handler->characters($text);
320 Function: Processes characters
329 if( $self->within_element('node') ) {
330 my $hash = pop @
{$self->{'_currentitems'}};
331 if( $self->in_element('bootstrap') ) {
332 # leading/trailing Whitespace-B-Gone
333 $ch =~ s/^\s+//; $ch =~ s/\s+$//;
334 $hash->{'-bootstrap'} = $ch;
335 } elsif( $self->in_element('branch_length') ) {
336 # leading/trailing Whitespace-B-Gone
337 $ch =~ s/^\s+//; $ch =~ s/\s+$//;
338 $hash->{'-branch_length'} = $ch;
339 } elsif( $self->in_element('id') ) {
340 $hash->{'-id'} = $ch;
341 } elsif( $self->in_element('description') ) {
342 $hash->{'-desc'} = $ch;
343 } elsif ( $self->in_element('tag_name') ) {
344 $hash->{'-NHXtagname'} = $ch;
345 } elsif ( $self->in_element('tag_value') ) {
346 $hash->{'-nhx'}->{$hash->{'-NHXtagname'}} = $ch;
347 delete $hash->{'-NHXtagname'};
348 } elsif( $self->in_element('leaf') ) {
349 $hash->{'-leaf'} = $ch;
351 push @
{$self->{'_currentitems'}}, $hash;
353 $self->debug("chars: $ch\n");