2 # BioPerl module for Bio::TreeIO::TreeEventBuilder
4 # Please direct questions and support issues to <bioperl-l@bioperl.org>
6 # Cared for by Jason Stajich <jason@bioperl.org>
8 # Copyright Jason Stajich
10 # You may distribute this module under the same terms as perl itself
12 # POD documentation - main docs before the code
16 Bio::TreeIO::TreeEventBuilder - Build Bio::Tree::Tree's and
17 Bio::Tree::Node's from Events
25 This object will take events and build a Bio::Tree::TreeI compliant
26 object makde up of Bio::Tree::NodeI objects.
32 User feedback is an integral part of the evolution of this and other
33 Bioperl modules. Send your comments and suggestions preferably to
34 the Bioperl mailing list. Your participation is much appreciated.
36 bioperl-l@bioperl.org - General discussion
37 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
41 Please direct usage questions or support issues to the mailing list:
43 I<bioperl-l@bioperl.org>
45 rather than to the module maintainer directly. Many experienced and
46 reponsive experts will be able look at the problem and quickly
47 address it. Please include a thorough description of the problem
48 with code and data examples if at all possible.
52 Report bugs to the Bioperl bug tracking system to help us keep track
53 of the bugs and their resolution. Bug reports can be submitted via the
56 https://github.com/bioperl/bioperl-live/issues
58 =head1 AUTHOR - Jason Stajich
60 Email jason-at-bioperl.org
64 The rest of the documentation details each of the object methods.
65 Internal methods are usually preceded with a _
70 # Let the code begin...
73 package Bio
::TreeIO
::TreeEventBuilder
;
79 use base
qw(Bio::Root::Root Bio::Event::EventHandlerI);
84 Usage : my $obj = Bio::TreeIO::TreeEventBuilder->new();
85 Function: Builds a new Bio::TreeIO::TreeEventBuilder object
86 Returns : Bio::TreeIO::TreeEventBuilder
93 my($class,@args) = @_;
95 my $self = $class->SUPER::new
(@args);
96 my ($treetype, $nodetype) = $self->_rearrange([qw(TREETYPE
98 $treetype ||= 'Bio::Tree::Tree';
99 $nodetype ||= 'Bio::Tree::Node';
102 $self->_load_module($treetype);
103 $self->_load_module($nodetype);
107 $self->throw("Could not load module $treetype or $nodetype. \n$@\n")
109 $self->treetype($treetype);
110 $self->nodetype($nodetype);
111 $self->{'_treelevel'} = 0;
118 Usage : $obj->treetype($newval)
120 Returns : value of treetype
121 Args : newvalue (optional)
127 my ($self,$value) = @_;
128 if( defined $value) {
129 $self->{'treetype'} = $value;
131 return $self->{'treetype'};
137 Usage : $obj->nodetype($newval)
139 Returns : value of nodetype
140 Args : newvalue (optional)
146 my ($self,$value) = @_;
147 if( defined $value) {
148 $self->{'nodetype'} = $value;
150 return $self->{'nodetype'};
158 =head2 start_document
160 Title : start_document
161 Usage : $handler->start_document
162 Function: Begins a Tree event cycle
170 $self->{'_lastitem'} = {};
171 $self->{'_currentitems'} = [];
172 $self->{'_currentnodes'} = [];
179 Usage : my @trees = $parser->end_document
180 Function: Finishes a Phylogeny cycle
181 Returns : An array Bio::Tree::TreeI
187 my ($self,$label) = @_;
189 my ($root) = @
{$self->{'_currentnodes'}};
191 $self->debug("Root node is " . $root->to_string()."\n");
192 if( $self->verbose > 0 ) {
193 foreach my $node ( $root->get_Descendents ) {
194 $self->debug("node is ". $node->to_string(). "\n");
197 my $tree = $self->treetype->new(-verbose
=> $self->verbose,
204 Title : start_element
209 Args : $data => hashref with key 'Name'
214 my ($self,$data) =@_;
215 $self->{'_lastitem'}->{$data->{'Name'}}++;
217 $self->debug("starting element: $data->{Name}\n");
218 push @
{$self->{'_lastitem'}->{'current'}},$data->{'Name'};
222 if( $data->{'Name'} eq 'node' ) {
223 push @
{$self->{'_currentitems'}}, \
%data;
224 $self->{'_treelevel'}++;
225 } elsif ( $data->{Name
} eq 'tree' ) {
235 Args : $data => hashref with key 'Name'
240 my ($self,$data) = @_;
242 $self->debug("end of element: $data->{Name}\n");
243 # this is the stack where we push/pop items from it
244 my $curcount = scalar @
{$self->{'_currentnodes'}};
245 my $level = $self->{'_treelevel'};
246 my $levelct = $self->{'_nodect'}->[$self->{'_treelevel'}+1] || 0;
248 if( $data->{'Name'} eq 'node' ) {
250 my $node = pop @
{$self->{'_currentitems'}};
252 $tnode = $self->nodetype->new( -verbose
=> $self->verbose,
254 $self->debug( "new node will be ".$tnode->to_string."\n");
255 if ( !$node->{'-leaf'} && $levelct > 0) {
256 $self->debug(join(',', map { $_->to_string }
257 @
{$self->{'_currentnodes'}}). "\n");
258 $self->throw("something wrong with event construction treelevel ".
259 "$level is recorded as having $levelct nodes ".
260 "but current nodes at this level is $curcount\n")
261 if( $levelct > $curcount);
262 for ( splice( @
{$self->{'_currentnodes'}}, - $levelct)) {
263 $self->debug("adding desc: " . $_->to_string . "\n");
264 $tnode->add_Descendent($_);
266 $self->{'_nodect'}->[$self->{'_treelevel'}+1] = 0;
268 push @
{$self->{'_currentnodes'}}, $tnode;
269 $self->{'_nodect'}->[$self->{'_treelevel'}]++;
271 $curcount = scalar @
{$self->{'_currentnodes'}};
272 $self->debug ("added node: count is now $curcount, treelevel: $level, nodect: $levelct\n");
274 $self->{'_treelevel'}--;
275 } elsif( $data->{'Name'} eq 'tree' ) {
276 $self->debug("end of tree: nodes in stack is $curcount\n");
279 $self->{'_lastitem'}->{ $data->{'Name'} }--;
280 pop @
{$self->{'_lastitem'}->{'current'}};
299 return 0 if ! defined $self->{'_lastitem'} ||
300 ! defined $self->{'_lastitem'}->{'current'}->[-1];
301 return ($e eq $self->{'_lastitem'}->{'current'}->[-1]);
305 =head2 within_element
307 Title : within_element
319 return $self->{'_lastitem'}->{$e};
325 Usage : $handler->characters($text);
326 Function: Processes characters
335 if( $self->within_element('node') ) {
336 my $hash = pop @
{$self->{'_currentitems'}};
337 if( $self->in_element('bootstrap') ) {
338 # leading/trailing Whitespace-B-Gone
339 $ch =~ s/^\s+//; $ch =~ s/\s+$//;
340 $hash->{'-bootstrap'} = $ch;
341 } elsif( $self->in_element('branch_length') ) {
342 # leading/trailing Whitespace-B-Gone
343 $ch =~ s/^\s+//; $ch =~ s/\s+$//;
344 $hash->{'-branch_length'} = $ch;
345 } elsif( $self->in_element('id') ) {
346 $hash->{'-id'} = $ch;
347 } elsif( $self->in_element('description') ) {
348 $hash->{'-desc'} = $ch;
349 } elsif ( $self->in_element('tag_name') ) {
350 $hash->{'-NHXtagname'} = $ch;
351 } elsif ( $self->in_element('tag_value') ) {
352 $hash->{'-nhx'}->{$hash->{'-NHXtagname'}} = $ch;
353 delete $hash->{'-NHXtagname'};
354 } elsif( $self->in_element('leaf') ) {
355 $hash->{'-leaf'} = $ch;
357 push @
{$self->{'_currentitems'}}, $hash;
359 $self->debug("chars: $ch\n");