etetoolkit / ete

Python package for building, comparing, annotating, manipulating and visualising trees. It provides a comprehensive API and a collection of command line tools, including utilities to work with the NCBI taxonomy tree.
http://etetoolkit.org
GNU General Public License v3.0
773 stars 216 forks source link

any way to make each layer of the tree equal width? #697

Closed tommyfuu closed 10 months ago

tommyfuu commented 11 months ago

Hi!

I wish to make a visualization for a distance-agnostic tree where each layer (equal depth or number of steps from the most-ancestral node) occupies the same amount of horizontal space. I am wondering if there's a way to do that in the current ete3 framework?

For example, with the following tree

demonstrate_tree = Tree( """
                      (\
                          (\
                             (AAAAAA, \
                             BBBBBB, \
                             CCCC, \
                             DDDDDDD)\
                        aaaa,\
                            (BCB, \
                            AVDCSA)\
                        bb)\
                      a,\
                      (CVS)\
                     abcd)\
                  cc;\
                    """, format=1
                 )

print(demonstrate_tree.get_ascii(show_internal=True))

We get:


          /-AAAAAA
         |
         |--BBBBBB
      /aaaa
     |   |--CCCC
     |   |
   /a|    \-DDDDDDD
  |  |
  |  |   /-BCB
-cc   \bb
  |      \-AVDCSA
  |
   \abcd-CVS

and this, when rendered, looks like this image

You can notice that due to the differing lengths of the ancestral nodes, different layers occupy the same horizontal space. In our particular case, I want the node a and the node abcd to occupy the same horizontal space, potentially by making a a longer node. If there's a way to implement that, that will be great! Thanks!

dengzq1234 commented 11 months ago

Hi, I image you used faces.add_face_to_node() method to render the above picture. In this method, you can use the argument position="branch-top" so the TextFace of your node name will show above the branch such as mytree Here is I attached the code that I drew this image

from ete3 import Tree, TreeStyle, TextFace, faces t = Tree('(((AAAAAA:1,BBBBBB:1,CCCC:1,DDDDDDD:1)aaaa:1,(BCB:1,AVDCSA:1)bb:1)a:1,(CVS:1)abcd:1)cc:0;',format=1) ts = TreeStyle() ts.show_leaf_name = True ts.show_branch_length = False ts.show_branch_support = False def layout(node): if node.is_leaf(): pass else: if node.name: N = TextFace(node.name) faces.add_face_to_node(N, node, 0, position="branch-top") ts.layout_fn = layout t.render("mytree.png", w=183, units="mm", tree_style=ts)

Also we are now marching to ete4, as you may noticed in our main page of repo.

tommyfuu commented 11 months ago

hi,

thanks for your speedy response! in my actual tree that i am plotting i actually have some very long names. When I use the "branch-top" option, the tree visualizer nicely formed some dashed lines to add more space for the node name. However, this wiggle room enabled by the differing dash lines made the horizontal space occupied by nodes unequal again. Wondering if there are ways to fix that? thanks! image

tommyfuu commented 11 months ago

kind of found a hard-coded way to do it!

ts = TreeStyle()
ts.show_leaf_name = True
ts.show_branch_length = False
ts.show_branch_support = False
def layout(node):
    if node.is_leaf():
        pass
    else:
        if node.name:
            # N = TextFace(node.name, tight_text=True)
            N = RectFace(width=300,height=20, fgcolor=None, bgcolor=None,
                                 label={"text":node.name, "fonttype":"Courier", "color":"black", "fontsize":10})
            faces.add_face_to_node(N, node, 0, position="branch-top")
ts.layout_fn = layout
test_tree.render("mytree.png", w=1920, units="px", tree_style=ts)