Reputation: 179
I have a similar plot drawn with Networkx/Graphviz:
import networkx as nx
from networkx.drawing.nx_agraph import graphviz_layout
T = nx.balanced_tree(2, 5)
pos = graphviz_layout(T, prog="twopi")
nx.draw_networkx(T, pos, with_labels=True)
plt.show()
Which gives me the following plot:
What I want:
I want that all the node labels are rotated clockwise around the center of the graph. How do i do this? I would prefer a way directly with Networkx or Graphviz.
With "rotated clockwise" I mean similar like the labels on this polar plot:
I also tried with the following code:
T = nx.balanced_tree(2, 5)
pos = graphviz_layout(T, prog="twopi")
nx.draw_networkx(T, pos, with_labels=False)
text = nx.draw_networkx_labels(T, pos=pos)
for _, t in text.items():
t.set_rotation('clockwise')
plt.show()
But for set_rotation()
only 'horizontal', 'vertical', numeric value, or None
are supported.
I also found similar questions, but non of which could help me:
Does not plot the node labels and it's a quiet old question from 2017, also it seems for me to complicated: NetworkX node labels relative position
Answer is that it is not possible with graphviz in 2019: https://stackoverflow.com/questions/55009159/change-label-orientation-90º-of-a-node-in-graphviz
Upvotes: 3
Views: 1656
Reputation: 4705
A possible workaround of the limitations listed by @sroush is removing the node labels all together and label your nodes using plt.text
.
See code below:
import networkx as nx
import matplotlib.pyplot as plt
T = nx.balanced_tree(2, 5)
N_nodes=T.number_of_nodes()
fig,ax=plt.subplots(figsize=(10,5))
#Circular layout as an example
pos = nx.circular_layout(T)
#Setting up the text by using node position
texts=[plt.text(pos[i][0],pos[i][1],str(i),rotation=(i/N_nodes)*360,fontsize=10,horizontalalignment='center',verticalalignment='center') for i in range(N_nodes)]
#Plot result
nx.draw(T, pos)
ax.set_aspect('equal')
plt.show()
And the output gives:
EDIT: Using graphviz_layout(T, prog="twopi")
layout:
import networkx as nx
import matplotlib.pyplot as plt
from networkx.drawing.nx_agraph import graphviz_layout
T = nx.balanced_tree(2, 5)
N_nodes=T.number_of_nodes()
pos = pos = graphviz_layout(T, prog="twopi")
fig,ax=plt.subplots(figsize=(10,5))
texts=[plt.text(pos[i][0],pos[i][1],str(i),rotation=(i/N_nodes)*360,fontsize=10,horizontalalignment='center',verticalalignment='center') for i in range(N_nodes)]
nx.draw(T, pos)
ax.set_aspect('equal')
plt.show()
And the output gives:
EDIT 2: Fine tuning node layout:
import networkx as nx
import matplotlib.pyplot as plt
from networkx.drawing.nx_agraph import graphviz_layout
T = nx.balanced_tree(2, 5)
N_nodes=T.number_of_nodes()
first_rot_node=31
N_rot=T.number_of_nodes()-first_rot_node+1
pos = pos = graphviz_layout(T, prog="twopi")
fig,ax=plt.subplots(figsize=(10,5))
cmt=0
for i in range(N_nodes):
if i>=first_rot_node:
cmt+=1
if ((cmt-1)/N_rot)*360<90 or ((cmt-1)/N_rot)*360>=270:
plt.text(pos[i][0],pos[i][1],str(i),rotation=((cmt-1)/N_rot)*360,fontsize=11,horizontalalignment='center',verticalalignment='center')
elif ((cmt-1)/N_rot)*360>=90 and ((cmt-1)/N_rot)*360<270:
plt.text(pos[i][0],pos[i][1],str(i),rotation=((cmt-1)/N_rot)*360+180,fontsize=11,horizontalalignment='center',verticalalignment='center')
else:
plt.text(pos[i][0],pos[i][1],str(i),rotation=0,fontsize=11,horizontalalignment='center',verticalalignment='center')
nx.draw(T, pos)
ax.set_aspect('equal')
plt.show()
Upvotes: 3
Reputation: 6783
Graphviz does not support rotated text. Here is an outstanding request to provide this capability - https://gitlab.com/graphviz/graphviz/-/issues/2006.
Two possible Graphviz work-arounds:
Upvotes: 1