-
Notifications
You must be signed in to change notification settings - Fork 61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tree.mrca
has side effect of changing rooting state
#152
Comments
Sets `collapse_unrooted_basal_bifurcation=False` in call to `Tree.encode_bipartitions` inside `Tree.mrca`. Closes jeetsukumaran#152.
Sets `collapse_unrooted_basal_bifurcation=False` in call to `Tree.encode_bipartitions` inside `Tree.mrca`. Closes jeetsukumaran#152.
Thanks for bringing this to our attention and this fix! I appreciate the issue and the fix makes sense. I'll look into this in a bit, and please don't hesitate to send me a reminder if I dawdle. One question I have is whether or not the '[&U]' is cosmetic or is the Maybe not related: does it make sense to ask for an MRCA of an unrooted tree? Should we throw an error? |
I did an additional experiment, and it looks like the rootedness is only changed to >>> import dendropy as dp
>>> tree = dp.Tree.get(
... data="((10,(((5,(11)),7,9))),((((1)))));",
... schema="newick",
... )
>>> leaf_taxa = [
... leaf.taxon for leaf in tree.leaf_node_iter()
... ]
>>> print("first tree.is_rooted", tree.is_rooted)
first tree.is_rooted None
>>> tree.is_rooted = False
>>> print("second tree.is_rooted", tree.is_rooted)
second tree.is_rooted False
>>> tree.mrca(taxa=leaf_taxa[:2])
<Node object at 0x7f7e81d0cd60: 'None' (None)>
>>> print("after tree.is_rooted", tree.is_rooted)
after tree.is_rooted False |
There could plausibly be some kind of argument to calculate the MRCA between two nodes in an unrooted tree by taking the shortest path between them (would be well-defined/unique) and selecting the node closest to the middle of this path. How the MRCA between more than two nodes might be interpreted in an unrooted tree isn't immediately obvious to me Plus, for either of these cases, I doubt there's a substantial intentional use case for MRCA in an unrooted tree anyways. In the scenario I ran into, I was basically relying on the ambiguity of the Warning or throwing an error for the |
I did a quick sanity check to see if BioPython had made any kind of decision here, and it looks like they're also just using the implicit root of an unrooted tree without a warning or error. >>> from io import StringIO
>>> from Bio import Phylo
>>> tree = Phylo.read(StringIO("(10,(((5,(11)),7,9)),((((1)))))R;"), "newick")
>>> tree.rooted
False
>>> leaf1 = tree.get_terminals()[0]
>>> leaf1
Clade(name='10')
>>> leaf2 = tree.get_terminals()[1]
>>> leaf2
Clade(name='5')
>>> mrca = tree.common_ancestor(leaf1, leaf2)
>>> mrca
Clade(name='R') |
Ok, let's go ahead and merge this. Maybe a warning would be good thing to add though |
Sets `collapse_unrooted_basal_bifurcation=False` in call to `Tree.encode_bipartitions` inside `Tree.mrca`. Closes jeetsukumaran#152.
Here is a minimum working example:
Works on multiple versions of Python, including
Python 3.9.16 (main, Dec 7 2022, 01:12:08) [GCC 11.3.0] on linux
withdendropy 4.5.2
.In a more copy/pasteable form:
This side effect is can have very unexpected and perplexing consequences.
Consider, for example
(Note the addition of the
[&U]
prefix after callingmrca
.)as far as I can tell what is happening is
Tree.mrca
Tree.encode_bipartitions
suppress_unifurcations=False
collapse_unrooted_basal_bifurcation=True
,suppress_storage=False
, andis_bipartitions_mutable=False
left as defaultDendroPy/src/dendropy/datamodel/treemodel/_tree.py
Line 1553 in 0b0d8df
Tree.collapse_basal_bifurcation
set_as_unrooted_tree=True
left as defaultDendroPy/src/dendropy/datamodel/treemodel/_tree.py
Line 3570 in 0b0d8df
is_rooted = False
DendroPy/src/dendropy/datamodel/treemodel/_tree.py
Line 2401 in 0b0d8df
The text was updated successfully, but these errors were encountered: