简体   繁体   中英

Trouble using Insetposition for Inset Axes with Cartopy

I want to create an inset map on a map using Cartopy. I'd like to specify the x & y inset location positions as a function of the parent axes so that the child axes are always inside the parent. For example, 0,0 aligns the inset axes at the bottom left and 1,1 aligns the inset axes at the top right, but in both cases the inset plot is inside the parent. I've achieved this using the following:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import InsetPosition
import cartopy.crs as ccrs

ax = plt.axes(projection=ccrs.PlateCarree(), label='1')
ax.coastlines()

iax = plt.axes([0, 0, 1, 1], projection=ccrs.PlateCarree(), label='2')
iax.coastlines()

size = .5
inset_x = 1
inset_y = 1

left = inset_x - inset_x*size
bottom = inset_y - inset_y*size

ip = InsetPosition(ax, [left, bottom, size, size]) #posx, posy, width, height
iax.set_axes_locator(ip)

working fine when extents not set

The problem is if I apply new extents to the inset map. Depending on the aspect ratio of the newly set extents, my x or y inset position translates to positions well inside the parent axes - a 0-y results in the inset being off the bottom and a 1-y results it being offset at the top. When this happens, the offset is symmetric and only occurs in one of the position axes, the other one behaves as desired. I've tried using get_position, but that doesn't seem intuitive when using Cartopy because the bbox returned does not reflect the aspect ratio of the plot extents. For example, adding this before applying the InsetPosition:

# extent=[-20,60,40,65] # this breaks y positioning
extent=[-20,60,0,65] # this breaks x positioning
iax.set_extent(extent, crs=ccrs.PlateCarree())

not working as expected

I can manually adjust them to where I want but the correction doesn't match differences in bbox height/width or any other value I've thought to check. Any suggestions?

If I change the left and bottom locations to:

left = inset_x - size/2
bottom = inset_y - size/2

That always works consistently, regardless of the extents set, but it puts the inset map overlapping the corner. works consistently but not desired results

Additional note - the same behavior can be found if you use ordinary (non-GeoAxes) plots and change the aspect of the inset using set_aspect. I still haven't figured out the bbox size relationships (parent and inset) between the pre- and post-aspect change and how it impacts the specific inset placement.

@Hagbeard,I found the similar question the similar question , and I have further refined @gepcel's code so that it can better meet your needs.

Here is the code.

import matplotlib.pyplot as plt
#from mpl_toolkits.axes_grid1.inset_locator import InsetPosition
import cartopy.crs as ccrs

ax = plt.axes(projection=ccrs.PlateCarree(), label='1')
ax.coastlines()

size = .2 # Figure Standardized coordinates (0~1)
#GeoAxes has a width/height ratio according to self's projection
#Therefore, Here only set  a same width and height

iax = plt.axes([0, 0, size, size], projection=ccrs.PlateCarree(), label='2')
iax.coastlines()

extent=[-20,60,40,65]
#extent=[-20,60,0,65]
iax.set_extent(extent, crs=ccrs.PlateCarree())

def set_subplot2corner(ax,ax_sub,corner="bottomright"):
    ax.get_figure().canvas.draw()
    p1 = ax.get_position()
    p2 = ax_sub.get_position()
    if corner == "topright":
        ax_sub.set_position([p1.x1-p2.width, p1.y1-p2.height, p2.width, p2.height])
    if corner == "bottomright":
        ax_sub.set_position([p1.x1-p2.width, p1.y0, p2.width, p2.height])
    if corner == "bottomleft":
        ax_sub.set_position([p1.x0, p1.y0, p2.width, p2.height])
    if corner == "topleft":
        ax_sub.set_position([p1.x0, p1.y1-p2.height, p2.width, p2.height])

set_subplot2corner(ax,iax,corner="topright")

# Do not support a interactive zoom in and out
# so plz save the plot as a static figure
plt.savefig("corner_subfig.png",bbox_inches="tight")
#plt.show()

And the final plot.

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM