Skip to content

Commit

Permalink
Remove default sp_naming_function in PhyloTree.
Browse files Browse the repository at this point in the history
The one we had makes no sense for modern trees. Better
not to set any function unless the user chooses it.
  • Loading branch information
jordibc committed Nov 10, 2023
1 parent d12c0bf commit 23a3b77
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 28 deletions.
3 changes: 1 addition & 2 deletions ete4/nexml/_nexml_tree.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import sys
from ._nexml import MixedContainer, FloatTree, TreeFloatEdge, TreeNode, LiteralMeta
from .. import PhyloTree
from ..phylo.phylotree import _parse_species
from ..parser.newick import loads

class Children(list):
Expand Down Expand Up @@ -58,7 +57,7 @@ def _set_children(self, value):
name = property(fget=_get_name, fset=_set_name)

def __init__(self, newick=None, alignment=None, alg_format="fasta", \
sp_naming_function=_parse_species, parser=0):
sp_naming_function=None, parser=0):

self.nexml_tree = FloatTree()
self.nexml_tree.set_anyAttributes_({'xsi:type': 'FloatTree'})
Expand Down
4 changes: 1 addition & 3 deletions ete4/phylo/phylotree.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@

__all__ = ["PhyloTree"]

def _parse_species(name):
return name[:3] if name is not None else ''

def is_dup(n):
return n.props.get("evoltype") == "D"
Expand Down Expand Up @@ -272,7 +270,7 @@ class PhyloTree(Tree):
"""

def __init__(self, newick=None, children=None, alignment=None,
alg_format="fasta", sp_naming_function=_parse_species,
alg_format="fasta", sp_naming_function=None,
parser=None):
"""
:param newick: If not None, initializes the tree from a newick,
Expand Down
39 changes: 26 additions & 13 deletions tests/test_phylotree.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ def test_link_alignmets(self):
alg1 = SeqGroup(fasta)
alg2 = SeqGroup(iphylip, format="iphylip")

t = PhyloTree("(((seqA,seqB),seqC),seqD);", alignment=fasta, alg_format="fasta")
t = PhyloTree("(((seqA,seqB),seqC),seqD);", alignment=fasta, alg_format="fasta",
sp_naming_function=lambda name: name[:3])

for l in t.leaves():
self.assertEqual(l.props.get('sequence'), alg1.get_seq(l.name))
Expand All @@ -69,7 +70,8 @@ def test_get_sp_overlap_on_all_descendants(self):
""" Tests ortholgy prediction using the sp overlap"""
# Creates a gene phylogeny with several duplication events at
# different levels.
t = PhyloTree(example_tree)
t = PhyloTree(example_tree,
sp_naming_function=lambda name: name[:3])

# Scans the tree using the species overlap algorithm and detect all
# speciation and duplication events
Expand Down Expand Up @@ -158,19 +160,22 @@ def test_get_sp_overlap_on_all_descendants(self):
self.assertEqual(expected_orthologs, orthologs)

# Test different sos_thr
t = PhyloTree('(((SP1_a, SP2_a), (SP3_a, SP1_b)), (SP1_c, SP2_c));')
t = PhyloTree('(((SP1_a, SP2_a), (SP3_a, SP1_b)), (SP1_c, SP2_c));',
sp_naming_function=lambda name: name[:3])
seed = t['SP1_a']
events = t.get_descendant_evol_events(0.1)
self.assertEqual(t.common_ancestor([seed, 'SP3_a']).props.get('evoltype'), 'D')
self.assertEqual(t.common_ancestor([seed, 'SP1_c']).props.get('evoltype'), 'D')

t = PhyloTree('(((SP1_a, SP2_a), (SP3_a, SP1_b)), (SP1_c, SP2_c));')
t = PhyloTree('(((SP1_a, SP2_a), (SP3_a, SP1_b)), (SP1_c, SP2_c));',
sp_naming_function=lambda name: name[:3])
seed = t['SP1_a']
events = t.get_descendant_evol_events(0.5)
self.assertEqual(t.common_ancestor([seed, 'SP3_a']).props.get('evoltype'), 'S')
self.assertEqual(t.common_ancestor([seed, 'SP1_c']).props.get('evoltype'), 'D')

t = PhyloTree('(((SP1_a:1, SP2_a:1):1, (SP3_a:1, SP1_b:1):1):1, (SP1_c:1, SP2_c:1):1):0;')
t = PhyloTree('(((SP1_a:1, SP2_a:1):1, (SP3_a:1, SP1_b:1):1):1, (SP1_c:1, SP2_c:1):1):0;',
sp_naming_function=lambda name: name[:3])
seed = t['SP1_a']
events = seed.get_my_evol_events(0.75)
self.assertEqual(t.common_ancestor([seed, 'SP3_a']).props.get('evoltype'), 'S')
Expand All @@ -180,7 +185,8 @@ def test_get_sp_overlap_on_a_seed(self):
""" Tests ortholgy prediction using sp overlap"""
# Creates a gene phylogeny with several duplication events at
# different levels.
t = PhyloTree(example_tree)
t = PhyloTree(example_tree,
sp_naming_function=lambda name: name[:3])

