首页 > 解决方案 > Cartopy:循环多个范围而不重新生成地图图像/删除网格线对象

问题描述

我正在尝试在 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”中看到问题。我不知道如何擦除网格,清除轴会删除地图图像。 _

标签: pythoncartopy

解决方案


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

# 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实例的操作。


推荐阅读