Search code examples
pythonmatplotlibplotbackground-imagescale

How to plot a graph with logscale over a background image?


I want to plot a curve over a background image with the x and y axis in logscale. However, when I try to do so, the image is stretched by the logscale. I obtain this figure

This is the code I wrote.

import numpy as np  
import matplotlib.pyplot as plt

x = np.random.uniform(low=0, high=10**6, size=(100,)) 
y = np.random.uniform(low=10**(-14), high=10**(-10), size=(100,)) 

x.sort() 
y.sort()

xm = len(x) 
ym = len(y)

img = plt.imread("quiverplot.png")

fig, ax2 = plt.subplots() 
plt.plot(x, y) 
ax2.set_xscale('log')
ax2.set_yscale('log')


ax1 = ax2.twinx()

img = ax1.imshow(img, zorder=0, extent=[x[0], x[xm-1], y[0], y[ym-1]], aspect='auto')

fig.tight_layout() 
plt.show() 

Thanks for any advices you can give me.


Solution

  • Don't use twinx(), but create a new axes with matplotlib.pyplot.axes(). You can do like this controlling the frame(background), x/y axis, and z-order.

    fig, ax2 = plt.subplots()
    ax2.plot(x, y) 
    ax2.set_xscale('log')
    ax2.set_yscale('log')
    ax2.set_frame_on(False)
    ax2.zorder = 1
    
    ax1 = plt.axes(ax2.get_position(True))
    ax1.set_frame_on(False)
    ax1.set_axis_off()
    ax1.imshow(img, extent=[x[0], x[xm-1], y[0], y[ym-1]], aspect='auto')
    ...
    

    It will be simpler if you change the order of plotting like this.

    fig, ax2 = plt.subplots() 
    ax2.imshow(img, extent=[x[0], x[xm-1], y[0], y[ym-1]], aspect='auto')
    ax2.set_axis_off()
    
    ax1 = plt.axes(ax2.get_position(True))
    ax1.set_frame_on(False)
    ax1.set_xscale('log')
    ax1.set_yscale('log')
    ax1.plot(x, y)
    ...