# Scans the tree using the species overlap algorithm
seed = t['Hsa_001']
Expand Down Expand Up @@ -261,19 +267,22 @@ def test_get_sp_overlap_on_a_seed(self):
self.assertEqual(expected_orthologs, orthologs)

# Test different sos_thr
t = PhyloTree('(((SP1_a:1, SP2_a:1):1, (SP3_a:1, SP1_b:1):1):1, (SP1_c:1, SP2_c:1):1):0;')
t = PhyloTree('(((SP1_a:1, SP2_a:1):1, (SP3_a:1, SP1_b:1):1):1, (SP1_c:1, SP2_c:1):1):0;',
sp_naming_function=lambda name: name[:3])
seed = t['SP1_a']
events = seed.get_my_evol_events(0.1)
self.assertEqual(t.common_ancestor([seed, 'SP3_a']).props.get('evoltype'), 'D')
self.assertEqual(t.common_ancestor([seed, 'SP1_c']).props.get('evoltype'), 'D')

t = PhyloTree('(((SP1_a:1, SP2_a:1):1, (SP3_a:1, SP1_b:1):1):1, (SP1_c:1, SP2_c:1):1):0;')
t = PhyloTree('(((SP1_a:1, SP2_a:1):1, (SP3_a:1, SP1_b:1):1):1, (SP1_c:1, SP2_c:1):1):0;',
sp_naming_function=lambda name: name[:3])
seed = t['SP1_a']
events = seed.get_my_evol_events(0.50)
self.assertEqual(t.common_ancestor([seed, 'SP3_a']).props.get('evoltype'), 'S')
self.assertEqual(t.common_ancestor([seed, 'SP1_c']).props.get('evoltype'), 'D')

t = PhyloTree('(((SP1_a:1, SP2_a:1):1, (SP3_a:1, SP1_b:1):1):1, (SP1_c:1, SP2_c:1):1):0;')
t = PhyloTree('(((SP1_a:1, SP2_a:1):1, (SP3_a:1, SP1_b:1):1):1, (SP1_c:1, SP2_c:1):1):0;',
sp_naming_function=lambda name: name[:3])
seed = t['SP1_a']
events = seed.get_my_evol_events(0.75)
self.assertEqual(t.common_ancestor([seed, 'SP3_a']).props.get('evoltype'), 'S')
Expand All @@ -284,8 +293,10 @@ def test_reconciliation(self):
gene_tree_nw = '((Dme_001,Dme_002),(((Cfa_001,Mms_001),((Hsa_001,Ptr_001),Mmu_001)),(Ptr_002,(Hsa_002,Mmu_002))));'
species_tree_nw = "((((Hsa, Ptr), Mmu), (Mms, Cfa)), Dme);"

genetree = PhyloTree(gene_tree_nw)
sptree = PhyloTree(species_tree_nw)
genetree = PhyloTree(gene_tree_nw,
sp_naming_function=lambda name: name[:3])
sptree = PhyloTree(species_tree_nw,
sp_naming_function=lambda name: name[:3])

recon_tree, events = genetree.reconcile(sptree)
# Check that reconcilied tree nodes have the correct lables:
Expand All @@ -299,7 +310,8 @@ def test_miscelaneus(self):
""" Test several things """
# Creates a gene phylogeny with several duplication events at
# different levels.
t = PhyloTree(example_tree)
t = PhyloTree(example_tree,
sp_naming_function=lambda name: name[:3])

# Create a dictionary with relative ages for the species present in
# the phylogenetic tree. Note that ages are only relative numbers to
Expand Down Expand Up @@ -337,7 +349,8 @@ def test_miscelaneus(self):
self.assertEqual(set([sp for sp in t.iter_species()]), set(sp2age.keys()))

def test_collapse(self):
t = PhyloTree('((Dme_001,Dme_002),(((Cfa_001,Mms_001),((((Hsa_001,Hsa_001),Ptr_001),Mmu_001),((Hsa_004,Ptr_004),Mmu_004))),(Ptr_002,(Hsa_002,Mmu_002))));')
t = PhyloTree('((Dme_001,Dme_002),(((Cfa_001,Mms_001),((((Hsa_001,Hsa_001),Ptr_001),Mmu_001),((Hsa_004,Ptr_004),Mmu_004))),(Ptr_002,(Hsa_002,Mmu_002))));',
sp_naming_function=lambda name: name[:3])
for n in t.traverse():
n.dist = 1
n.support = 1
Expand Down
26 changes: 17 additions & 9 deletions tests/test_tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -1457,7 +1457,8 @@ def test_monophyly(self):
self.assertEqual(monotype, 'paraphyletic')

