【问题标题】:Trouble using Insetposition for Inset Axes with Cartopy使用 Cartopy 对插入轴使用插入位置时遇到问题
【发布时间】:2021-12-07 19:02:16
【问题描述】:

我想使用 Cartopy 在地图上创建插图。我想将 x & y 插入位置位置指定为父轴的函数,以便子轴始终位于父轴内。例如,0,0 对齐左下角的插入轴,1,1 对齐右上角的插入轴,但在这两种情况下,插入图都在父级内部。我使用以下方法实现了这一点:

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

问题是如果我将新范围应用于插图。根据新设置的范围的纵横比,我的 x 或 y 插入位置转换为父轴内的位置 - 0-y 导致插入偏离底部,1-y 导致它在顶部偏移.发生这种情况时,偏移是对称的,并且仅发生在一个位置轴上,另一个则按需要运行。我尝试过使用 get_position,但在使用 Cartopy 时这似乎并不直观,因为返回的 bbox 不反映绘图范围的纵横比。例如,在应用 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

我可以手动将它们调整到我想要的位置,但校正与 bbox 高度/宽度或我想检查的任何其他值的差异不匹配。有什么建议吗?

如果我将左侧和底部位置更改为:

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

无论设置的范围如何,它始终可以始终如一地工作,但它会使插图与角落重叠。 works consistently but not desired results

附加说明 - 如果您使用普通(非 GeoAxes)绘图并使用 set_aspect 更改插图的方面,则可以找到相同的行为。我还没有弄清楚前后方面更改之间的 bbox 大小关系(父项和插图)以及它如何影响特定的插图位置。

【问题讨论】:

    标签: python matplotlib cartopy


    【解决方案1】:

    @Hagbeard,我找到了类似的问题the similar question,并进一步完善了@gepcel的代码,以便更好地满足您的需求。

    这里是代码。

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

    还有最后的情节。

    【讨论】:

    • 好的,谢谢@LiYupeng!我一直专注于使用 InsetPosition,以至于我没有尝试仅设置轴位置。我修改了您的解决方案以供我使用,以允许使用值 0-1 更好地控制位置:inset_x = .99 inset_y = .99 left = p1.x0 + inset_x*(p1.x1 - p2.width - p1.x0) bottom = p1.y0 + inset_y*(p1.y1 - p2.height - p1.y0)
    猜你喜欢
    • 2018-08-05
    • 2012-03-20
    • 2011-09-28
    • 1970-01-01
    • 2017-01-29
    • 1970-01-01
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多