Question: I am trying to use an existing graph as a background for new data that I want to plot on top of the graph. I have been able to do so when using a graph with all information contained within the axes and using the extent parameter of plt.imshow because then I just have to scale the image. I would like to scale and shift the background graph. Replotting the background is not an option in the real use case. Here is what I tried so far :  Generation of a background graph (reproducible example)  import matplotlib.pyplot as plt fig, ax = plt.subplots() ax.plot([0, 5, 10], [8, 5, 12]) ax.set_xlim(0, 20) ax.set_ylim(0, 15) ax.set_title('Background graph') fig.show() fig.savefig('bg_graph.png')    Use plt.imshow() to add the background graph and then superimpose my data.  bg_img = plt.imread('bg_graph.png') fig, ax = plt.subplots() ax.imshow(bg_img, extent=[0,50,0,50]) ax.scatter([4.9, 5.2], [7, 4.9]) fig.show() fig.savefig('result.png')   I have made a mockup of the expected result using Excel :  Is there a method to stretch a new graph onto existing axis (from an image) in order to plot new pieces of data ? I assume that the coordinates of the axis in the image are known or can be guessed through trial an error. One way to rephrase this is to say that I would like to stretch the new plot to the image and not the other way around.

Answer: We can follow this answer to a related question and adapt it to your needs (see code comments for explanations): import matplotlib.pyplot as plt bg_img = plt.imread('stackoverflow/bg.png') # TODO: Adjust as necessary bg_width, bg_xlim, bg_ylim = 6, (0, 20), (0, 15) # Create a figure with the same aspect ratio and scale as the image. # This provides the axes in which we will plot our new data figsize = (bg_width, bg_width * bg_img.shape[0] / bg_img.shape[1]) fig, axes = plt.subplots(nrows=1, ncols=1, figsize=figsize) axes.patch.set_alpha(0.0) # Make new figure's area transparent axes.set_xlim(*bg_xlim) # Adjust limits to background's limits axes.set_ylim(*bg_ylim) axes.scatter([4.9, 5.2], [7, 4.9], color='red') # Plot our new data # Optionally, turn off axes, as we already have them from # the background and they will not match perfectly: plt.axis('off') background_ax = plt.axes([0, 0, 1, 1]) # Create dummy subplot for background background_ax.set_zorder(-1) # Set background subplot behind the other background_ax.imshow(bg_img, aspect='auto') # Show background image plt.axis('off') # Turn off axes that surround the background  For me, using the background image that you shared and loading it as bg.png results in the following plot:  What if adjusting the whitespace is necessary? Luckily, the layout of the whitespace in your background image seems to match Matplotlib's defaults. If that was not the case, however, we could use subplots_adjust() on the foreground plot, together with a bit of trial and error, to make the axes of the foreground plot and background image align as perfectly as possible. In this case, I would initially leave the axes of the foreground plot turned on (and thus comment out the first plt.axis('off') in the code above) to make adjustments easier. To demonstrate this, I created a version of your background image with additional green padding (called bg_padded.png in the code below), which looks as follows:  I then adjusted the code from above as follows: import matplotlib.pyplot as plt bg_img = plt.imread('stackoverflow/bg_padded.png') # TODO: Adjust as necessary bg_width, bg_xlim, bg_ylim = 7.5, (0, 20), (0, 15) # Create a figure with the same aspect ratio and scale as the image. # This provides the axes in which we will plot our new data figsize = (bg_width, bg_width * bg_img.shape[0] / bg_img.shape[1]) fig, axes = plt.subplots(nrows=1, ncols=1, figsize=figsize) # Adjust padding of foreground plot to padding of background image plt.subplots_adjust(left=.2, right=.82, top=.805, bottom=0.19) axes.patch.set_alpha(0.0) # Make new figure's area transparent axes.set_xlim(*bg_xlim) # Adjust limits to background's limits axes.set_ylim(*bg_ylim) axes.scatter([4.9, 5.2], [7, 4.9], color='red') # Plot our new data # Optionally, turn off axes, as we already have them from # the background and they will not match perfectly: # plt.axis('off') background_ax = plt.axes([0, 0, 1, 1]) # Create dummy subplot for background background_ax.set_zorder(-1) # Set background subplot behind the other background_ax.imshow(bg_img, aspect='auto') # Show background image plt.axis('off') # Turn off axes that surround the background  Changes are:  I loaded bg_padded.png rather than bg.png (obviously); I changed bg_width to 7.5 to account for the increased size of the background image and, with it, for the relative decrease in size (e.g. of the fonts) in the foreground plot; I added the line plt.subplots_adjust(left=.2, right=.82, top=.805, bottom=0.19) to adjust for the padding.  This time, I also left the first plt.axis('off') commented out, as mentioned above, to see and to show how well the axes of the background image and the foreground plot match. The result looks as follows: