Reputation: 7929
Say that I have a regular 2d grid graph G
made of NxN=100x100
nodes. I create such network by calling:
N=100
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() ) #Dictionary of all positions
labels = dict( ((i, j), i + (N-1-j) * N ) for i, j in G.nodes() )
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10)
and I get a result similar to that shown in the left hand side of this picture:
Now, say that my network experiences a disruptive event which renders a number of nodes failed (right hand side of the picture). My graph G
is no longer made of the same number of nodes: graph G2
now possesses K<NxN
nodes. Given this case, I want to be able to draw G2
by calling:
G2=G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes
nx.draw_networkx(G2, pos=pos, labels=labels,with_labels=False, node_size=10)
My question. How can I do this, in order to make sure that the dictionary of positions pos
is not altered? This means: if node 0
is in position (0,0)
(upper left) in situation 1) and it does not fail, then it must appear in the same position in situation 2). This way, the two networks can be comparable in that the second is just a "transformation" of the first. Thanks!
Upvotes: 2
Views: 1637
Reputation: 15909
I would extend a bit the answer of @AbdallahSobehy. However, for a more general reusability of networkx
graphs, I would suggest storing position and label information inside the graph structure, rather than in a separate containers.
Starting with the reduced version of your graph (for N = 5
):
N = 5
G = nx.grid_2d_graph(N,N)
pos = dict((n, n) for n in G.nodes())
labels = dict(((i, j), i + (N-1-j) * N) for i, j in G.nodes())
One can store pos
and label
dictionaries as graph attributes:
nx.set_node_attributes(G, 'pos', pos)
nx.set_node_attributes(G, 'labels', labels)
And use them for ploting:
nx.draw_networkx(G, pos=nx.get_node_attributes(G, 'pos'),
labels=nx.get_node_attributes(G, 'labels'),
with_labels=True, node_size=500)
You can later perfom any operation in the graph, such as removing some nodes:
G.remove_nodes_from([(0,0),(0,2),(2,2),(2,1)])
And replot the graph without actually needing to recalculate pos
or label
dictionaries, as the entries are automatically updated with the graph operations. The following line is exactly the same as the plot call above:
nx.draw_networkx(G, pos=nx.get_node_attributes(G, 'pos'),
labels=nx.get_node_attributes(G, 'labels'),
with_labels=True, node_size=500)
But this time, yields a different image:
In short: store everything you can in node/edge attributes, as they will be automatically updated with graph changes.
Upvotes: 2
Reputation: 23887
I struggled to see why you were asking this question - the code should basically work exactly as you want already. However, you have an error which may be what is causing you to ask this question.
G2= G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes
This will make G2
be None
. G.remove_nodes_from(L)
removes the nodes in L
from G
. It doesn't create a new graph that looks like G
, but without those nodes. So it doesn't return anything. Because of this G2
isn't being given any value. The graph G
has had those nodes removed.
So the following should work:
N=100
G=nx.grid_2d_graph(N,N)
pos = dict( (n, n) for n in G.nodes() ) #Dictionary of all positions
labels = dict( ((i, j), i + (N-1-j) * N ) for i, j in G.nodes() )
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10)
#find failed nodes here
G.remove_nodes_from(failed_nodes_dict) #Failed_node_dict holds the disrupted nodes
nx.draw_networkx(G, pos=pos, labels=labels,with_labels=False, node_size=10)
pos
is never changed in this code.
Upvotes: 1
Reputation: 3021
You can do so by relabeling nodes from (i,j) to the numbers you see on the figures from the labels dictionary. Then remove the failed nodes. Finally, adjust the pos dictionary to map positions to the new labels of nodes by simply reversing the labels dictionary. Here is what I added after your code:
nx.relabel_nodes(G,labels,False)
G.remove_nodes_from([0,4,12,18])
pos = {y:x for x,y in labels.iteritems()}
nx.draw_networkx(G, pos=pos, with_labels=True, node_size = 300)
for an N = 5 and failed nodes [0,4,12,18], here is the results I got before (left) and after (right) failed nodes are removed.
Upvotes: 1