Reputation: 55
I am struggling to produce a plot that I want to get. I create a networkx
graph with a model of mine. To get the hierachical display of nodes I used graphviz_layout
. I managed to color code the nodes like I want to, but a few things I cannot get to work:
This is my code...
from networkx.drawing.nx_agraph import write_dot, graphviz_layout
G = model.block_tree.tree
write_dot(G,'test.dot')
pos = graphviz_layout(G, prog='dot', root=0)
plt.title("Some title")
nx.draw_networkx_nodes(G, pos, node_color=color_vector, node_shape='s', node_size=500)
nx.draw_networkx_edges(G, pos)
nx.draw_networkx_labels(G, pos, font_size=10, font_color="white")
plt.show()
I would greatly appreciate, if someone could point me towards the right direction. Thank you so much!!!
EDIT1
Thanks to a comment I now have arrows between all correct nodes. It turns out the nodes were too large and overlapping. Now it looks like this: .
I would stil like to get it horizontal and somehow scale the arrow length, if anyone knows...
EDIT2
I managed to get it working properly now. I reduced the arrow length by sequeezing the plot via figure size (not ideal solution, but gets the job done...)
The horizontal flip I managed to get working after figuring out that there was a conflict between root
and the extra arguments passed in the graphviz_lazout function. I used this documentation to get there. See code below:
def blocktree_plot(model):
honest_blocks = []
selfish_blocks = []
for block in model.block_tree.tree.nodes():
if model.block_tree[block]["miner_is_selfish"] == True:
selfish_blocks.append(model.block_tree[block]["id"])
else:
honest_blocks.append(model.block_tree[block]["id"])
fig, ax = plt.subplots(nrows=1, ncols=1, figsize=(6, 2), sharex=True, sharey=True)
G = model.block_tree.tree
H = G.reverse(copy=True)
pos = graphviz_layout(H, prog='dot', args='-Grankdir="RL"')
plt.title(r"Blockchain with Selfish Mining ($\alpha$ = {})".format(alpha))
nx.draw_networkx_nodes(H,pos=pos, nodelist=honest_blocks, node_color='green', label="Honest miner", node_shape='s', node_size=200)
nx.draw_networkx_nodes(H,pos=pos, nodelist=selfish_blocks, node_color='red', label="Selfish miner", node_shape='s', node_size=200)
nx.draw_networkx_nodes(H,pos=pos, nodelist=[0], node_color='blue', label="Genesis block", node_shape='s', node_size=200)
nx.draw_networkx_edges(H, pos, arrows=True)
nx.draw_networkx_labels(H, pos, font_size=10, font_color="white")
# plt.legend(labelspacing=0.8, fontsize=9, frameon=False, borderpad=0.1)
plt.show()
And this is what it looks like now:
Upvotes: 3
Views: 1781
Reputation: 23827
I don't know if it's possible to easily scale the edge lengths, so I'm leaving that part unanswered, and hoping someone else has a suggestion.
If you basically want to just rotate your figure, what you can do is the following:
tmppos = graphviz_layout(G, prog='dot', root=0)
pos = {node: (-y, x) for node, x,y in tmppos.items()}
which should take the original x and y coordinates and flip them (and make the downward direction in original turn into a rightward shift horizontally in the new).
Upvotes: 2