Working with time trees
***********************
.. contents::
The TimeTree class
==================
A :class:`TimeTree` can be initialized with a given newick string using the |etree| constructor and its format options.
Additionally, a :class:`TREE` object (:ref:`c classes`) is generated and saved in the :class:`TimeTree` and used for efficient RNNI distance computations.
.. |etree| raw:: html
ete3.Tree
TimeTree attributes
-------------------
.. table::
======================================== ========================================================================================================
Method Description
======================================== ========================================================================================================
:attr:`TimeTree.etree` returns the :class:`ete3.Tree` object
:attr:`TimeTree.ctree` returns the respective :class:`TREE` object
:attr:`len(TimeTree)` returns the number of leaves of the :class:`TimeTree`
:attr:`TimeTree.fp_distance(t)` returns the findpath distance to another :class:`TimeTree` *t*
:attr:`TimeTree.fp_path(t)` returns a :class:`TREE_LIST` object, allocated memory needs to be freed!
:attr:`TimeTree.get_newick(format)` returns the *write()* function of the :class:`ete3.Tree` with the specified *format*, defaults to *format=5*
:attr:`TimeTree.copy()` returns a deep copy of the current :class:`TimeTree`
:attr:`TimeTree.neighbours()` returns a list of :class:`TimeTree`'s containing all neighbours at distance *1*
:attr:`TimeTree.rank_neighbours()` returns a list of :class:`TimeTree`'s containing only neighbours one *rank move* away
:attr:`TimeTree.nni_neighbours()` returns a list of :class:`TimeTree`'s containing only neighbours one *NNI move* away
:attr:`TimeTree.nwk_to_cluster()` computes the set of all clades present in the given :class:`TimeTree`
:attr:`TimeTree.apply_new_taxa_map()` applies a new taxa map (in form of a dictionary) to a :class:`TimeTree`
======================================== ========================================================================================================
This is an example of how to access the different attributes of a TimeTree object:
.. code-block:: python
from tetres.trees.time_trees import TimeTree, free_tree_list
# Initialize a time tree from a newick string
tt = TimeTree("((1:3,5:3):1,(4:2,(3:1,2:1):1):2);")
tt.ctree # the TREE class object
tt.etree # the ete3.Tree object
len(tt) # Number of leaves in the tree tt --> 5
tt.fp_distance(tt) # Distance to another TimeTree --> 0
path = tt.fp_path(tt) # A shortest path to another TimeTree --> []
free_tree_list(path) # Allocated memory needs to be freed after usage
tt.get_newick() # Returns the newick string in ete3 format=5
ttc = tt.copy() # ttc contains a deep copy of the TimeTree tt
tt.neighbours() # a list of TimeTree objects each at distance one to tt
tt.rank_neighbours() # list of TimeTree obtained by doing all possible rank moves on tt
tt.nni_neighbours() # list of TimeTree obtained by doing all possible NNI moves on tt
tt.nwk_to_cluster() # returns set of all clades in the tree
tt.apply_new_taxa_map(new_map, old_map) # Will apply the new taxa map to the tree
ete3 functionalities
--------------------
Via the :class:`ete3.Tree` object the respective function of the :mod:`ete3` package are available for a :class:`TimeTree` object.
For example drawing and saving a tree to a file:
.. code-block:: python
from tetres.trees.time_trees import TimeTree
tt = TimeTree("((1:3,5:3):1,(4:2,(3:1,2:1):1):2);")
# Automatically save the tree to a specific file_path location
tt.etree.render('file_path_string')
# Defining a layout to display internal node names in the plot
def my_layout(node):
if node.is_leaf():
# If terminal node, draws its name
name_face = ete3.AttrFace("name")
else:
# If internal node, draws label with smaller font size
name_face = ete3.AttrFace("name", fsize=10)
# Adds the name face to the image at the preferred position
ete3.faces.add_face_to_node(name_face, node, column=0, position="branch-right")
ts = ete3.TreeStyle()
ts.show_leaf_name = False
ts.layout_fn = my_layout
ts.show_branch_length = True
ts.show_scale = False
# Will open a separate plot window, which also allows interactive changes and saving the image
tt.etree.show(tree_style=ts)
See the :mod:`ete3` `documentation `_ for more options.
The TimeTreeSet class
=====================
A :class:`TimeTreeSet` is an iterable list of :class:`TimeTree` objects, which is initialized with a nexus file (as returned by a BEAST2 analysis), hence it contains a taxa map.
=========================================== ========================================================================================================
Method Description
=========================================== ========================================================================================================
:attr:`TimeTreeSet.map` a dictionary conataining the taxa to integer translation from the nexus file
:attr:`TimeTreeSet.trees` a list of :class:`TimeTree` objects
:attr:`TimeTreeSet[i]` returns the :class:`TimeTree` at :attr:`TimeTreeSet.trees[i]`
:attr:`len(TimeTreeSet)` returns the number of trees in the list :attr:`TimeTreeSet.trees`
:attr:`TimeTreeSet.fp_distance(i, j)` returns the distances between the trees at postition i and j
:attr:`TimeTreeSet.fp_path(i, j)` returns a shortest path (:class:`TREE_LIST`) between the trees at postition i and j
:attr:`TimeTreeSet.copy()` returns a copy of the list of :class:`TimeTree`s
:attr:`TimeTreeSet.get_common_clades()` returns and computes the set of shared clades among all trees in the set
:attr:`TimeTreeSet.change_mapping(new_map)` Will apply the given new taxa map to all trees in the set
=========================================== ========================================================================================================
Reading Trees
-------------
A TimeTreeSet object can be initialized with a path to a nexus file.
.. code-block:: python
from tetres.trees.time_trees import TimeTreeSet, free_tree_list
# Initializing with a path to a nexus tree file
tts = TimeTreeSet("path_to_nexus_file.nex")
tts.map # a dictionary keys:int and values:string(taxa)
tts.trees # A list of TimeTree objects
for tree in tts:
# tree is a TimeTree object
...
tts[0] # trees are accessible via the index
len(tts) # Returns the number of trees in the TimeTreeSet object
tts.fp_distance(i, j) # Returns the distance between trees i and j
path = tts.fp_path(i, j) # Returns a shortest path between trees i and j
free_tree_list(path) # Allocated memory needs to be freed after usage
General Functions
=================
A list of the functions available from the module 'tetres.trees.time_trees'.
============================================= =====================================================================================
Function Description
============================================= =====================================================================================
:attr:`time_trees.neighbourhood(tree)` returns a list of :class:`TimeTree` objects containing the one-neighbours of tree
:attr:`time_trees.get_rank_neighbours(tree)` returns a list of :class:`TimeTree` objects containing the rank neighbours of tree
:attr:`time_trees.get_nni_neighbours(tree)` returns a list of :class:`TimeTree` objects containing the NNI neighbours of tree
:attr:`time_trees.read_nexus(file)` returns a list of :class:`TimeTree` objects contained in given the nexus file
:attr:`time_trees.get_mapping_dict(file)` returns a :class:`dictionary` containing the taxa to integer translation of the given file
:attr:`time_trees.findpath_distance(t1, t2)` Computes the distance between t1 and t2, returns :class:`int`
:attr:`time_trees.findpath_path(t1, t2)` Computes the path between t1 and t2, returns :class:`TREE_LIST`, after usage memory needs to be freed!
============================================= =====================================================================================
.. note::
Both functions :attr:`time_trees.findpath_distance(t1, t2)` and :attr:`time_trees.findpath_path(t1, t2)`
can be called with t1 and t2 being either a :class:`TREE`, :class:`TimeTree` or :class:`ete3.Tree`, both have to be the same type!
.. note::
When using :attr:`time_trees.findpath_path(t1, t2)` the c code is allocating memory to the returned object.
This memory needs to be freed with the :attr:`time_trees.free_tree_list(tree_list)` function to avoid memory leaks, see more info below!
Working with findpath_path and c memory
---------------------------------------
When using the :attr:`time_trees.findpath_path(t1, t2)` implementation it is important to free the memory of the
returned :class:`TREE_LIST` object. When calling the function the package will also throw a UserWarning indicating this.
Below are some examples of how to use the findpath_path implementation and the underlying class :class:`TREE_LIST`.
.. code-block:: python
from tetres.trees.time_trees import TimeTreeSet, free_tree_list
t1 = TimeTree()
t2 = TimeTree()
path = findpath_path(t1.ctree, t2.ctree) # Will throw a UserWarning
free_tree_list(path) # Free the memory allocated by c
# Calling findpath_path without the UserWarning being printed
with warnings.catch_warnings():
# Ignores the 'Free memory' warning issued by findpath_path
warnings.simplefilter("ignore")
# All following calls do the same thing, but the memory is not being freed
path = findpath_path(t1, t2)
path = findpath_path(t1.ctree, t2.ctree)
path = findpath_path(t1.etree, t2.etree)
# Use the c code to free the memory
from ctypes import CDLL
from tetres.trees._ctrees import TREE_LIST
lib = CDLL(f".../tetres/trees/findpath.so")
lib.free_treelist.argtypes = [TREE_LIST]
lib.free_treelist(path)
.. _c classes:
Classes for the c library
=========================
These classes are found in the :file:`_ctrees.py` module.
The corresponding CDLL c library is generated from :file:`findpath.c`.
NODE
----
- :attr:`parent`: index of the parent node (int, defaults to -1)
- :attr:`children[2]`: index of the two children ([int], defaults to [-1, -1])
- :attr:`time`: Time of the node (int, defaults to 0)
.. note::
The attribute :attr:`time` is currently not being used!
TREE
----
- :attr:`num_leaves`: Number of leaves in the tree (int)
- :attr:`tree`: Points to a :class:`NODE` object (POINTER(:class:`NODE`))
- :attr:`root_time`: Time of the root :class:`Node` (int)
.. note::
The attribute :attr:`root_time` is currently not being used!
TREELIST
--------
- :attr:`num_trees`: Number of trees in the list (int)
- :attr:`trees`: List of trees (POINTER(:class:`TREE`))
Class converter functions
=========================
These are found in :file:`_converter.py` and convert one tree type into the other.
When converting a ctree to an ete3 Tree the branch lengths are discrete integers since the ctrees do not have a branch length annotation.
=========================================== ================================================================
Function Description
=========================================== ================================================================
:attr:`_converter.ete3_to_ctree(tree)` traverses an :class:`ete3.Tree` and construct the correct :class:`TREE`
:attr:`_converter.ctree_to_ete3(ctree)` recursively traverses a :class:`TREE` and generates an :class:`ete3.Tree`
=========================================== ================================================================