Plotly Tree covered by Node and Background

I’ve followed the example on plotting the tree from Tree-plots | Python | Plotly. However, I’ve a very long annotation but it is covered by the background such that it is cut off. Is it possible to annotate it outside the circle? I’ve pasted the code below. It can be run directly by copying and pasting the code into your machine. I cannot upload a picture of it here due to policy.

import igraph
from igraph import Graph, EdgeSeq
nr_vertices = 25
v_label = list(map(str, range(nr_vertices)))
G = Graph.Tree(nr_vertices, 2) # 2 stands for children number
lay = G.layout('rt')

position = {k: lay[k] for k in range(nr_vertices)}
Y = [lay[k][1] for k in range(nr_vertices)]
M = max(Y)

es = EdgeSeq(G) # sequence of edges
E = [e.tuple for e in G.es] # list of edges

L = len(position)
Xn = [position[k][0] for k in range(L)]
Yn = [2*M-position[k][1] for k in range(L)]
Xe = []
Ye = []
for edge in E:
    Xe+=[position[edge[0]][0],position[edge[1]][0], None]
    Ye+=[2*M-position[edge[0]][1],2*M-position[edge[1]][1], None]

labels = v_label

import plotly.graph_objects as go
fig = go.Figure()
fig.add_trace(go.Scatter(x=Xe,
                   y=Ye,
                   mode='lines',
                   line=dict(color='rgb(210,210,210)', width=1),
                   hoverinfo='none'
                   ))
fig.add_trace(go.Scatter(x=Xn,
                  y=Yn,
                  mode='markers',
                  name='bla',
                  marker=dict(symbol='circle-dot',
                                size=18,
                                color='#6175c1',    #'#DB4551',
                                line=dict(color='rgb(50,50,50)', width=1)
                                ),
                  text=labels,
                  hoverinfo='text',
                  opacity=0.8
                  ))

def make_annotations(pos, text, font_size=10, font_color='rgb(250,250,250)'):
    L=len(pos)
    if len(text)!=L:
        raise ValueError('The lists pos and text must have the same len')
    annotations = []
    for k in range(L):
        annotations.append(
            dict(
                text=labels[k], # or replace labels with a different list for the text within the circle
                x=pos[k][0], y=2*M-position[k][1],
                xref='x1', yref='y1',
                font=dict(color=font_color, size=font_size),
                showarrow=False)
        )
    return annotations

axis = dict(showline=False, # hide axis line, grid, ticklabels and  title
            zeroline=False,
            showgrid=False,
            showticklabels=False,
            )

labels = ["Long text to show in the node but it is covered unfortunately", "bbbbbbbbbbbbbbbbbb",'2',
 '3',
 '4',
 '5',
 '6',
 '7',
 '8',
 '9',
 '10',
 '11',
 '12',
 '13',
 '14',
 '15',
 '16',
 '17',
 '18',
 '19',
 '20',
 '21',
 '22',
 '23',
 '24']

fig.update_layout(title= 'Tree with Reingold-Tilford Layout',
              annotations=make_annotations(position, v_label),
              font_size=12,
              showlegend=False,
              xaxis=axis,
              yaxis=axis,
              margin=dict(l=40, r=40, b=85, t=100),
              hovermode='closest',
              plot_bgcolor='rgb(248,248,248)'
              )
fig.show()

@zytan
This example of plotting a tree is 5-6 years old. Meantime Plotly object definitions have been changed.

  • I modified the code such that you can display long node labels, either by truncating them or with their length.

  • I removed annotations. The node labels in v_label are displayed as text (see
    mode ="markers+text" in the trace definition for nodes). Supplementary long labels are added as customdata, and they are displaed as tooltips according to hoverformat.

  • the hoverinfo=‘none’ in the trace that defines the edges is now replaced by hoverinfo="skip".

  • the efect of xaxis= axis, a dict that removes zeroline, grid, etc is now replaced by setting:

xaxis_visible=False
yaxis_visible=False
import plotly.graph_objects as go
fig = go.Figure()

labels = ["Long text<br>to show in the node<br>but it is covered<br>unfortunately", 
          "this is also<br>a long label",'aaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
 '3',
 '4',
 '5',
 '6',
 '7',
 '8',
 '9',
 '10',
 '11',
 '12',
 '13',
 '14',
 '15',
 '16',
 '17',
 '18',
 '19',
 '20',
 '21',
 '22',
 '23',
 '24']

fig.add_trace(go.Scatter(x=Xe,
                   y=Ye,
                   mode='lines',   
                   line=dict(color='rgb(210,210,210)', width=1),
                   hoverinfo="skip"
                   ))
fig.add_trace(go.Scatter(x=Xn,
                  y=Yn,
                  mode='markers+text',
                  name='bla',
                  customdata=labels,
                  hovertemplate="%{customdata}<extra></extra>",
                  marker=dict(
                                size=26,
                                color='#6175c1',    #'#DB4551',
                                line=dict(color='rgb(50,50,50)', width=1)
                                ),
                  text=v_label,
                  textfont_color="white",

                  opacity=0.8
                  ))

fig.update_layout(title_text= 'Tree with Reingold-Tilford Layout',
                  title_x=0.5,
              font_size=12,
              showlegend=False,
              xaxis_visible=False,
              yaxis_visible=False,
              margin=dict(l=40, r=40, b=85, t=100),
              hovermode='closest',
              plot_bgcolor='rgb(248,248,248)'
              )
1 Like

Thanks a lot! Is it possible to wrap the labels into a defined size? such that it won’t just be a 1 liner