mirror of
https://github.com/biopython/biopython.git
synced 2025-10-20 13:43:47 +08:00
Preserve root branch length in Phylo.TreeMixin.prune
This commit is contained in:
@ -660,8 +660,8 @@ class TreeMixin:
|
|||||||
def prune(self, target=None, **kwargs):
|
def prune(self, target=None, **kwargs):
|
||||||
"""Prunes a terminal clade from the tree.
|
"""Prunes a terminal clade from the tree.
|
||||||
|
|
||||||
If taxon is from a bifurcation, the connecting node will be collapsed
|
If the taxon is from a bifurcation, the connecting node will be collapsed
|
||||||
and its branch length added to remaining terminal node. This might be no
|
and its branch length added to remaining terminal node. This might no
|
||||||
longer be a meaningful value.
|
longer be a meaningful value.
|
||||||
|
|
||||||
:returns: parent clade of the pruned target
|
:returns: parent clade of the pruned target
|
||||||
@ -679,17 +679,14 @@ class TreeMixin:
|
|||||||
parent.clades.remove(path[-1])
|
parent.clades.remove(path[-1])
|
||||||
if len(parent) == 1:
|
if len(parent) == 1:
|
||||||
# We deleted a branch from a bifurcation
|
# We deleted a branch from a bifurcation
|
||||||
if parent == self.root:
|
child = parent.clades[0]
|
||||||
|
if child.branch_length is not None:
|
||||||
|
child.branch_length += parent.branch_length or 0.0
|
||||||
|
if len(path) == 1:
|
||||||
# If we're at the root, move the root upwards
|
# If we're at the root, move the root upwards
|
||||||
# NB: This loses the length of the original branch
|
parent = self.root = child
|
||||||
newroot = parent.clades[0]
|
|
||||||
newroot.branch_length = None
|
|
||||||
parent = self.root = newroot
|
|
||||||
else:
|
else:
|
||||||
# If we're not at the root, collapse this parent
|
# If we're not at the root, collapse this parent
|
||||||
child = parent.clades[0]
|
|
||||||
if child.branch_length is not None:
|
|
||||||
child.branch_length += parent.branch_length or 0.0
|
|
||||||
if len(path) < 3:
|
if len(path) < 3:
|
||||||
grandparent = self.root
|
grandparent = self.root
|
||||||
else:
|
else:
|
||||||
|
@ -352,7 +352,7 @@ function:
|
|||||||
>>> Phylo.write(tree1, "tree1.nwk", "newick")
|
>>> Phylo.write(tree1, "tree1.nwk", "newick")
|
||||||
1
|
1
|
||||||
>>> Phylo.write(trees, "other_trees.xml", "phyloxml") # write the remaining trees
|
>>> Phylo.write(trees, "other_trees.xml", "phyloxml") # write the remaining trees
|
||||||
12
|
13
|
||||||
|
|
||||||
Convert files between any of the supported formats with the ``convert``
|
Convert files between any of the supported formats with the ``convert``
|
||||||
function:
|
function:
|
||||||
@ -364,7 +364,7 @@ function:
|
|||||||
>>> Phylo.convert("tree1.nwk", "newick", "tree1.xml", "nexml")
|
>>> Phylo.convert("tree1.nwk", "newick", "tree1.xml", "nexml")
|
||||||
1
|
1
|
||||||
>>> Phylo.convert("other_trees.xml", "phyloxml", "other_trees.nex", "nexus")
|
>>> Phylo.convert("other_trees.xml", "phyloxml", "other_trees.nex", "nexus")
|
||||||
12
|
13
|
||||||
|
|
||||||
To use strings as input or output instead of actual files, use
|
To use strings as input or output instead of actual files, use
|
||||||
``StringIO`` as you would with SeqIO and AlignIO:
|
``StringIO`` as you would with SeqIO and AlignIO:
|
||||||
@ -681,7 +681,7 @@ tree intact, make a complete copy of the tree first, using Python’s
|
|||||||
sort clades deepest-to-shallowest.
|
sort clades deepest-to-shallowest.
|
||||||
|
|
||||||
``prune``
|
``prune``
|
||||||
Prunes a terminal clade from the tree. If taxon is from a
|
Prunes a terminal clade from the tree. If the taxon is from a
|
||||||
bifurcation, the connecting node will be collapsed and its branch
|
bifurcation, the connecting node will be collapsed and its branch
|
||||||
length added to remaining terminal node. This might no longer be a
|
length added to remaining terminal node. This might no longer be a
|
||||||
meaningful value.
|
meaningful value.
|
||||||
|
@ -408,6 +408,26 @@
|
|||||||
</clade>
|
</clade>
|
||||||
</clade>
|
</clade>
|
||||||
</phylogeny>
|
</phylogeny>
|
||||||
|
<phylogeny rooted="true">
|
||||||
|
<clade>
|
||||||
|
<branch_length>0.04</branch_length>
|
||||||
|
<clade>
|
||||||
|
<branch_length>0.06</branch_length>
|
||||||
|
<clade>
|
||||||
|
<name>A</name>
|
||||||
|
<branch_length>0.102</branch_length>
|
||||||
|
</clade>
|
||||||
|
<clade>
|
||||||
|
<name>B</name>
|
||||||
|
<branch_length>0.23</branch_length>
|
||||||
|
</clade>
|
||||||
|
</clade>
|
||||||
|
<clade>
|
||||||
|
<name>C</name>
|
||||||
|
<branch_length>0.4</branch_length>
|
||||||
|
</clade>
|
||||||
|
</clade>
|
||||||
|
</phylogeny>
|
||||||
<align:alignment xmlns:align="http://example.org/align">
|
<align:alignment xmlns:align="http://example.org/align">
|
||||||
<seq name="A">acgtcgcggcccgtggaagtcctctcct</seq>
|
<seq name="A">acgtcgcggcccgtggaagtcctctcct</seq>
|
||||||
<seq name="B">aggtcgcggcctgtggaagtcctctcct</seq>
|
<seq name="B">aggtcgcggcctgtggaagtcctctcct</seq>
|
||||||
|
@ -150,7 +150,7 @@ class IOTests(unittest.TestCase):
|
|||||||
trees = Phylo.parse("PhyloXML/phyloxml_examples.xml", "phyloxml")
|
trees = Phylo.parse("PhyloXML/phyloxml_examples.xml", "phyloxml")
|
||||||
with tempfile.NamedTemporaryFile(mode="w") as out_handle:
|
with tempfile.NamedTemporaryFile(mode="w") as out_handle:
|
||||||
count = Phylo.write(trees, out_handle, "phyloxml")
|
count = Phylo.write(trees, out_handle, "phyloxml")
|
||||||
self.assertEqual(13, count)
|
self.assertEqual(14, count)
|
||||||
|
|
||||||
def test_convert_phyloxml_filename(self):
|
def test_convert_phyloxml_filename(self):
|
||||||
"""Write phyloxml to a given filename."""
|
"""Write phyloxml to a given filename."""
|
||||||
@ -162,7 +162,7 @@ class IOTests(unittest.TestCase):
|
|||||||
count = Phylo.write(trees, tmp_filename, "phyloxml")
|
count = Phylo.write(trees, tmp_filename, "phyloxml")
|
||||||
finally:
|
finally:
|
||||||
os.remove(tmp_filename)
|
os.remove(tmp_filename)
|
||||||
self.assertEqual(13, count)
|
self.assertEqual(14, count)
|
||||||
|
|
||||||
def test_int_labels(self):
|
def test_int_labels(self):
|
||||||
"""Read newick formatted tree with numeric labels."""
|
"""Read newick formatted tree with numeric labels."""
|
||||||
@ -471,6 +471,7 @@ class MixinTests(unittest.TestCase):
|
|||||||
tree = self.phylogenies[1]
|
tree = self.phylogenies[1]
|
||||||
parent = tree.prune(name="C")
|
parent = tree.prune(name="C")
|
||||||
self.assertEqual(parent, tree.root)
|
self.assertEqual(parent, tree.root)
|
||||||
|
self.assertEqual(tree.root.branch_length, 0.06)
|
||||||
self.assertEqual(len(parent.clades), 2)
|
self.assertEqual(len(parent.clades), 2)
|
||||||
for clade, name, blen in zip(parent, "AB", (0.102, 0.23)):
|
for clade, name, blen in zip(parent, "AB", (0.102, 0.23)):
|
||||||
self.assertTrue(clade.is_terminal())
|
self.assertTrue(clade.is_terminal())
|
||||||
@ -478,6 +479,10 @@ class MixinTests(unittest.TestCase):
|
|||||||
self.assertAlmostEqual(clade.branch_length, blen)
|
self.assertAlmostEqual(clade.branch_length, blen)
|
||||||
self.assertEqual(len(tree.get_terminals()), 2)
|
self.assertEqual(len(tree.get_terminals()), 2)
|
||||||
self.assertEqual(len(tree.get_nonterminals()), 1)
|
self.assertEqual(len(tree.get_nonterminals()), 1)
|
||||||
|
# Taxon just below root
|
||||||
|
tree = self.phylogenies[13]
|
||||||
|
parent = tree.prune(name="C")
|
||||||
|
self.assertEqual(tree.root.branch_length, 0.1)
|
||||||
|
|
||||||
def test_split(self):
|
def test_split(self):
|
||||||
"""TreeMixin: split() method."""
|
"""TreeMixin: split() method."""
|
||||||
|
@ -96,13 +96,13 @@ class ParseTests(unittest.TestCase):
|
|||||||
test_read_apaf = _test_read_factory(EX_APAF, (1, 0))
|
test_read_apaf = _test_read_factory(EX_APAF, (1, 0))
|
||||||
test_read_bcl2 = _test_read_factory(EX_BCL2, (1, 0))
|
test_read_bcl2 = _test_read_factory(EX_BCL2, (1, 0))
|
||||||
test_read_made = _test_read_factory(EX_MADE, (6, 0))
|
test_read_made = _test_read_factory(EX_MADE, (6, 0))
|
||||||
test_read_phylo = _test_read_factory(EX_PHYLO, (13, 1))
|
test_read_phylo = _test_read_factory(EX_PHYLO, (14, 1))
|
||||||
test_read_dollo = _test_read_factory(EX_DOLLO, (1, 0))
|
test_read_dollo = _test_read_factory(EX_DOLLO, (1, 0))
|
||||||
|
|
||||||
test_parse_apaf = _test_parse_factory(EX_APAF, 1)
|
test_parse_apaf = _test_parse_factory(EX_APAF, 1)
|
||||||
test_parse_bcl2 = _test_parse_factory(EX_BCL2, 1)
|
test_parse_bcl2 = _test_parse_factory(EX_BCL2, 1)
|
||||||
test_parse_made = _test_parse_factory(EX_MADE, 6)
|
test_parse_made = _test_parse_factory(EX_MADE, 6)
|
||||||
test_parse_phylo = _test_parse_factory(EX_PHYLO, 13)
|
test_parse_phylo = _test_parse_factory(EX_PHYLO, 14)
|
||||||
test_parse_dollo = _test_parse_factory(EX_DOLLO, 1)
|
test_parse_dollo = _test_parse_factory(EX_DOLLO, 1)
|
||||||
|
|
||||||
# lvl-2 clades, sub-clade counts, lvl-3 clades
|
# lvl-2 clades, sub-clade counts, lvl-3 clades
|
||||||
|
Reference in New Issue
Block a user