You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
inset_locator.inset_axes produces axes without extent and at incorrect position. #8952
The mpl_toolkits.axes_grid1.inset_locator.inset_axes is not working as expected when using the bbox_to_anchor argument. Using inset_axes(ax, width="70%", height="30%",bbox_to_anchor=(0.4,0.1), loc=3) gives an inset axes without extention at an incorrect position. (This issue is raised in this stackoverflow post.)
c:\winpython\winpython-64bit-2.7.10.3\python-2.7.10.amd64\lib\site-packages\matplotlib\axis.py:1035: UserWarning: Unable to find pixel distance along axis for interval padding of ticks; assuming no interval padding needed.
when being run with python 2.7, matplotlib 2.0.2. In the lower left corner of the image you see what I suppose are the ticks of the zero-sized axes. Since the documentation clearly states that width and height can be strings (and they actually can be if bbox_to_anchor is ommited) and since the default bbox_transform is parent_axes.transAxes, the above is clearly expected to work.
Note that when explicitely supplying the bbox_transform we at least get the axes at the correct position,
Is this an error in the documentation or a bug in the matplotlib code?
The expected outcome of the above would be an inset axes with the lower left corner at (0.4,0.1) in axes coordinates and a width of 0.3 and a height of 0.7 (also in normalized axes units) as shown in the below image (which is produced by other means than inset_axes):
I've spent a bit of time trying to understand where this behaviour is coming from. I've noted the following:
When bbox_to_anchor is provided, the display coordinates are used instead of the axes coordinates. As noted, this can be remedied by providing the bbox_transform argument.
One must provide four arguments to bbox_to_anchor (left, bottom, width, height).
With width and height arguments set to 1, behaviour is pretty much as expected. The effect of setting to other values is difficult to understand.
The following snippet illustrates the current behaviour on matplotlib 2.1.0, which may be useful to anyone trying to work around or fix it.
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes
mpl.transforms.DEBUG = True
xdata, ydata = np.arange(8), np.arange(8)
plt.figure(figsize=(6,6))
# Using all default arguments, things seems OK.
ax = plt.subplot(421)
ax.set_title("Defaults")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="30%", height="30%", loc='upper left')
# The following fails with "ValueError: Transforming to a singular bounding box.",
# even though according to the docstring it is valid.
#ax = plt.subplot(422)
#ax.set_title("bbox=(0,0)")
#ax.plot(xdata, ydata)
#axins = inset_axes(ax, width="30%", height="30%", loc='upper left',
# bbox_to_anchor=(0, 0))
# According to the docstring, the default value for `bbox_transform` should
# be `ax.transAxes`, and yet the following uses display coordinates.
ax = plt.subplot(423)
ax.set_title("bbox=(0,0,1,1), default transform")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="30%", height="30%", loc='upper left',
bbox_to_anchor=(0, 0, 1, 1)) # Tiny axes in lower left of figure
#bbox_to_anchor=(100, 70, 100, 100)) # These coords put the
# inset within the plot
# Supplying `ax.transAxes` as argument recovers most of the expected behaviour
ax = plt.subplot(424)
ax.set_title("bbox=(0,0,1,1)")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="30%", height="30%", loc='upper left',
bbox_to_anchor=(0, 0, 1, 1),
bbox_transform=ax.transAxes)
# The effect of changing the bbox width and height is difficult to predict
ax = plt.subplot(425)
ax.set_title("bbox=(0, 0, 0.5, 1)")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="30%", height="30%", loc='upper left',
bbox_to_anchor=(0, 0, .5, 1),
bbox_transform=ax.transAxes)
ax = plt.subplot(426)
ax.set_title("bbox=(0, 0, 1, 0.5)")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="30%", height="30%", loc='upper left',
bbox_to_anchor=(0, 0, 1, .5),
bbox_transform=ax.transAxes)
# `loc` argument applies to *both* the parent and inset axes simultaneously
# i.e. with 'upper right', coordinates are those of the upper right point
# of the inset, relative to the upper right of the parent axes.
ax = plt.subplot(427)
ax.set_title("bbox=(0,0,1,1), upper right")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="30%", height="30%", loc='upper right',
bbox_to_anchor=(0, 0, 1, 1),
bbox_transform=ax.transAxes)
ax = plt.subplot(428)
ax.set_title("bbox=(0,0,1,1), lower right")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="30%", height="30%", loc='lower right',
bbox_to_anchor=(0, 0, 1, 1),
bbox_transform=ax.transAxes)
plt.subplots_adjust(hspace=0.8)
Wow, good catch @alcrene. 👍
I think this now all makes sense. Even width and height are consistent. E.g. the following are two ways to specify the same inset. Either you make the width/height some percentage or you make the box width and height fractional. (You just have to mind that the position is different due to the loc then).
The bbox_transform not being the axes transform has by now been "fixed" in #10756. But that fix apparently broke the usual behaviour of the inset_axes taking numbers as arguments for width and height.
Activity
tacaswell commentedon Jul 28, 2017
Likely both, the
axis_gridtools are both under documented and under tested.alcrene commentedon Apr 1, 2018
I've spent a bit of time trying to understand where this behaviour is coming from. I've noted the following:
bbox_to_anchoris provided, the display coordinates are used instead of the axes coordinates. As noted, this can be remedied by providing thebbox_transformargument.bbox_to_anchor(left,bottom,width,height).widthandheightarguments set to 1, behaviour is pretty much as expected. The effect of setting to other values is difficult to understand.The following snippet illustrates the current behaviour on matplotlib 2.1.0, which may be useful to anyone trying to work around or fix it.
ImportanceOfBeingErnest commentedon Apr 1, 2018
Wow, good catch @alcrene. 👍
I think this now all makes sense. Even width and height are consistent. E.g. the following are two ways to specify the same inset. Either you make the width/height some percentage or you make the box width and height fractional. (You just have to mind that the position is different due to the loc then).
The
bbox_transformnot being the axes transform has by now been "fixed" in #10756. But that fix apparently broke the usual behaviour of the inset_axes taking numbers as arguments for width and height.ImportanceOfBeingErnest commentedon Aug 11, 2018
Closing since this is now fixed by #11060.