2
$\begingroup$

I am using Biopython Phylo and RDkit Cluster to obtain a UPGMA tree from a distance matrix of 5k x 5k entries. How can I extract the taxa names within a given clade(s)?

For example, Bio.Phylo can return plain-text representation of a tree, so I think I can parse it by the number of tabs:

Phylogeny()
     Clade()
         Clade(branch_length=0.06)
             Clade(branch_length=0.102, name='A')
             Clade(branch_length=0.23, name='B')
         Clade(branch_length=0.4, name='C') 
...

or, ASCII format:

          _____________ A
  _______|
_|       |_______________________________ B
 |
 |_______________________________________________________ C

Which, I think is more difficult to parse but possible. Either way, those are not established methods for this kind of task, so I would like a hint.

$\endgroup$
1
  • $\begingroup$ There are two packages that do this well, ETE3 and dendropy. I will put a ETE3 solution forward. $\endgroup$
    – M__
    Aug 11, 2022 at 2:23

1 Answer 1

2
$\begingroup$

The example given a 3 taxa tree, isn't an ideal example. What is required is a raw treefile in a common format (nexus, philip, newark). The example below uses ETE3 for a 5 taxa tree A,B,C,D,E. Its ROOTED - very important to know the direction.

ETE3 is providing a means of traversing down the tree from the root, however the coder needs to interrogate the path it has taken.

  1. Tree file imported
  2. Ladderizing ... so you know the horizontal direction of the tree (see *)
  3. Ask the ETE3 to search down the nodes ... each child is a node from the root.
  4. Parse the output and identify the clade.

The two outputs from point 3 are either it encounters a node - in this case it returns all the children below it (taxa names). The alternative is that it encounters a terminal node or a leaf, like a species name or isolate. In this case the taxa name is returned.

The caveat is the terminal node (taxa label or leaf) is always bifurcation and the taxa names are split into [1] and [0] on the ETE3 object (see code) ... you have to interrogate both.

Thats what the OP is looking for and this part of the code is marked 'Part 1'

Parsing Part 2 is more complicated, because usually the coder wants the clade a particular taxa (or leaf) belongs to. Essentially, the coder needs to ask what the leaf name is, if the target leaf name is found then the clade is then identified, i.e. the other stuff next to it.

The code is below. I agree if you don't think trees, this is a rushed explanation.

from ete3 import Tree

# Part 1
tree = Tree(intree, format=1)
tree.ladderize(direction=1)
clade1_ = tree.children[0].children[0].children[0].name
leaf1_ = tree.children[0].children[0].children[0].children[0].name 
leaf2_ = tree.children[0].children[0].children[0].children[1].name

# Part 2
if leaf1 == 'A' or leaf2 == 'A':
    CladeA = clade1_
if leaf2 == 'B' or leaf2 == 'B':
    CladeA = clade1_

*, ladderizing that can be important for classifying [0] and [1] in ETE3 ... its a weird one in trees 'cause it shouldn't matter

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.