Create input arrows in networkx - python

I'm wondering if is possible to create some sort of notation to indicate inputs for a graph in networkx / Python.
For example, taking the image presented here, supposed I want to be able to identify sources and sinks. I would be interested in creating a representation such as:
Is that possible?

The annotate functionality does exactly what you want. (See also the annotate intro)
Given the example you linked, you could just add the following to annotate selected nodes. (It depends on the positions dictionary pos to know where the nodes are located).
ax = plt.gca()
ax.annotate("3", xy=pos.get('B'), xytext=(0, 40), textcoords='offset points',
arrowprops=dict(facecolor='black', shrink=0.15),
bbox=dict(boxstyle="round", fc="cyan"))
ax.annotate("4", xy=pos.get('F'), xytext=(0, 40), textcoords='offset points',
arrowprops=dict(facecolor='black', shrink=0.15),
bbox=dict(boxstyle="round", fc="cyan"))
So that this answer is self-contained, Full code including linked example:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()
G.add_edges_from(
[('A', 'B'), ('A', 'C'), ('D', 'B'), ('E', 'C'), ('E', 'F'),
('B', 'H'), ('B', 'G'), ('B', 'F'), ('C', 'G')])
val_map = {'A': 1.0,
'D': 0.5714285714285714,
'H': 0.0}
values = [val_map.get(node, 0.25) for node in G.nodes()]
# Specify the edges you want here
red_edges = [('A', 'C'), ('E', 'C')]
edge_colours = ['black' if not edge in red_edges else 'red'
for edge in G.edges()]
black_edges = [edge for edge in G.edges() if edge not in red_edges]
# Need to create a layout when doing
# separate calls to draw nodes and edges
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, cmap=plt.get_cmap('jet'),
node_color = values, node_size = 500)
nx.draw_networkx_labels(G, pos)
nx.draw_networkx_edges(G, pos, edgelist=red_edges, edge_color='r', arrows=True)
nx.draw_networkx_edges(G, pos, edgelist=black_edges, arrows=False)
# add annotations for selected nodes.
ax = plt.gca()
ax.annotate("3", xy=pos.get('B'), xytext=(0, 40), textcoords='offset points',
arrowprops=dict(facecolor='black', shrink=0.15),
bbox=dict(boxstyle="round", fc="cyan"))
ax.annotate("4", xy=pos.get('F'), xytext=(0, 40), textcoords='offset points',
arrowprops=dict(facecolor='black', shrink=0.15),
bbox=dict(boxstyle="round", fc="cyan"))
plt.show()

Related

NetworkX add node after spring_layout to the graph

Having the following code:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_nodes_from(range(1, 10))
G.add_edges_from([(1, 3), (2, 4), (3, 4), (2,6), (1, 2), (4, 9), (9, 1)])
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True)
plt.show()
G.add_node(10)
nx.draw(G, pos, with_labels=True) # this gives the error
plt.show()
How can I add node 10 to the graph at a random position?
The error I'm actually getting is:
NetworkXError: Node 10 has no position.
How can I include the newly created node to the graph already built spring_layout?
The problem (as already noted by others) is that pos is a dict which assigns a position to each node. But when you've added a node, it doesn't update pos.
The following will find a good position for new node 10 given the existing position of all the other nodes. Basically, it calls spring_layout again, but holds all of the existing nodes in place. I've got node 10 connected to node 9.
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_nodes_from(range(1, 10))
G.add_edges_from([(1, 3), (2, 4), (3, 4), (2,6), (1, 2), (4, 9), (9, 1)])
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True)
plt.show()
G.add_node(10)
G.add_edge(9,10) #So node 10 should be close to node 9
oldnodes = list(G.nodes())
oldnodes.remove(10)
pos = nx.spring_layout(G, pos=pos, fixed=oldnodes)
nx.draw(G, pos, with_labels=True)
plt.show()
The output from spring layout is a dictionary mapping nodes to positions
{nodeid:[x,y]}. To place the new node randomly, you have to give it a random position in the pos dictionary.
Here is an example that finds the bounding box and then picks a random point somewhere inside.
import numpy as np
bounds = np.zeros((2,2)) # xy min, xymax
for pt in pos.values():
bounds[0] = np.min([bounds[0],pt], axis=0) # compare point to bounds and take the lower value
bounds[1] = np.max([bounds[1],pt], axis=0) # compare point to bounds and take the highest value
pos[10] = (bounds[1] - bounds[0]) * np.random.random(2) + bounds[0]

Networkx: how to change a color and size of same edges?

