Skip Menu |

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Bio-Phylo CPAN distribution.

Report information
The Basics
Id: 26332
Status: resolved
Priority: 0/
Queue: Bio-Phylo

People
Owner: Nobody in particular
Requestors: struckma [...] uni-greifswald.de
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Bio::Phylo::Treedrawer
Date: Fri, 13 Apr 2007 18:57:38 +0200
To: bug-Bio-Phylo [...] rt.cpan.org
From: Stephan Struckmann <struckma [...] uni-greifswald.de>
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Dear Bio-Phylo Team I have two issues that concern using Bio::Phylo via a (Web-)Frontend. If Treedrawer is called twice, the second SVG unfortunately will always have wrong y-coordinates: In Bio::Phylo::Treedrawer you have: { my $tips = 0.000_000_000_000_01; sub _y_terminals { my $self = shift; my $node = $_[0]; if ( !$node->get_first_daughter ) { $tips++; $node->set_generic( y => ( ( $tips * $self->_get_scaley ) + $self->get_padding ) ); } else { $node = $node->get_first_daughter; $self->_y_terminals($node); while ( $node->get_next_sister ) { $node = $node->get_next_sister; $self->_y_terminals($node); } } } } Thus $tips is never reset after the first call of the draw function. I worked around that by subclassing Treedrawer, but probably Treedrawer should reset $tips when the Bio::Phylo::Treedrawer::draw routine is invoked. Thus $tips has to be a class variable not a local. Some other remarks that may become feature requests, if You like to: * A reset routine for IDPool until no real serialization is implemented: package Bio::Phylo::Util::IDPool; [...] sub _reset { $obj_counter = 0 ; @reclaim = () ; } } 1; __END__ =head1 NAME [...] So one could reinitialize the ID counter. If one tries to restore a session in a web application it becomes possible as long as the objects are regenerated always in the same order and get_id can be used to identify e.g. a node the user clicked on. I also adjusted bioperl's reroot routine for Bio::Phylo::Tree package [...] ; # Rerooting copied from Bioperl: # Id: TreeFunctionsI.pm,v 1.14 2003/12/15 17:10:29 jason Exp # Therein rerooting code was worked on by # Daniel Barker and Ramiro Barrantes # See http://search.cpan.org/src/BIRNEY/bioperl-1.4/Bio/Tree/TreeFunctionsI.pm # for original code sub reroot { my ($tree, $new_root) = @_; unless (defined $new_root && $new_root->isa("Bio::Phylo::Forest::Node")) { die("Must provide a valid Bio::Phylo::Forest::Node when rerooting"); return 0; } if( $new_root->is_terminal() ) { warn("Asking to root with a leaf, will use the leaf's ancestor"); $new_root = $new_root->get_parent; } my $old_root = $tree->get_root; # print STDERR $new_root -> get_id . '/' . $old_root -> get_id . "\n" ; if( $new_root == $old_root ) { warn("Node requested for reroot is already the root node!"); return 0; } my @path = (); # along tree, from newroot to oldroot my $node = $new_root; while ($node) { push @path, $node; $node = $node->get_parent; } my @path_from_oldroot = reverse @path; for (my $i = 0; $i < @path_from_oldroot - 1; $i++) { my $current = $path_from_oldroot[$i]; my $next = $path_from_oldroot[$i + 1]; [...]::remove_Descendent($current, $next); $current->set_branch_length($next->get_branch_length); $next->set_child($current); } $new_root->set_branch_length(undef); return 1; } sub remove_Descendent { # may be substituted by a tree->_analyze call, but _analyze is not # documented in the official CPAN documentation my $parent = shift ; my $child = shift ; die 'Internal error.' unless $child->get_parent eq $parent ; $child -> set_parent ( ) ; if ($parent -> get_first_daughter eq $child) { $parent -> set_first_daughter( $child -> get_next_sister ) ; } if ($parent -> get_last_daughter eq $child) { $parent -> set_last_daughter( $child -> get_previous_sister ) ; } if (my $ps = $child -> get_previous_sister) { $ps->set_next_sister($child->get_next_sister); $ps->get_next_sister->set_previous_sister($ps) if defined $ps->get_next_sister; $child->set_previous_sister(); $child->set_next_sister(); } elsif (my $ns = $child -> get_next_sister) { $ns->set_previous_sister($child->get_previous_sister); $ns->get_previous_sister->set_next_sister($ns) if defined $ns->get_previous_sister; $child->set_previous_sister(); $child->set_next_sister(); } } Finally I would like to ask, why the Bio::Phylo::Forest::make_taxa was removed after revision 0.15? The Mrp unparser would need it yet. But probably You plan to adjust the unparser accordingly. So far my remarks. I hope, that you find these helpful. Thank You very much for your great Phylogeny library, Yours sincerely Stephan Struckmann struckma@uni-greifswald.de Germany -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (MingW32) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGH7aC8viug4UfhY8RAvprAJwOxONcitFn+doLsgMGHSPHaKW7KQCeKTKb 4wC3yrHyUQJjQvavEhHd2Dg= =TSgS -----END PGP SIGNATURE-----
Download smime.p7s
application/x-pkcs7-signature 6.1k

Message body not shown because it is not plain text.

