How do I set the aspect ratio for a plot that uses twinx?
Below, I provide three examples:
twinx to highlight how I set the aspect ratio twinx to illustrate how the previously defined aspect ratio is reset y-axis while using twinx (which does not work)I am using matplotlib 1.3.0
The following script illustrates how I set the aspect ratio of a simple plot:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,1.6,50) + 50.0
fig = plt.figure()
ax = fig.add_subplot(111)
XLIM = [50.0, 51.6]
YLIM = [0.0, 1.1, 0.0, 11.0]
ax.plot(x,np.sin(x-50.0),'b')
ax.set_xlim([XLIM[0], XLIM[1]])
ax.set_ylim([YLIM[0], YLIM[1]])
ax.set_xticks(np.arange(XLIM[0], XLIM[1], 0.2))
ax.set_yticks(np.arange(YLIM[0], YLIM[1]+0.1, 0.1)[:-1])
ax.grid(True,which='major',linestyle='solid')
ax.set_aspect((XLIM[1]-XLIM[0])/(YLIM[1]-YLIM[0]))
plt.show()
The figure this produces has a defined aspect ratio:

However, if I want to add an additional y-axis using the twinx() function, the aspect ratio is reset:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,1.6,50) + 50.0
fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()
XLIM = [50.0, 51.6]
YLIM = [0.0, 1.1, 0.0, 11.0]
ax.plot(x,np.sin(x-50.0),'b')
ax.set_xlim([XLIM[0], XLIM[1]])
ax.set_ylim([YLIM[0], YLIM[1]])
ax.set_xticks(np.arange(XLIM[0], XLIM[1], 0.2))
ax.set_yticks(np.arange(YLIM[0], YLIM[1]+0.1, 0.1)[:-1])
ax.grid(True,which='major',linestyle='solid')
ax.set_aspect((XLIM[1]-XLIM[0])/(YLIM[1]-YLIM[0]))
plt.show()
Resulting in this figure (in which the previously defined y-limits on the left-hand-side are reset):

Now, trying to specify the aspect ratio again does not yield the expected result:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,1.6,50) + 50.0
fig = plt.figure()
ax = fig.add_subplot(111)
ax2 = ax.twinx()
XLIM = [50.0, 51.6]
YLIM = [0.0, 1.1, 0.0, 11.0]
ax.plot(x,np.sin(x-50.0),'b')
ax2.plot(x,np.cos(x-50.0)*10.,'r')
ax.set_xlim([XLIM[0], XLIM[1]])
ax.set_ylim([YLIM[0], YLIM[1]])
ax2.set_ylim([YLIM[2], YLIM[3]])
ax.set_xticks(np.arange(XLIM[0], XLIM[1], 0.2))
ax.set_yticks(np.arange(YLIM[0], YLIM[1]+0.1, 0.1)[:-1])
ax2.set_yticks(np.arange(YLIM[2], YLIM[3]+1.0, 1.0))
ax.grid(True,which='major',linestyle='solid')
ax.set_aspect((XLIM[1]-XLIM[0])/(YLIM[1]-YLIM[0]))
ax2.set_aspect((XLIM[1]-XLIM[0])/(YLIM[3]-YLIM[2]))
plt.show()
This produces:

What am I missing in order to generate a plot like the first one, but with two y-axis of different scales? How do I define the aspect ratio when using twinx?
Have a look at the adjustable parameter of the axes. This controls whether the data limits or the bounding rectangle's shape are changed when the aspect/limits are changed.
Normally, the options are "box" and "datalim", but there's a special case for shared axes. In your case, you want adjustable='box-forced'.
As a quick example (I took the liberty of simplifying things slightly, feel free to use the separate set_foo methods if they're clearer to you. If you take that route, the method is ax.set_adjustable.):
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,1.6,50) + 50.0
fig, ax = plt.subplots()
ax2 = ax.twinx()
XLIM = [50.0, 51.6]
YLIM = [0.0, 1.1, 0.0, 11.0]
ax.plot(x,np.sin(x-50.0),'b')
ax2.plot(x,np.cos(x-50.0)*10.,'r')
ax.set(adjustable='box-forced',
xlim=XLIM, ylim=YLIM[:2],
xticks=np.arange(XLIM[0], XLIM[1], 0.2),
yticks=np.arange(YLIM[0], YLIM[1]+0.1, 0.1)[:-1],
aspect=(XLIM[1]-XLIM[0])/(YLIM[1]-YLIM[0]))
ax2.set(adjustable='box-forced',
ylim=YLIM[2:],
yticks=np.arange(YLIM[2], YLIM[3]+1.0, 1.0),
aspect=(XLIM[1]-XLIM[0])/(YLIM[3]-YLIM[2]))
ax.grid(True, which='major',linestyle='solid')
plt.show()

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With