Home > Net >  Position of images as nodes in networkx plot?
Position of images as nodes in networkx plot?

Time:01-19

After using enter image description here

The x,y-positions of the nodes is set as:

pos={
0: [0, 0], 
1: [1, 0], 
2: [2, 0], 
3: [3, 0], 
4: [4, 0], 
5: [5, 0], 
6: [6, 0], 
7: [5, 1]
}

and the code to generate the plot is:

pos:Dict={}
    for nodename in G.nodes:
        pos[nodename]=G.nodes[nodename]["pos"]
    print(f'pos={pos}')
    

    fig=plt.figure(figsize=(1,1))
    ax=plt.subplot(111)
    ax.set_aspect('equal')
    nx.draw_networkx_edges(G,pos,ax=ax)
    

    # plt.xlim(-1,10)
    # plt.ylim(-1.5,1.5)

    trans=ax.transData.transform
    trans2=fig.transFigure.inverted().transform

    piesize=0.3 # this is the image size
    p2=piesize/2.0
    for n in G:
        xx,yy=trans(pos[n]) # figure coordinates
        #print(f'xx,yy={xx,yy}')
        xa,ya=trans2((xx,yy)) # axes coordinates
        print(f'xa,ya={xa,ya}')
        a = plt.axes([xa-p2,ya-p2, piesize, piesize])
        a.set_aspect('equal')
        a.imshow(G.nodes[n]['image'])
        a.axis('off')
    ax.axis('off')
    plt.show()

However, the y-coordinates of the edges does not align with the y-coordinates of the images. I expect this is because the coordinate transformation applied for the plt.axes[[xa-p2... line, is not applied to the edge drawings.

Question

How can I ensure the images are placed on their x,y coordinate positions a figure with size [x_min,x_max,y_min,y_max] whilst ensuring the edges of the networkx Graph also point to the accompaning coordinates?

CodePudding user response:

Try not to set the axes ratio to equal (i.e. remove this line ax.set_aspect('equal')).

Though this will hopefully solve the question, there will probably the additional problem, that the arrow heads are hidden behind the images. A solution is to set the node_size parameter when calling nx.draw_networkx_edges().

When doing so an additional challenge is, that the image size seems to have different length and height values. A workaround is to first draw the vertical edges with a larger node_size. Then add the horizontal edges and set a smaller node_size (the vertical edges will be drawn again, but their arrow heads are hidden behind the image). You will probably have to play around with the values a bit.


pos={
0: [0, 0], 
1: [1, 0], 
2: [2, 0], 
3: [3, 0], 
4: [4, 0], 
5: [5, 0], 
6: [6, 0], 
7: [5, 1]
}

img=mpimg.imread(sample_img_path)
G=nx.DiGraph()
G.add_node(0,image=img)
G.add_node(1,image=img)
G.add_node(2,image=img)
G.add_node(3,image=img)
G.add_node(4,image=img)
G.add_node(5,image=img)
G.add_node(6,image=img)
G.add_node(7,image=img)


fig=plt.figure(figsize=(12,3))
ax=plt.subplot(111)
#ax.set_aspect('equal') # <-- not set the aspect ratio to equal

# draw vertical edges using a larger node size
G.add_edge(4,7)
G.add_edge(5,7)
G.add_edge(6,7)
nx.draw_networkx_edges(G,pos,ax=ax, node_size=8000, arrowsize=30)

# add the horizontal edges with a smaller node size
G.add_edge(0,1)
G.add_edge(1,2)
G.add_edge(2,3)
G.add_edge(3,4)
G.add_edge(4,5)
G.add_edge(6,5)
nx.draw_networkx_edges(G,pos,ax=ax, node_size=3000, arrowsize=30)

trans=ax.transData.transform
trans2=fig.transFigure.inverted().transform

piesize=0.4 # this is the image size
p2=piesize/2.0
for n in G:
    xx,yy=trans(pos[n]) # figure coordinates
    xa,ya=trans2((xx,yy)) # axes coordinates
    a = plt.axes([xa-p2,ya-p2, piesize, piesize])
    a.set_aspect('equal')
    a.imshow(G.nodes[n]['image'])
    a.axis('off')
ax.axis('off')
plt.show()

sample graph

  • Related