3 # BioPerl module for Bio::TreeIO::TreeEventBuilder
5 # Please direct questions and support issues to <bioperl-l@bioperl.org>
7 # Cared for by Jason Stajich <jason@bioperl.org>
9 # Copyright Jason Stajich
11 # You may distribute this module under the same terms as perl itself
13 # POD documentation - main docs before the code
17 Bio::TreeIO::TreeEventBuilder - Build Bio::Tree::Tree's and
18 Bio::Tree::Node's from Events
26 This object will take events and build a Bio::Tree::TreeI compliant
27 object makde up of Bio::Tree::NodeI objects.
33 User feedback is an integral part of the evolution of this and other
34 Bioperl modules. Send your comments and suggestions preferably to
35 the Bioperl mailing list. Your participation is much appreciated.
37 bioperl-l@bioperl.org - General discussion
38 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
42 Please direct usage questions or support issues to the mailing list:
44 L<bioperl-l@bioperl.org>
46 rather than to the module maintainer directly. Many experienced and
47 reponsive experts will be able look at the problem and quickly
48 address it. Please include a thorough description of the problem
49 with code and data examples if at all possible.
53 Report bugs to the Bioperl bug tracking system to help us keep track
54 of the bugs and their resolution. Bug reports can be submitted via the
57 http://bugzilla.open-bio.org/
59 =head1 AUTHOR - Jason Stajich
61 Email jason-at-bioperl.org
65 The rest of the documentation details each of the object methods.
66 Internal methods are usually preceded with a _
71 # Let the code begin...
74 package Bio
::TreeIO
::TreeEventBuilder
;
80 use base
qw(Bio::Root::Root Bio::Event::EventHandlerI);
85 Usage : my $obj = Bio::TreeIO::TreeEventBuilder->new();
86 Function: Builds a new Bio::TreeIO::TreeEventBuilder object
87 Returns : Bio::TreeIO::TreeEventBuilder
94 my($class,@args) = @_;
96 my $self = $class->SUPER::new
(@args);
97 my ($treetype, $nodetype) = $self->_rearrange([qw(TREETYPE
99 $treetype ||= 'Bio::Tree::Tree';
100 $nodetype ||= 'Bio::Tree::Node';
103 $self->_load_module($treetype);
104 $self->_load_module($nodetype);
108 $self->throw("Could not load module $treetype or $nodetype. \n$@\n")
110 $self->treetype($treetype);
111 $self->nodetype($nodetype);
112 $self->{'_treelevel'} = 0;
119 Usage : $obj->treetype($newval)
121 Returns : value of treetype
122 Args : newvalue (optional)
128 my ($self,$value) = @_;
129 if( defined $value) {
130 $self->{'treetype'} = $value;
132 return $self->{'treetype'};
138 Usage : $obj->nodetype($newval)
140 Returns : value of nodetype
141 Args : newvalue (optional)
147 my ($self,$value) = @_;
148 if( defined $value) {
149 $self->{'nodetype'} = $value;
151 return $self->{'nodetype'};
159 =head2 start_document
161 Title : start_document
162 Usage : $handler->start_document
163 Function: Begins a Tree event cycle
171 $self->{'_lastitem'} = {};
172 $self->{'_currentitems'} = [];
173 $self->{'_currentnodes'} = [];
180 Usage : my @trees = $parser->end_document
181 Function: Finishes a Phylogeny cycle
182 Returns : An array Bio::Tree::TreeI
188 my ($self,$label) = @_;
189 my $root = $self->nodetype->new(
191 -verbose
=> $self->verbose);
192 # aggregate the nodes into trees basically ad-hoc.
193 while ( @
{$self->{'_currentnodes'}} ) {
194 my ($node) = ( shift @
{$self->{'_currentnodes'}});
195 $root->add_Descendent($node);
198 $self->debug("Root node is " . $root->to_string()."\n");
199 if( $self->verbose > 0 ) {
200 foreach my $node ( $root->get_Descendents ) {
201 $self->debug("node is ". $node->to_string(). "\n");
204 my $tree = $self->treetype->new(-verbose
=> $self->verbose,
211 Title : start_element
216 Args : $data => hashref with key 'Name'
221 my ($self,$data) =@_;
222 $self->{'_lastitem'}->{$data->{'Name'}}++;
224 $self->debug("starting element: $data->{Name}\n");
225 push @
{$self->{'_lastitem'}->{'current'}},$data->{'Name'};
229 if( $data->{'Name'} eq 'node' ) {
230 push @
{$self->{'_currentitems'}}, \
%data;
231 } elsif ( $data->{Name
} eq 'tree' ) {
232 $self->{'_treelevel'}++;
242 Args : $data => hashref with key 'Name'
247 my ($self,$data) = @_;
249 $self->debug("end of element: $data->{Name}\n");
250 # this is the stack where we push/pop items from it
251 my $curcount = scalar @
{$self->{'_currentnodes'}};
252 my $level = $self->{'_treelevel'};
253 my $levelct = $self->{'_nodect'}->[$self->{'_treelevel'}+1] || 0;
255 if( $data->{'Name'} eq 'node' ) {
257 my $node = pop @
{$self->{'_currentitems'}};
259 $tnode = $self->nodetype->new( -verbose
=> $self->verbose,
261 $self->debug( "new node will be ".$tnode->to_string."\n");
262 if ( !$node->{'-leaf'} && $levelct > 0) {
263 $self->debug(join(',', map { $_->to_string }
264 @
{$self->{'_currentnodes'}}). "\n");
265 $self->throw("something wrong with event construction treelevel ".
266 "$level is recorded as having $levelct nodes ".
267 "but current nodes at this level is $curcount\n")
268 if( $levelct > $curcount);
269 for ( splice( @
{$self->{'_currentnodes'}}, - $levelct)) {
270 $self->debug("adding desc: " . $_->to_string . "\n");
271 $tnode->add_Descendent($_);
273 $self->{'_nodect'}->[$self->{'_treelevel'}+1] = 0;
275 push @
{$self->{'_currentnodes'}}, $tnode;
276 $self->{'_nodect'}->[$self->{'_treelevel'}]++;
278 $self->debug ("added node: nodes in stack is $curcount, treelevel: $level, nodect: $levelct\n");
280 } elsif( $data->{'Name'} eq 'tree' ) {
281 $self->debug("end of tree: nodes in stack is $curcount\n");
282 $self->{'_treelevel'}--;
285 $self->{'_lastitem'}->{ $data->{'Name'} }--;
287 pop @
{$self->{'_lastitem'}->{'current'}};
306 return 0 if ! defined $self->{'_lastitem'} ||
307 ! defined $self->{'_lastitem'}->{'current'}->[-1];
308 return ($e eq $self->{'_lastitem'}->{'current'}->[-1]);
312 =head2 within_element
314 Title : within_element
326 return $self->{'_lastitem'}->{$e};
332 Usage : $handler->characters($text);
333 Function: Processes characters
342 if( $self->within_element('node') ) {
343 my $hash = pop @
{$self->{'_currentitems'}};
344 if( $self->in_element('bootstrap') ) {
345 # leading/trailing Whitespace-B-Gone
346 $ch =~ s/^\s+//; $ch =~ s/\s+$//;
347 $hash->{'-bootstrap'} = $ch;
348 } elsif( $self->in_element('branch_length') ) {
349 # leading/trailing Whitespace-B-Gone
350 $ch =~ s/^\s+//; $ch =~ s/\s+$//;
351 $hash->{'-branch_length'} = $ch;
352 } elsif( $self->in_element('id') ) {
353 $hash->{'-id'} = $ch;
354 } elsif( $self->in_element('description') ) {
355 $hash->{'-desc'} = $ch;
356 } elsif ( $self->in_element('tag_name') ) {
357 $hash->{'-NHXtagname'} = $ch;
358 } elsif ( $self->in_element('tag_value') ) {
359 $hash->{'-nhx'}->{$hash->{'-NHXtagname'}} = $ch;
360 delete $hash->{'-NHXtagname'};
361 } elsif( $self->in_element('leaf') ) {
362 $hash->{'-leaf'} = $ch;
364 push @
{$self->{'_currentitems'}}, $hash;
366 $self->debug("chars: $ch\n");