缓存或重用cartopy功能

问题描述 投票:0回答:1

我正在使用 Cartopy 在多个 Matplotlib 子图中显示 GSHHSFeature 海岸线,并在其上叠加不同的数据。

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

xss = np.linspace(-21, 36, 36)
extent = [-21, 36, 33, 64]  # west,east,south,north

fig, ax = plt.subplots(nrows=3, ncols=2, figsize=(13, 15), 
                       subplot_kw={'projection': ccrs.PlateCarree()})

for i in range(rows):
    for j in range(cols):
        ax[i][j].set_extent(extent)
        ax[i][j].add_feature(cfeature.GSHHSFeature(scale="intermediate", edgecolor="black", facecolor="#bca89f"))

        # Plot individual data sets on subplots
        ax[i][j].plot(xss, np.random.uniform(low=33, high=64, size=(len(xss),)), color='cyan', zorder=20, transform=ccrs.PlateCarree(), linewidth=2)
        
        # Write map title
        ax[i][j].set_title("Row:"+str(i)+", Col:"+str(j))

plt.tight_layout()
plt.show()

绘制海岸线是一项耗时的操作,特别是在使用“完整”数据集比例时。由于每个子图中的底图都是相同的,因此我一直在寻找仅创建一次并在循环中重用它的方法。

有没有办法可以缓存特征甚至整个子图轴并定义像

ax[i][j].plot_my_basemap(map_ax)
ax[i][j] = copy_axis_from(map_ax)
这样的函数?

# Create a plot axes of choice
map_ax = plt.axes(projection=ccrs.PlateCarree())
map_ax.set_extent(extentd)
# Request and process the basemap features
map_ax.add_feature(cfeature.GSHHSFeature(scale="intermediate", edgecolor="black", facecolor="#bca89f"))

fig, ax = plt.subplots(nrows=3, ncols=2, figsize=(13, 15), 
                       subplot_kw={'projection': ccrs.PlateCarree()})

for i in range(rows):
    for j in range(cols):
        ax[i][j].plot_my_basemap(map_ax)

        # Plot individual data sets on subplots
        ax[i][j].plot(xss, np.random.uniform(low=33, high=64, size=(len(xss),)), color='cyan', zorder=20, transform=ccrs.PlateCarree(), linewidth=2)
        
        # Write map title
        ax[i][j].set_title("Row:"+str(i)+", Col:"+str(j))

plt.tight_layout()
plt.show()

这个问题的答案(我从中改编了我的示例)显示了如何使用 Google 平铺图像执行此操作,但这种方法在我的情况下不起作用,因为海岸线不是图像对象,而是 cartopy.mpl.feature_artist .特色艺术家。

我还尝试直接重用map_ax,更改其属性并将其分配给子图,但这在matplotlib中不起作用:

for i in range(rows):
    for j in range(cols):
        props = ax[i][j].properties()
        props = dict((k, props[k]) for k in ["position", "subplotspec"])
        ax[i][j] = map_ax.update(props)

        # Plot individual data sets on subplots
        ax[i][j].plot(xss, np.random.uniform(low=33, high=64, size=(len(xss),)), color='cyan', zorder=20, transform=ccrs.PlateCarree(), linewidth=2)
        
        # Write map title
        ax[i][j].set_title("Row:"+str(i)+", Col:"+str(j))

我希望能够定义和重用诸如 Basemap 对象之类的东西https://github.com/matplotlib/basemap/issues/354(但我不想使用 Basemap,因为它将被 Cartopy 取代)并且它已经与 Matplotlib 3.8 存在兼容性问题)

caching cartopy
1个回答
0
投票

如果您每次都使用

plt.show()
,则此方法不起作用,但如果您保存每个图像,则只需更新由
Line2D
创建的
ax.plot
对象上的 y 数据即可。

我使用标准

coastlines
调用只是为了加快此示例的速度。我还删除了
tight_layout
,因为它正在移动每次迭代的子图。在图形创建中使用
layout='compressed'
使我的布局更加一致。

请注意,大多数(全部?)matplotlib 绘图方法返回的艺术家都有某种

set_data
方法,因此如果您的真实示例使用
plot
以外的其他内容,这应该是通用的。

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

xss = np.linspace(-21, 36, 36)
extent = [-21, 36, 33, 64]  # west,east,south,north

nrows = 3
ncols = 2


fig, ax = plt.subplots(nrows=nrows, ncols=ncols, figsize=(13, 15), 
                       subplot_kw={'projection': ccrs.PlateCarree()},
                       layout='compressed')


for n in range(3):
    for i in range(nrows):
        for j in range(ncols):
            if n == 0:
                # Set up maps and plot first data. 
                ax[i][j].set_extent(extent)
                ax[i][j].coastlines()
                
                # Plot individual data sets on subplots
                ax[i][j].plot(xss, np.random.uniform(low=33, high=64, size=(len(xss),)), color='cyan', zorder=20, transform=ccrs.PlateCarree(), linewidth=2)
            
            else:
                # Replace line y-data.
                ax[i][j].get_lines()[0].set_ydata(np.random.uniform(low=33, high=64, size=(len(xss),)))
            
            # Write map title
            ax[i][j].set_title("Row:"+str(i)+", Col:"+str(j))

    plt.savefig(f'myplot{n}.png')
© www.soinside.com 2019 - 2024. All rights reserved.