# Now with unrooted trees, and using species instead of names.
t = PhyloTree('(aaa1, (aaa3, (aaa4, (bbb1, bbb2))));')
t = PhyloTree('(aaa1, (aaa3, (aaa4, (bbb1, bbb2))));',
sp_naming_function=lambda name: name[:3])
# ─┬╴aaa1 # the species will be 'aaa' for this node, etc.
# ╰─┬╴aaa3
# ╰─┬╴aaa4
Expand All @@ -1469,50 +1470,57 @@ def test_monophyly(self):
(True, 'monophyletic', set()))

# Variations on that tree.
t = PhyloTree('(aaa1, (bbb3, (aaa4, (bbb1, bbb2))));')
t = PhyloTree('(aaa1, (bbb3, (aaa4, (bbb1, bbb2))));',
sp_naming_function=lambda name: name[:3])
is_mono, _, extra = t.check_monophyly(values={'aaa'},
prop='species', unrooted=True)
self.assertFalse(is_mono)
self.assertEqual(extra, {t['bbb3']})

t = PhyloTree('(aaa1, (aaa3, (aaa4, (bbb1, bbb2))));')
t = PhyloTree('(aaa1, (aaa3, (aaa4, (bbb1, bbb2))));',
sp_naming_function=lambda name: name[:3])
is_mono, _, extra = t.check_monophyly(values={'bbb'},
prop='species', unrooted=True)
self.assertTrue(is_mono)
self.assertEqual(extra, set())

t = PhyloTree('(aaa1, (aaa3, (aaa4, (bbb1, ccc2))));')
t = PhyloTree('(aaa1, (aaa3, (aaa4, (bbb1, ccc2))));',
sp_naming_function=lambda name: name[:3])
is_mono, _, extra = t.check_monophyly(values={'bbb', 'ccc'},
prop='species', unrooted=True)
self.assertTrue(is_mono)
self.assertEqual(extra, set())

t = PhyloTree('(aaa1, (aaa3, (bbb4, (bbb1, bbb2))));')
t = PhyloTree('(aaa1, (aaa3, (bbb4, (bbb1, bbb2))));',
sp_naming_function=lambda name: name[:3])
is_mono, _, extra = t.check_monophyly(values={'bbb4', 'bbb2'},
prop='name', unrooted=True)
self.assertFalse(is_mono)
self.assertEqual(extra, {t['bbb1']})

t = PhyloTree('(aaa1, (aaa3, (bbb4, (bbb1, bbb2))));')
t = PhyloTree('(aaa1, (aaa3, (bbb4, (bbb1, bbb2))));',
sp_naming_function=lambda name: name[:3])
is_mono, _, extra = t.check_monophyly(values={'bbb1', 'bbb2'},
prop='name', unrooted=True)
self.assertTrue(is_mono)
self.assertEqual(extra, set())

t = PhyloTree('(aaa1, aaa3, (aaa4, (bbb1, bbb2)));')
t = PhyloTree('(aaa1, aaa3, (aaa4, (bbb1, bbb2)));',
sp_naming_function=lambda name: name[:3])
is_mono, _, extra = t.check_monophyly(values={'aaa'},
prop='species', unrooted=True)
self.assertTrue(is_mono)
self.assertEqual(extra, set())

t = PhyloTree('(aaa1, bbb3, (aaa4, (bbb1, bbb2)));')
t = PhyloTree('(aaa1, bbb3, (aaa4, (bbb1, bbb2)));',
sp_naming_function=lambda name: name[:3])
is_mono, _, extra = t.check_monophyly(values={'aaa'},
prop='species', unrooted=True)
self.assertFalse(is_mono)
self.assertEqual(extra, {t['bbb3']})

# # Check monophyly randomization test
# t = PhyloTree()
# t = PhyloTree(,
# t.populate(100)
# ancestor = t.common_ancestor(['aaaaaaaaaa', 'aaaaaaaaab', 'aaaaaaaaac'])
# all_nodes = list(t.descendants())
Expand Down
2 changes: 1 addition & 1 deletion tests/test_treematcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def test_search():


def test_safer():
t = PhyloTree('(a,(b,c));')
t = PhyloTree('(a,(b,c));', sp_naming_function=lambda name: name)

tp_unsafe = tm.TreePattern('("node.get_species()=={\'c\'}",'
' node.species=="b")')
Expand Down

0 comments on commit 23a3b77

Please sign in to comment.