Reputation: 1521
This is a follow up to my previous question posted here to visualize edge attacks in graphs.
The code below has been posted as an answer to my previous post
import matplotlib.pyplot as plt
import networkx as nx
H = nx.gnm_random_graph(n=8, m=9, seed=5) # generate a random graph
H.add_edges_from([('I', 1), (5, 'O')]) # adding input/output nodes
pos = nx.spring_layout(H, iterations=200) # find good positions for nodes
def attack(G, edge, color):
G.remove_edge(*edge) # first remove the edge
# check if another could be also impacted
if G.degree[edge[0]] == 1:
neighbor = [n for n in G.neighbors(edge[0])][0]
impacted_edge = (edge[0], neighbor)
elif G.degree[edge[1]] == 1:
neighbor = [n for n in G.neighbors(edge[1])][0]
impacted_edge = (edge[1], neighbor)
else:
impacted_edge = None
G.add_edge(*edge) # put back the edge to redraw it
# redraw the attacked edge (solid) and the possible impacted one (dashed)
if impacted_edge:
nx.draw_networkx_edges(
G,
edgelist=[impacted_edge],
pos=pos,
edge_color=color,
style='dashed',
width=4
)
nx.draw_networkx_edges(
G,
edgelist=[edge],
pos=pos,
edge_color=color,
label=f'attack {edge[0]}{edge[1]}',
style='solid',
width=4
)
# attack some edges
attack(H, (6, 4), color='red')
attack(H, (3, 6), color='blue')
attack(H, (1, 2), color='green')
nx.draw(H, pos, node_size=700, with_labels=True, node_color='gray')
plt.legend()
plt.show()
The solid lines indicate the edges that are attacked and the dashed lines of same color indicate the neighboring edges that are impacted due to a specific attack.
The answer helps but there is a problem when the impacted edges overlap.
Example,
attack(H, (6, 4), color='red')
attack(H, (5, 4), color='yellow')
The colors overlap and it's hard to visualize. If we can draw the dashed lines that indicate the impacted/attacked edges next to each other, without overlapping like shown in this image that will be good.
Suggestions on how to improve this visualization will be greatly appreciated!
EDIT: The answer posted below is really useful for 2D networks and I am still
looking for ways to extend this to visualize 3D networks (i.e when x,y,z coordinates are available as pos
attributes of a node) in pyvis. Suggestions will be greatly appreciated.
Upvotes: 2
Views: 1538
Reputation: 733
Another good way to avoid the overlapping edges in your graph is to use pyvis
, however the problem here is that it only supports parallel edges in directed graphs. One solution is to visualize your graph as a directed one and then tweak the edge options to make the arrow unnoticeable. Add the following snippet to end of the above code.
from pyvis.network import Network
N = Network(bgcolor='#222222', font_color='white', directed=True)
N.set_edge_smooth('dynamic')
for n in H.nodes:
N.add_node(n, color='gray')
for e in H.edges:
N.add_edge(e[0], e[1], color='gray', width=0)
for e in impacted_edges:
N.add_edge(e[0], e[1], color=e[2], width=1, dashes=True)
for e in edges:
N.add_edge(e[0], e[1], color=e[2], width=1)
N.set_options('''
var options = {
"edges": {
"arrows": {
"to": {
"enabled": true,
"scaleFactor": 0
},
"middle": {
"enabled": true,
"scaleFactor": 0
},
"from": {
"enabled": true,
"scaleFactor": 0
}
},
"color": {
"inherit": true
},
"smooth": {
"forceDirection": "none"
}
},
"physics": {
"minVelocity": 0.75
}
}
''')
N.write_html('example_graph.html')
You can find the following graph in example_graph.html
:
Upvotes: 4