Specific location for inputs

I want to create an axis set to create an insert at a specific location in the parent axis set. Therefore it is impractical to use the parameter loc=1,2,3

in inset_axes

as shown below:

inset_axes = inset_axes(parent_axes,
                    width="30%", # width = 30% of parent_bbox
                    height=1., # height : 1 inch
                    loc=3)

      

However, I would like something close to this. And the answers here and here seem to be answers to questions somewhat more complex than mine.

So the question is, is there a parameter that I can replace in the above code that will allow customizing the position of the insertion axes within the parent axes? I tried to use bbox_to_anchor

but don't understand its specification or behavior from the documentation . Specifically, I've tried:

 inset_axes = inset_axes(parent_axes,
                        width="30%", # width = 30% of parent_bbox
                        height=1., # height : 1 inch
                        bbox_to_anchor=(0.4,0.1))

      

to try and anchor the left and bottom of the insert to 40% and 10% from the x and y axis respectively. Or I tried to put it in absolute coordinates:

inset_axes = inset_axes(parent_axes,
                            width="30%", # width = 30% of parent_bbox
                            height=1., # height : 1 inch
                            bbox_to_anchor=(-4,-100))

      

None of them worked correctly and gave me a warning that I could not interpret.

All in all, it seems to be loc

a pretty standard setting in many of the functions owned matplotlib

, so is there a general solution to this problem that can be used anywhere? It seems that bbox_to_anchor

, but again, I can't figure out how to use it correctly.

+7


source to share


2 answers


The approach you have taken is, in principle, correct. However, as with placing a legend with using bbox_to_anchor

, location is defined as the interaction between bbox_to_anchor

and loc

. Most of the explanations in the above answer also apply here.

The default loc

for is ("top right"). This means that if you specify , it will be the coordinates of the top right corner, not the bottom left. Therefore, you need to specify that the lower left corner of the insert is in position . inset_axes

loc=1

bbox_to_anchor=(0.4,0.1)


loc=3

(0.4,0.1)

However, specifying the bounding tuple as a 2-tuple makes sense if you don't specify the width and height in relative units ( "30%"

). Or, in other words, to use relative units, you need to use 4- bbox_to_anchor

notation for bbox_to_anchor

.

In the case of specifying bbox_to_anchor

in units of axes, you must reuse the argument bbox_transform

, as explained here , and set it to ax.transAxes

.

plt.figure(figsize=(6,3))
ax = plt.subplot(221)
ax.set_title("100%, (0.5,1-0.3,.3,.3)")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="100%", height="100%", loc='upper left',
                   bbox_to_anchor=(0.5,1-0.3,.3,.3), bbox_transform=ax.transAxes)


ax = plt.subplot(222)
ax.set_title("30%, (0.5,0,1,1)")
ax.plot(xdata, ydata)
axins = inset_axes(ax, width="30%", height="30%", loc='upper left',
                   bbox_to_anchor=(0.5,0,1,1), bbox_transform=ax.transAxes)

      

enter image description here

Find a complete example on matplotlib page: Demo version Inset Locator



Another option is to use InsetPosition

instead of inset_axes

and give the existing axes a new position. InsetPosition

takes the x and y coordinates of the lower left corner of the axes in normalized axis coordinates, and the width and height as input.

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition

fig, ax= plt.subplots()

iax = plt.axes([0, 0, 1, 1])
ip = InsetPosition(ax, [0.4, 0.1, 0.3, 0.7]) #posx, posy, width, height
iax.set_axes_locator(ip)

iax.plot([1,2,4])
plt.show()

      

Finally, it should be mentioned that from matplotlib 3.0 on you can use matplotlib.axes.Axes.inset_axes

import matplotlib.pyplot as plt

plt.figure(figsize=(6,3))
ax = plt.subplot(221)
ax.set_title("ax.inset_axes, (0.5,1-0.3,.3,.3)")
ax.plot([0,4], [0,10])
axins = ax.inset_axes((0.5,1-0.3,.3,.3))

plt.show()

      

The result is about the same, except that it mpl_toolkits.axes_grid1.inset_locator.inset_axes

allows mpl_toolkits.axes_grid1.inset_locator.inset_axes

around the axes (and applies it by default), while Axes.inset_axes

it has no such padding.

enter image description here

+5


source


Using the answer from ImportanceOfBeingErnest and a few suggested links from unreleased documentation matplotlib

like the locator demo and inset_axes

docs
, it still took me a while to figure out how all the parameters behave. So I will repeat my understanding here for clarity. I ended up using:

bbox_ll_x = 0.2
bbox_ll_y = 0
bbox_w = 1
bbox_h = 1
eps = 0.01
inset_axes = inset_axes(parent_axes, 
               height="30%", #height of inset axes as frac of bounding box
               width="70%",  #width of inset axes as frac of bounding box
               bbox_to_anchor=(bbox_ll_x,bbox_ll_y,bbox_w-bbox_ll_x,bbox_h), 
               loc='upper left',
               bbox_transform=parent_axes.transAxes)

parent_axes.add_patch(plt.Rectangle((bbox_ll_x, bbox_ll_y+eps),
               bbox_w-eps-bbox_ll_x, 
               bbox_h-eps, 
               ls="--", 
               ec="c", 
               fc="None",
               transform=parent_axes.transAxes))

      

bbox_ll_x

is the x location of the bottom left corner of the bounding rectangle in parent axis coordinates (i.e. the input value bbox_transform

)

bbox_ll_y

- this is the y-position of the bottom-left corner of the bounding box in parent axis coordinates

bbox_w

- the width of the bounding box in the coordinates of the parent axis



bbox_h

- the height of the bounding box in the coordinates of the parent axis

eps

- a small number to display rectangles from below the axes when drawing a rectangular bounding rectangle.

I used a call add_patch

to place the blue dotted line that represents the inner edge of the hand-drawn frame.

The hardest part for me was understanding that the inputs height

and width

(when specified as percentages) refer to the size of the bounding box. Therefore (as mentioned in the links and below) you must specify a 4-tuple for the parameter bbox_to_anchor

if you specify the size of the insertion axes in percent. If you give the size of the insertion axes in percentage and don't supply bbox_w

or bbox_h

how matplotlib

to get the absolute size of the insertion?

Another thing is that the parameter loc

specifies where to bind the insertion axes in the bounding box. As far as I can tell, the only function of this parameter.

+2


source







All Articles