Skip to content

Commit

Permalink
if the same node is provided as first argument to get_common_ancestor…
Browse files Browse the repository at this point in the history
…, returns itself. Unittest of get_common_ancestor improved.
  • Loading branch information
jhcepas committed Mar 30, 2020
1 parent 0b84a2a commit 465f56f
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 21 deletions.
40 changes: 22 additions & 18 deletions ete3/coretype/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -884,10 +884,19 @@ def get_common_ancestor(self, *target_nodes, **kargs):
# Convert node names into node instances
target_nodes = _translate_nodes(self, *target_nodes)

# If only one node is provided, use self as the second target
if type(target_nodes) != list:
target_nodes = [target_nodes, self]

if type(target_nodes) != list:
# If only one node is provided and is the same as the seed node,
# return itself
if target_nodes is self:
if get_path:
return self, {}
else:
return self
else:
#Otherwise find the common ancestor of current seed node and
#the target_node provided
target_nodes = [target_nodes, self]

n2path = {}
reference = []
Expand Down Expand Up @@ -2442,7 +2451,7 @@ def cophenetic_matrix(self):
else:
output[i].append(leaf_distances[n][m])
return output, allleaves

def add_face(self, face, column, position="branch-right"):
"""
.. versionadded: 2.1
Expand Down Expand Up @@ -2485,14 +2494,14 @@ def set_style(self, node_style):

@staticmethod
def from_parent_child_table(parent_child_table):
"""Converts a parent-child table into an ETE Tree instance.
"""Converts a parent-child table into an ETE Tree instance.
:argument parent_child_table: a list of tuples containing parent-child
relationships. For example: [("A", "B", 0.1), ("A", "C", 0.2), ("C",
"D", 1), ("C", "E", 1.5)]. Where each tuple represents: [parent, child,
child-parent-dist]
:returns: A new Tree instance
:returns: A new Tree instance
:example:
Expand Down Expand Up @@ -2527,20 +2536,20 @@ def get_node(nodename, dist=None):

@staticmethod
def from_skbio(skbio_tree, map_attributes=None):
"""Converts a scikit-bio TreeNode object into ETE Tree object.
:argument skbio_tree: a scikit bio TreeNode instance
"""Converts a scikit-bio TreeNode object into ETE Tree object.
:argument skbio_tree: a scikit bio TreeNode instance
:argument None map_attributes: A list of attribute nanes in the
scikit-bio tree that should be mapped into the ETE tree
instance. (name, id and branch length are always mapped)
:returns: A new Tree instance
:returns: A new Tree instance
:example:
>>> tree = Tree.from_skibio(skbioTree, map_attributes=["value"])
"""
from skbio import TreeNode as skbioTreeNode

Expand Down Expand Up @@ -2601,8 +2610,3 @@ def _translate_nodes(root, *nodes):
# Alias
#: .. currentmodule:: ete3
Tree = TreeNode





25 changes: 22 additions & 3 deletions ete3/test/test_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import unittest
import random
import itertools
import json

import sys
from six.moves import range
Expand Down Expand Up @@ -469,7 +470,7 @@ def test_common_ancestors(self):
# getting nodes, get_childs, get_sisters, get_tree_root,
# get_common_ancestor, get_nodes_by_name
# get_descendants_by_name, is_leaf, is_root
t = Tree("(((A,B),C)[&&NHX:tag=common],D)[&&NHX:tag=root:name=root];")
t = Tree("(((A,B)N1,C)N2[&&NHX:tag=common],D)[&&NHX:tag=root:name=root];", format=1)
self.assertEqual(t.get_sisters(), [])

A = t.search_nodes(name="A")[0]
Expand Down Expand Up @@ -499,6 +500,24 @@ def test_common_ancestors(self):
self.assert_(not A.get_tree_root().is_leaf())
self.assertRaises(TreeError, A.get_common_ancestor, Tree())

# Test multiple target nodes and get_path argument
common, path = t.get_common_ancestor(['A', 'C'], get_path=True)
N1 = t & "N1"
N2 = t & "N2"
expected_path = {A: set([A, root, N1, N2]), C: set([C, N2, root])}
self.assertEqual(common, N2)
self.assertEqual(path.keys(), expected_path.keys())
for k in path.keys():
self.assertEqual(list(sorted(path[k])), list(sorted(expected_path[k])))

# Test common ancestor function using self as single argument (issue #398)
common = A.get_common_ancestor(A)
self.assert_(common, A)
common = C.get_common_ancestor("C")
self.assert_(common, C)
common, path = C.get_common_ancestor("C", get_path=True)
self.assertEqual(common, C)
self.assertDictEqual(path, {})

def test_getters_iters(self):

Expand Down Expand Up @@ -863,12 +882,12 @@ def _astuple(d):
# RF unrooted in too small trees
self.assertEqual(_astuple(small.compare(ref1, unrooted=True)),
("NA", "NA", 0.0, "NA", "NA", 2, 1, "NA"))

small = Tree("(A, B);")
# RF unrooted in too small trees
self.assertEqual(_astuple(small.compare(ref1, unrooted=False)),
("NA", "NA", 0.0, "NA", "NA", 2, 1, "NA"))

# identical trees, 8 rooted partitions in total (4 an 4), and 6 unrooted
self.assertEqual(_astuple(s1.compare(ref1)),
(0.0, 0.0, 8, 1.0, 1.0, 6, 1, "NA"))
Expand Down

0 comments on commit 465f56f

Please sign in to comment.