I generated a graph using networkx
import networkx as nx
G = nx.grid_graph(dim=[5,5])
nx.draw(G);
Then I compute the minimal path between two nodes using the astar algorithm
def dist(a, b):
(x1, y1) = a
(x2, y2) = b
return ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5
nodes = list(G.nodes)
tmp = nx.astar_path(G,nodes[3],nodes[14],dist)
Now I would like to to modify the color and the size of the edges of the path between the nodes, where the nodes are defined by tmp
tmp
[(0, 3), (1, 3), (2, 3), (2, 4)]
You need to plot each of the network's components with its own commands. Here is a working code that demonstrates how to achieve such a plot.
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
# only relevant part is treated here
G = nx.grid_graph(dim=[5,5])
node_list = [(0, 3), (1, 3), (2, 3), (2, 4)]
edge_list = [[(0, 3), (1, 3)], [(1, 3), (2, 3)], [(2, 3), (2, 4)]]
pos = nx.spring_layout(G)
nx.draw(G, pos=pos, with_labels=True)
# draw selected nodes in green with triangle shape
nx.draw_networkx_nodes(G, pos=pos, nodelist=node_list, node_size=300, node_color='g', node_shape='^')
# draw selected edges in blue with solid line
nx.draw_networkx_edges(G, pos=pos, edgelist=edge_list, width=3.0, edge_color='blue', style='solid')
The output plot:

Color a subgraph

I have a complete graph (all nodes are directly connected by an edge), and I want to color a subset of nodes and edges over the same graph. The complete graph for N=5 is this.
N=5 COMPLETE GRAPH
Now I want to color, for example, the next subset of edges: [(0, 3), (1, 0), (2, 1), (3, 4), (4, 2)] in blue. How can I do that over the same graph?.
Thanks in advance.
If you use the draw_networkx_* functions to separately draw each part of the graph (nodes, node labels, edges, edge labels), you have fine control of what is rendered. The main trick is to produce the positions dictionary and then reuse it for each drawing function.
import networkx as nx
import itertools
import matplotlib.pyplot as plt
# produce a degree-5 complete directed graph
G = nx.DiGraph()
edges = itertools.permutations(xrange(5), 2) # see https://stackoverflow.com/a/10651524/1643946
G.add_edges_from(edges)
# specific path to highlight
elist = [(0, 3), (1, 0), (2, 1), (3, 4), (4, 2)]
# set up layout
pos = nx.circular_layout(G)
# draw it
nx.draw_networkx_nodes(G, pos)
nx.draw_networkx_labels(G, pos)
nx.draw_networkx_edges(G, pos, edge_color='k', width=0.5) # show all edges, thin lines
nx.draw_networkx_edges(G, pos, edgelist=elist, edge_color='b', width=2) # highlight elist
# turn off axis markings
plt.axis('off')
Produces a graph like this:

NetworkX: 'Graph'

I have the following error:
Traceback (most recent call last):
File "net.py", line 6, in <module>
G=nx.Graph()
AttributeError: 'module' object has no attribute 'Graph'
when I run this code:
import networkx as nx
import pylab as py
blue_edges = [('B', 'C'), ('B', 'D'), ('B', 'E'), ('E', 'F')]
red_edges = [('A', 'B'), ('A', 'C'), ('C', 'E'), ('D', 'E'), ('D', 'F')]
G=nx.Graph() #define G
G.add_edges_from(blue_edges)
G.add_edges_from(red_edges)
pos = {'A':(0,0), 'B':(1,1), 'C':(1,-1), 'D':(2,1), 'E':(2,-1), 'F':(3,0)}
nx.draw_networkx(G, pos=pos, edgelist = [], node_color = 'k')
nx.draw_networkx(G, pos=pos, nodelist = [], edgelist = blue_edges, edge_color = 'b')
nx.draw_networkx(G, pos=pos, nodelist = [], edgelist = red_edges, edge_color = 'r')
I use python 2.7 and 1.11 networkx library all within anaconda

NetworkX: Drawing Graph

I am trying to draw a graph using NetworkX in Python. I am using the following code:
G=nx.to_networkx_graph(adj)
pos=nx.spring_layout(G)
#G=nx.path_graph(8)
nx.draw(G,pos,labels)
plt.savefig("simple_path.png") # save as png
plt.show() # display
I get this output:
But I want to get the following output with Labels:
What can I do on the code? thank you.
So for the positioning, you've set pos based on spring_layout. pos gives the positions of your nodes. Check it out - once you've defined it, ask python to print pos for you and see what it's doing.
Here's an alternative code:
import networkx as nx
import pylab as py
blue_edges = [('B', 'C'), ('B', 'D'), ('B', 'E'), ('E', 'F')]
red_edges = [('A', 'B'), ('A', 'C'), ('C', 'E'), ('D', 'E'), ('D', 'F')]
G=nx.Graph() #define G
G.add_edges_from(blue_edges)
G.add_edges_from(red_edges)
pos = {'A':(0,0), 'B':(1,1), 'C':(1,-1), 'D':(2,1), 'E':(2,-1), 'F':(3,0)}
nx.draw_networkx(G, pos=pos, edgelist = [], node_color = 'k')
nx.draw_networkx(G, pos=pos, nodelist = [], edgelist = blue_edges, edge_color = 'b')
nx.draw_networkx(G, pos=pos, nodelist = [], edgelist = red_edges, edge_color = 'r')
and if you want it without the x and y axes showing, change the last bit to:
nx.draw(G, pos=pos, edgelist = [], node_color = 'k')
nx.draw(G, pos=pos, nodelist = [], edgelist = blue_edges, edge_color = 'b')
nx.draw(G, pos=pos, nodelist = [], edgelist = red_edges, edge_color = 'r')

Categories