Dear Stephan, thanks for your remarks! I do actually check these bug reports, but not that often, apparently. 1. we're reworking the treedrawer, the issue with the static $tips variable will be fixed in the next release. 2. the ID reinitialize function is an interesting idea, but ids are used in many places, accidentally resetting when another object with the same id still exists would be disastrous. I can see the persistence argument though, so I'll give it some thought. 3. a reroot method is definitely a good idea, though I think it should be a node method (not a tree method, so no argument with checks necessary). 4. the way links between trees/matrices/taxa are managed has changed internally (using a mediator). The complete removal of make_taxa is frankly a mistake, it should be moved up in the inheritance tree to the TaxaLinker superclass. Thanks for your kind words, best wishes, Rutger Vos On Fri Apr 13 12:58:07 2007, struckma@uni-greifswald.de wrote: Show quoted text
> -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Dear Bio-Phylo Team > > I have two issues that concern using Bio::Phylo via a (Web-)Frontend. If > Treedrawer is called twice, the second SVG unfortunately will always > have wrong y-coordinates: > > In Bio::Phylo::Treedrawer you have: > > { > my $tips = 0.000_000_000_000_01; > > sub _y_terminals { > my $self = shift; > my $node = $_[0]; > if ( !$node->get_first_daughter ) { > $tips++; > $node->set_generic( > y => ( ( $tips * $self->_get_scaley ) + > $self->get_padding ) ); > } > else { > $node = $node->get_first_daughter; > $self->_y_terminals($node); > while ( $node->get_next_sister ) { > $node = $node->get_next_sister; > $self->_y_terminals($node); > } > } > } > } > > Thus $tips is never reset after the first call of the draw function. I > worked around that by subclassing Treedrawer, but probably Treedrawer > should reset $tips when the Bio::Phylo::Treedrawer::draw routine is > invoked. Thus $tips has to be a class variable not a local. > > Some other remarks that may become feature requests, if You like to: > > * A reset routine for IDPool until no real serialization is implemented: > > package Bio::Phylo::Util::IDPool; > [...] > sub _reset { > $obj_counter = 0 ; > @reclaim = () ; > } > } > 1; > __END__ > > =head1 NAME > [...] > > So one could reinitialize the ID counter. If one tries to restore a > session in a web application it becomes possible as long as the objects > are regenerated always in the same order and get_id can be used to > identify e.g. a node the user clicked on. > > > I also adjusted bioperl's reroot routine for Bio::Phylo::Tree > > package [...] ; > > # Rerooting copied from Bioperl: > # Id: TreeFunctionsI.pm,v 1.14 2003/12/15 17:10:29 jason Exp > # Therein rerooting code was worked on by > # Daniel Barker and Ramiro Barrantes > # See > http://search.cpan.org/src/BIRNEY/bioperl-1.4/Bio/Tree/TreeFunctionsI.pm > # for original code > > sub reroot { > my ($tree, $new_root) = @_; > unless (defined $new_root && > $new_root->isa("Bio::Phylo::Forest::Node")) { > die("Must provide a valid Bio::Phylo::Forest::Node when rerooting"); > return 0; > } > if( $new_root->is_terminal() ) { > warn("Asking to root with a leaf, will use the leaf's ancestor"); > $new_root = $new_root->get_parent; > } > > my $old_root = $tree->get_root; > # print STDERR $new_root -> get_id . '/' . $old_root -> get_id . "\n" ; > if( $new_root == $old_root ) { > warn("Node requested for reroot is already the root node!"); > return 0; > } > > my @path = (); # along tree, from newroot to oldroot > my $node = $new_root; > while ($node) { > push @path, $node; > $node = $node->get_parent; > } > > my @path_from_oldroot = reverse @path; > for (my $i = 0; $i < @path_from_oldroot - 1; $i++) { > my $current = $path_from_oldroot[$i]; > my $next = $path_from_oldroot[$i + 1]; > [...]::remove_Descendent($current, $next); > $current->set_branch_length($next->get_branch_length); > $next->set_child($current); > } > > $new_root->set_branch_length(undef); > > return 1; > } > > sub remove_Descendent { > # may be substituted by a tree->_analyze call, but _analyze is not > # documented in the official CPAN documentation > my $parent = shift ; > my $child = shift ; > > die 'Internal error.' unless $child->get_parent eq $parent ; > > $child -> set_parent ( ) ; > > if ($parent -> get_first_daughter eq $child) { > $parent -> set_first_daughter( $child -> get_next_sister ) ; > } > > if ($parent -> get_last_daughter eq $child) { > $parent -> set_last_daughter( $child -> get_previous_sister ) ; > } > > if (my $ps = $child -> get_previous_sister) { > $ps->set_next_sister($child->get_next_sister); > $ps->get_next_sister->set_previous_sister($ps) if defined > $ps->get_next_sister; > $child->set_previous_sister(); > $child->set_next_sister(); > } elsif (my $ns = $child -> get_next_sister) { > $ns->set_previous_sister($child->get_previous_sister); > $ns->get_previous_sister->set_next_sister($ns) if defined > $ns->get_previous_sister; > $child->set_previous_sister(); > $child->set_next_sister(); > } > } > > Finally I would like to ask, why the Bio::Phylo::Forest::make_taxa was > removed after revision 0.15? The Mrp unparser would need it yet. But > probably You plan to adjust the unparser accordingly. > > So far my remarks. I hope, that you find these helpful. Thank You very > much for your great Phylogeny library, > > Yours sincerely > > Stephan Struckmann > struckma@uni-greifswald.de > Germany > -----BEGIN PGP SIGNATURE----- > Version: GnuPG v1.4.5 (MingW32) > Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org > > iD8DBQFGH7aC8viug4UfhY8RAvprAJwOxONcitFn+doLsgMGHSPHaKW7KQCeKTKb > 4wC3yrHyUQJjQvavEhHd2Dg= > =TSgS > -----END PGP SIGNATURE-----
The 'bad y-coordinates after multiple draws' bug has been fixed, I added a regression test #26332 to the test suite. I now consider this bug resolved, the fixed treedrawer will be part of release v.0.17 Best wishes, Rutger