【问题标题】:Cartopy coastlines hidden by inset_axes use of Axes.pie使用 Axes.pie 的 inset_axes 隐藏的 Cartopy 海岸线
【发布时间】:2017-10-27 07:25:56
【问题描述】:

我正在制作一张世界地图,其中包含单个模型网格框中的饼图。我使用 cartopy 制作地图和海岸线。我使用 inset_axes 生成的饼图。不幸的是,饼图隐藏了海岸线,我想清楚地看到它们。

最小工作示例:

import cartopy.crs as ccrs
import numpy as np
import cartopy.feature as feature
import matplotlib.pyplot as plt

def plot_pie_inset(dataframe_pie,ilat_pie,ilon_pie,axis_main,width_local,alpha_local):
    ax_sub= inset_axes(axis_main, width=width_local, height=width_local, loc=3, bbox_to_anchor=(ilat_pie, ilon_pie),bbox_transform=axis_main.figure.transFigure, borderpad=0.0)
    wedges,texts= ax_sub.pie(dataframe_pie,colors=colors_dual)
    for w in wedges:
        w.set_linewidth(0.02)
        w.set_alpha(alpha_local)
        w.set_zorder(1)
    plt.axis('equal')

colors_dual=['RosyBrown','LightBlue']
lat_list= np.arange(0.2,0.7,0.05)

fig= plt.figure()
ax_main= plt.subplot(1,1,1,projection=ccrs.PlateCarree())
ax_main.coastlines(zorder=3)
for ilat in np.arange(len(lat_list)):
    plot_pie_inset([75,25],lat_list[ilat],0.72,ax_main,0.2,0.9)

plt.show()

我可以通过降低 alpha 值使饼图部分透明来查看海岸线。然而,这使得颜色有些柔和。我的目标是将海岸线作为最顶层。

我尝试使用“zorder”将海岸线强制到顶层。但是,“zorder”不能传递给 inset_axes,也不能传递给 ax.pie,所以我将饼图中的色块设为半透明。这失败了,因为 ax_main.coastlines 没有自己的“zorder”。海岸线 zorder 似乎与 ax_main 相关。增加 ax_main 的 zorder 没有任何好处。

欢迎提出任何建议。

【问题讨论】:

    标签: python matplotlib z-order cartopy


    【解决方案1】:

    问题是每个轴要么位于另一个轴的顶部或下方。所以改变轴内艺术家的 zorder 在这里没有帮助。原则上,可以设置轴本身的 zorder,将插入轴放在主轴后面。

    ax_sub.set_zorder(axis_main.get_zorder()-1)
    

    Cartopy 的 GeoAxes 使用自己的背景补丁。然后需要将其设置为不可见。

    ax_main.background_patch.set_visible(False)
    

    完整示例:

    import cartopy.crs as ccrs
    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.axes_grid1.inset_locator import inset_axes
    
    def plot_pie_inset(dataframe_pie,ilat_pie,ilon_pie,axis_main,width_local,alpha_local):
        ax_sub= inset_axes(axis_main, width=width_local, height=width_local, loc=3, 
                           bbox_to_anchor=(ilat_pie, ilon_pie),
                           bbox_transform=axis_main.transAxes, 
                           borderpad=0.0)
        wedges,texts= ax_sub.pie(dataframe_pie,colors=colors_dual)
        for w in wedges:
            w.set_linewidth(0.02)
            w.set_alpha(alpha_local)
            w.set_zorder(1)
        plt.axis('equal')
        # Put insets behind main axes
        ax_sub.set_zorder(axis_main.get_zorder()-1)
    
    colors_dual=['RosyBrown','LightBlue']
    lat_list= np.arange(0.2,0.7,0.05)
    
    fig= plt.figure()
    ax_main= plt.subplot(1,1,1,projection=ccrs.PlateCarree())
    ax_main.coastlines()
    
    # set background patch invisible, such that axes becomes transparent
    # since the GeoAxes from cartopy uses a different patch as background
    # the following does not work
    # ax_main.patch.set_visible(False)
    # so we need to set the GeoAxes' background_patch invisible
    ax_main.background_patch.set_visible(False)
    
    for ilat in np.arange(len(lat_list)):
        plot_pie_inset([75,25],lat_list[ilat],0.72,ax_main,0.2,0.9)
    
    plt.show()
    

    【讨论】:

    • 非常感谢您快速而有用的回复。
    • 我不清楚将背景补丁设置为不可见如何使海岸线可见。使用的 set_visible(False) 是否适用于 GeoAxes 的背景和海岸线,还是仅适用于背景?我想可见和部分透明之间存在一些细微差别,这意味着不可见可以看到海岸线的线条。那是对的吗?再次感谢!
    • 背景是坐标轴中所有物体后面的白色矩形(因此也在海岸线后面)。如果我们将 insets 放在主轴后面,这个白色矩形就在 insets 前面并隐藏了它们。但是使背景不可见(即消除白色矩形)可以让主轴后面的所有东西都被看到。
    • 再次感谢您花时间解释这些细节 ImportanceOfBeingErnest。
    【解决方案2】:

    一位同事建议的替代解决方案忽略了使用 inset_axes,但实现了类似的结果。主要区别在于该方案中的坐标系是在原始的经纬度坐标中,而不是图形坐标中。

    def plot_pie_direct(dataframe_pie,ilat_pie,ilon_pie,axis_main,width_local,alpha_local):
        wedges,texts= ax_main.pie(dataframe_pie,colors=colors_aer_atm,radius=width_local)
        for w in wedges:
            w.set_linewidth(0.02)  ## Reduce linewidth to near-zero
            w.set_center((ilat_pie,ilon_pie))
            w.set_zorder(0)
    
    fig= plt.figure()
    ax_main= plt.axes(projection=ccrs.PlateCarree())
    ax_main.coastlines(zorder=3)
    ax_main.set_global()
    lim_x= ax_main.get_xlim()
    lim_y= ax_main.get_ylim()
    for ilat in np.arange(len(lat_list_trim)):
        plot_pie_direct(frac_aer_atm_reshape_trim[:,ilat,ilon],x_val_pies[ilon],y_val_pies[ilat],ax_main,lat_list_diff_trim,0.9)
    
    ax_main.coastlines(zorder=3)
    ax_main.set_xlim(lim_x)
    ax_main.set_ylim(lim_y)
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多