Cartopy:循环遍历多个范围而不重新生成地图 image/Deleting Gridliner 对象

Cartopy: Loop through multiple extents without regenerating map image/Deleting Gridliner Object

我正在尝试在 cartopy 的地图上绘制源点和接收器点,我在其中根据源和接收器的位置放大地图。对于源和接收器的每个组合,我都有一个新的地图,具有新的范围。我想找到一种方法,我可以下载一次地图图像,然后每次只更改范围,这样我就不必每次都加载地图图像(我必须制作数千个)。所有的事件都发生在一个国家,所以我希望只下载整个国家的地图,然后改变每个循环的范围。

我实际上已经部分解决了这个问题,但我 运行 遇到了网格问题。最初,我先将范围设置为全国,加载图像,然后保存。然后我可以重置每个源接收器对的范围,绘制两个点,然后保存图像。之后,我只需要擦掉这两个点,然后我就可以重新设置范围了。

但是,一旦我在网格中添加了经纬度标签,我 运行 就遇到了问题。我无法在每次迭代后擦除网格和标签,所以它们最终只是相互叠加,标签开始在整个图形上移动。我摆脱网格的唯一方法是清除轴,但这会擦除地图图像。

我的问题:有没有办法只擦除网格线对象(不是隐藏标签和网格而是实际删除)?如果没有,是否有不同的方式在开始时加载图像,这样我每次都可以清除轴,但不必完全重新加载新的平铺器?

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.io.img_tiles import Stamen

whole_extent = [18,42,8,36]
tiler = Stamen('terrain-background')

fig = plt.figure(figsize=(13.75,10))
ax1 = plt.axes(projection=ccrs.PlateCarree())
ax1.set_extent(whole_extent, crs=ccrs.PlateCarree())
ax1.add_image(tiler,6)
#Need to save initial figure to lock in initial picture, otherwise it locks in the extent from the first loop and any map that goes outside the extent of the first loop is white space
plt.savefig('plots/001_WholeFigure.png')


eventlist=[['A',22,15,30,30],['B',30,15,30,18],['C',38,24,21,15],['D',25,12,28,16],['E',38,32,21,11]]

for i in eventlist:
    eventname = i[0]
    slon = i[1] #source lon
    slat = i[2] #source lat
    lon = i[3] #receiver lon
    lat = i[4] #receiver lat

    print(f'{eventname} in progress')
    
    # Sets the zoomed in extent based on source/receiver locations
    if lon > slon:
        lonmin = slon - 2
        lonmax = lon + 2
    else:
        lonmin = lon - 2
        lonmax = slon + 2

    if lat > slat:
        latmin = slat -2
        latmax = lat + 2
    else:
        latmin = lat - 2
        latmax = slat + 2

    zoomextent = [lonmin,lonmax,latmin,latmax]


    # MAP
    ax1.set_extent(zoomextent, crs=ccrs.PlateCarree())
    receiverloc = ax1.plot(lon,lat,'r*',label='Receiver')
    sourceloc = ax1.plot(slon,slat,'k^',label='Source')
    text = ax1.text(slon+0.1,slat+0.1,eventname)
    legend = ax1.legend(loc="upper right")
    
    gl = ax1.gridlines(crs=ccrs.PlateCarree(),draw_labels=True,
        linewidth=2,color='gray',alpha=0.5,linestyle='--')
    gl.bottom_labels = gl.right_labels = False

    plt.savefig(f'plots/{eventname}.png')

    # Delete the two markers and the text so they don't show up on next loop
    receiverloc.pop(0).remove()
    sourceloc.pop(0).remove()
    text.remove()

这里上传了两张剧情图片,大家可以在'E'中看到问题。我不知道如何擦除网格,清除轴会删除地图图像。 A E

嗯,这不是一个很好的解决方案,因为它依赖于一些私有属性,但这可以在循环结束时添加:

# Remove all artists created by the gridliner
for artist in (gl.xline_artists + gl.yline_artists +
               gl.bottom_label_artists + gl.top_label_artists +
               gl.left_label_artists + gl.right_label_artists):
    artist.remove()

# Remove the created gridliner from the list
ax1._gridliners.remove(gl)

# Try to re-connect to the draw event, which since it's already
# connected will return the existing connection id
cid = gl.axes.figure.canvas.mpl_connect('draw_event', gl._draw_event)

# Disconnect using that cid
gl.axes.figure.canvas.mpl_disconnect(cid)

这有效地撤消了 ax.gridlines() 和创建 Gridliner 实例所做的事情。