3

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:

  • I would like the graph be horizontal, so that node 0 is the origin at the left.
  • I would like to manipulate the length of the arrows (reduce them).
  • I would like to have arrows between all nodes that have edges between one another, so also between node 3 and 5 , 5 and 7, 7 and 8, etc. (I checked G.edges() and they exist, but don't get displayed)

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()

And this is what I get... enter image description here

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: enter image description here.

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: enter image description here

  • 1
    related? https://stackoverflow.com/a/29597209/2966723. You'd need to interchange the x and y coordinates. I'm not sure whether networkx allows scaling of the edge length. I think the reason some of your edges appear to be missing is that the nodes are drawn too big and overlap. – Joel Dec 03 '20 at 11:21
  • @Joel You were right about the node size, thanks! It seems related, I can also run the code, but I don't see how I can make it horizontal. And it's strange to think that one cannot scale arrow length, but yeah I have not found anything on it... – casparschwa Dec 03 '20 at 11:55

1 Answers1

2

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).

Joel
  • 22,598
  • 6
  • 69
  • 93
  • Thanks! I finally managed to get the job done using [this](https://graphviz.org/doc/info/attrs.html#d:rankdir). See EDIT2 in my orginal post for the solution to the problem. – casparschwa Dec 04 '20 at 17:28