简体   繁体   中英

Cartopy coastlines hidden by inset_axes use of Axes.pie

I am producing a map of the world with pie charts in individual model grid boxes. I make the map and coastlines using cartopy. The pie charts I produce using inset_axes. Unfortunately the pie charts hide the coastlines and I'd like to see them clearly.

Minimum working example:

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

I can see the coastlines by making the pie charts partially transparent by reducing the alpha value. However, this makes the colors somewhat muted. My aim is to have the coastlines as the topmost layer.

I have attempted to use 'zorder' to force the coastlines to the top layer. However, 'zorder' cannot be passed to inset_axes, nor to ax.pie so I've made the patches of color in pie charts translucent. This fails because the ax_main.coastlines does not have its own 'zorder'. The coastline zorder seems to be tied to that of ax_main. There is no benefit in increasing the zorder of ax_main.

Any suggestions greatly welcomed.

The problem is that each axes either lies on top or below another axes. So changing the zorder of artists within axes, does not help here. In principle, one could set the zorder of the axes themselves, putting the inset axes behind the main axes.

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

Cartopy's GeoAxes uses its own background patch. This would then need to be set to invisble.

ax_main.background_patch.set_visible(False)

Complete example:

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

在此处输入图片说明

An alternative solution suggest by a colleague neglects to use the inset_axes but achieves a similar result. The main difference is that the coordinate system in this solution is in the original latitude/longitude coordinates rather than figure coordinates.

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

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