Define aspect ratio when using twinx

aspect-ratio, matplotlib, python

Solution

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()

Problem

How do I set the aspect ratio for a plot that uses `twinx`? Below, I provide three examples: - without `twinx` to highlight how I set the aspect ratio - with only `twinx` to illustrate how the previously defined aspect ratio is reset - my attempt to define the aspect ratio for both `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`?

Original source

Related problems