pythonmatplotlibnetworkximshowmatplotlibpyplot

Syncing matplotlib imshow coordinates


I'm trying to create an image using networkx, save that image to use later, and then overlay a plot over top of it later. However, when I try to load the image in and make new points, the scale seems off. I've tried everything I can find to make them sync, and I'm not sure what else to try at this point. Here's a simple example:

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
G = nx.dodecahedral_graph()
pos = nx.spring_layout(G)
plt.box(False)
nx.draw_networkx_edges(G, pos=pos)
fig.canvas.draw()

data = np.array(plt.gcf().canvas.get_renderer().buffer_rgba(), dtype=np.uint8)
extent = list(plt.xlim() + plt.ylim())

enter image description here

So now I have a graph and have saved that image to data, and have saved the range of that graph to extent. I then want to replot that graph from data and overlay the nodes of the graph, in the positions stored in pos.

plt.imshow(data, extent=extent)
plt.box(False)
nx.draw_networkx_nodes(G, pos=pos, node_color='green')

enter image description here

For some reason, the scale of the original image is shrunk, so the nodes end up being at a larger scale and not matching the edges. Is it something in the way I'm saving the image?


Solution

  • It seems that matplotlib adds padding to the sides of the image when saving the data from the plot. You can remove this padding by adding fig.tight_layout(pad=0) to the code like so:

    import networkx as nx
    import matplotlib.pyplot as plt
    import numpy as np
    
    fig = plt.figure()
    G = nx.dodecahedral_graph()
    pos = nx.spring_layout(G)
    plt.box(False)
    nx.draw_networkx_edges(G, pos=pos)
    fig.tight_layout(pad=0)
    fig.canvas.draw()
    
    data = np.array(plt.gcf().canvas.get_renderer().buffer_rgba(), dtype=np.uint8)
    extent = list(plt.xlim() + plt.ylim())