Manipulation of Tree Node Objects¶
Section author: Tony Walters
Examples of how to initialize and manipulate various tree node objects.
The general method to initialize a tree is load_tree
, however, for exceptionally large trees or if one needs to specify the node objects (TreeNode
, PhyloNode
, or RangeNode
), DndParser
should be used. load_tree
uses PhyloNode
objects by default.
The basic properties of the tree node objects are:
TreeNode
objects are general purpose in nature, and lack phylogenetic distance values.PhyloNode
objects inherit the methods of theTreeNode
class and in addition contain phylogenetic distances.RangeNode
objects contain evolution simulation methods in addition to the standard features of aPhyloNode
.
The following demonstrates the two methods for initializing a phylogenetic tree object.
Now to displaying, creating, deleting, and inserting a node in simple_tree. Note that simple_tree has three tips, one internal node ‘E’, and the root ‘F.’ For this example, we will create a node named ‘A’, with a distance of 0.1, delete the node ‘C’ through its parent, the internal node ‘E’, and finally we will insert ‘A’ where ‘C’ once was.
Display the original tree.
Create a new node object.
Display the children of the root node, one of which is the parent of the tip we wish to alter. To add or remove a node, we need to use the parent of the target node, which in this case is the internal node ‘E.’
Remove the ‘C’ tip. Note: remove()
and remove_node()
return ‘True’ if a node is removed, ‘False’ if they cannot remove a node.
Insert the new ‘A’ tip where ‘C’ was previously.
Finally, display the modified tree.
When deleting tree nodes, it is often desirable to clean up any unbranched internal nodes that may have resulted from removal of tips. For example, if we wanted to delete the node ‘A’ that was previously added, the resulting tree would have an unbranched internal node ‘E.’
With the prune()
method, internal nodes with only a single branch are removed.
An Example of Conditional Tree Node Modifications¶
Now to look at the more complex and realistic tree. In complex_tree, there are no internal nodes or a defined root. In order to display this tree in a more succinct manner, we can rename these tips to only contain the genus and species names. To step through the tips only, we can use the iter_tips()
iterator, and rename each node. The ascii_art()
function, by default, will attempt to display internal nodes; this can be suppressed by the parameter show_internal=False
.
First, let’s split the ungainly name string for each tip and only preserve the genus and species component, separated by a space.
Now we display the tree with ascii_art()
.
For another example of manipulating a phylogenetic tree, let us suppose that we want to remove any species in the tree that are not closely related to Aerococcus viridans. To do this, we will delete any nodes that have a greater phylogenetic distance than 1.8 from Aerococcus viridans. The best method to remove a large number of nodes from a tree is to first create a list of nodes to delete, followed by the actual removal process. It is important that the prune()
function be called after deletion of each node to ensure that internal nodes whose tips are deleted are removed instead of becoming tips. Alternatively, one could test for internal nodes whose children are deleted in the procedure and flag these nodes to be deleted as well.
First, generate a list of tip nodes.
Next, iterate through this list, compare the distances to Aerococcus, and append to the deletion list if greater than 1.8.
Now for the actual deletion process. We can simply use the parent of each node in the deletion list to remove itself. Pruning is necessary to prevent internal nodes from being left as tips. Note: remove()
and remove_node()
return ‘True’ if a node is successfully removed, ‘False’ otherwise.
Finally, print the modified complex_tree
.