from cogent3 import load_tree
tr = load_tree("data/test.tree")
print(tr)(((Human:0.0311054096183,HowlerMon:0.0415847131449):0.0382963424874,Mouse:0.277353608988):0.0197278502379,NineBande:0.0939768158209,DogFaced:0.113211053859);
ascii_art()dict nodes keyed by their name(((Human:0.0311054096183,HowlerMon:0.0415847131449):0.0382963424874,Mouse:0.277353608988):0.0197278502379,NineBande:0.0939768158209,DogFaced:0.113211053859);
The path to the original file is stored in the .source attribute.
ascii_art() /-Human
/edge.0--|
/edge.1--| \-HowlerMon
| |
| \-Mouse
-root----|
|--NineBande
|
\-DogFaced
See the Phylogenetic Trees for interactive graphical display of dendrograms.
dict nodes keyed by their nameThe root node name defaults to "root".
You can ensure internal nodes get named
Get all the nodes, tips and edges as a dict.
('root', Tree("(((Human,HowlerMon),Mouse),NineBande,DogFaced);"))
('edge.1', Tree("((Human,HowlerMon),Mouse)"))
('edge.0', Tree("(Human,HowlerMon)"))
('Human', Tree("Human"))
('HowlerMon', Tree("HowlerMon"))
('Mouse', Tree("Mouse"))
('NineBande', Tree("NineBande"))
('DogFaced', Tree("DogFaced"))
As a list.
Only the tip (terminal) nodes as a list.
Iterate the tip nodes.
Get just the internal nodes as a list
or iteratively.
The sum of all lengths on nodes connecting tips to the root node.
{'B': 3.0, 'C': 7.0, 'D': 9.0}
Can also be done for a subset of tips.
Get a distance matrix between all pairs of tips and a list of the tip nodes.
Via pairwise distances, which returns a DistanceMatrix instance.
| names | Mouse | Human |
|---|---|---|
| Mouse | 0.0000 | 0.3468 |
| Human | 0.3468 | 0.0000 |
Or directly between the node objects.
A list of all nodes to the tree root.
On a PhyloNode without branch lengths each branch has a weight of 1 so the distances represent the number of connected nodes. On a PhyloNode with branch lengths the measure is the sum of branch lengths.
| names | Human | HowlerMon | Mouse | NineBande | DogFaced |
|---|---|---|---|---|---|
| Human | 0.0000 | 0.0727 | 0.3468 | 0.1831 | 0.2023 |
| HowlerMon | 0.0727 | 0.0000 | 0.3572 | 0.1936 | 0.2128 |
| Mouse | 0.3468 | 0.3572 | 0.0000 | 0.3911 | 0.4103 |
| NineBande | 0.1831 | 0.1936 | 0.3911 | 0.0000 | 0.2072 |
| DogFaced | 0.2023 | 0.2128 | 0.4103 | 0.2072 | 0.0000 |
The method name is a bit misleading. If tr is an unrooted tree (loosely, this is a tree whose root node has > 2 children) then the result is more a re-orientation of the tree rather than true root.
This does produce a rooted tree.
The edge can be either a tip or an internal node.
/-Human
/edge.0--|
/edge.1--| \-HowlerMon
| |
| \-Mouse
-root----|
|--NineBande
|
\-DogFaced
'(((Human,HowlerMon),Mouse),NineBande,DogFaced);'
'(((Human:0.0311054096183,HowlerMon:0.0415847131449):0.0382963424874,Mouse:0.277353608988):0.0197278502379,NineBande:0.0939768158209,DogFaced:0.113211053859);'
Use with_support=True to include the value of node.support on each node in the newick string.
'(a:1.0,b:2.0,(c:3.0,d:4.0)95:5.0);'
Combining with_support=True with with_node_names=True retains the internal node names alongside their support values.
Here is the example tree for reference:
/-Human
/edge.0--|
/edge.1--| \-HowlerMon
| |
| \-Mouse
-root----|
|--NineBande
|
\-DogFaced
/-a
/--------|
| \-b
|
| /-c
---------| /--------|
| | \-d
| |
| | /-e
\--------|---------|
| \-f
|
| /-g
\--------|
\-h
Provide the names of nodes you want the subtree for. The default behaviour is to force the subtree to have the same number of children at the root as the original tree, in this case 2.
/-c
---------|
| /-e
\--------|
\-g
Use the as_rooted argument to ensure the selected subtree topology is as it existed on the original tree.
/-c
|
---------|--e
|
\-g
.. We do some file clean up
/tmp/ipykernel_10453/2817304194.py:3: DeprecationWarning: function remove_files is discontinued and will be removed in version 2026.9
reason='use shutil instead'
remove_files(["data/temp.tree", "data/temp.pdf"], error_on_missing=False)
Remove internal nodes with only one child. Create new connections and branch lengths (if tree is a PhyloNode) to reflect the change.
/-B
-root----|
\E------- /-D
The prune() modifies the tree in place.
(((Human,HowlerMon),Mouse),NineBande,DogFaced);
Add internal nodes so that every node has 2 or fewer children.
/-B
|
|--H
-G-------|
| /-C
| |
\F-------|--D
|
\-E
Using a balanced tree can substantially improve performance of likelihood calculations for time-reversible models. Note that the resulting tree has a different orientation with the effect that specifying clades or stems for model parameterisation should be done using the “outgroup_name” argument.
/-Human
/edge.0--|
/edge.1--| \-HowlerMon
| |
| \-Mouse
-root----|
|--NineBande
|
\-DogFaced
Branch lengths don’t matter.
A number of topological tree distance metrics are available. They include:
There are several variations of the Robinson-Foulds metric in the literature. The definition used by cogent3 is the cardinality of the symmetric difference of the sets of clades/splits in the two rooted/unrooted trees. Other definitions sometimes divide this by two, or normalise it to the unit interval.
The Robinson-Foulds distance is quick to compute, but is known to saturate quickly. Moving a single leaf in a tree can maximise this metric.
The Matching Cluster and Lin-Rajan-Moret are two matching-based distances that are more statistically robust. Unlike the Robinson-Foulds distance which counts how many of the splits/clades are not exactly same, the matching-based distances measures the degree by which the splits/clades are different. The matching-based distances solve a min-weight matching problem, which for large trees may take longer to compute.
# Distance metrics for rooted trees
from cogent3 import make_tree
tr1 = make_tree(treestring="(a,(b,(c,(d,e))));")
tr2 = make_tree(treestring="(e,(d,(c,(b,a))));")
mc_distance = tr1.tree_distance(tr2, method="matching_cluster") # or method="mc" or method="matching"
rooted_rf_distance = tr1.tree_distance(tr2, method="rooted_robinson_foulds") # or method="rrf" or method="rf"
print("Matching Cluster Distance:", mc_distance)
print("Rooted Robinson Foulds Distance:", rooted_rf_distance)Matching Cluster Distance: 10
Rooted Robinson Foulds Distance: 6
# Distance metrics for unrooted trees
from cogent3 import make_tree
tr1 = make_tree(treestring="(a,b,(c,(d,e)));")
tr2 = make_tree(treestring="((a,c),(b,d),e);")
lrm_distance = tr1.tree_distance(tr2, method="lin_rajan_moret") # or method="lrm" or method="matching"
unrooted_rf_distance = tr1.tree_distance(tr2, method="unrooted_robinson_foulds") # or method="urf" or method="rf"
print("Lin-Rajan-Moret Distance:", lrm_distance)
print("Unrooted Robinson Foulds Distance:", unrooted_rf_distance)Lin-Rajan-Moret Distance: 3
Unrooted Robinson Foulds Distance: 4