【问题标题】:Plotting timeseries contour data with basemap and matplotlib使用底图和 matplotlib 绘制时间序列等高线数据
【发布时间】:2018-02-27 22:55:00
【问题描述】:

我是底图和 python 的新手,但我正在尝试为日常 cron 作业的天气模型构建绘图仪。我们每天绘制大约 1000 张图像。

我写了一些脚本来实现我想要的。但它花了很长时间,因为它为每个时间步重新绘制底图。绘制底图用了30秒,绘制contourf()只用了4秒。

我有一些想法可以通过预先绘制底图并在每次迭代中更新 contourf() 来加快进程。但我不明白 matplotlib 对象是如何工作的。

我已经研究过有关此问题的相同问题,但没有发现任何问题。但我从 user3982706 的 here 中发现了类似的东西。

from matplotlib import animation
from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.basemap import Basemap


fig, ax = plt.subplots()

# set up map projection
m = Basemap(projection='nsper',lon_0=-0,lat_0=90)
m.drawcoastlines()
m.drawparallels(np.arange(0.,180.,30.))
m.drawmeridians(np.arange(0.,360.,60.))

# some 2D geo arrays to plot (time,lat,lon)
data = np.random.random_sample((20,90,360))
lat = np.arange(len(data[0,:,0]))
lon = np.arange(len(data[0,0,:]))
lons,lats = np.meshgrid(lon,lat)

# ims is a list of lists, each row is a list of artists to draw in the
# current frame; here we are animating three artists, the contour and 2 
# annotatons (title), in each frame
ims = []
for i in range(len(data[:,0,0])):
    im = m.contourf(lons,lats,data[i,:,:],latlon=True)
    add_arts = im.collections
    text = 'title={0!r}'.format(i)
    te = ax.text(90, 90, text)
    an = ax.annotate(text, xy=(0.45, 1.05), xycoords='axes fraction')
    ims.append(add_arts + [te,an])

ani = animation.ArtistAnimation(fig, ims)
## If you have ffmpeg you can save the animation by uncommenting 
## the following 2 lines
# FFwriter = animation.FFMpegWriter()
# ani.save('basic_animation.mp4', writer = FFwriter)
plt.show()

该脚本将轮廓数据保存为艺术家列表。我不需要动画。所以我需要编辑这个脚本以将图形保存在循环中。所以这个脚本产生了figure1.png、figure2.png、figure3.png等等。

有什么建议吗?

【问题讨论】:

  • 如果您是新手并且尚未依赖 Basemap 中的现有工作,那么我强烈建议您使用 cartopy 而不是 basemap。它可以为您省去很多麻烦。

标签: python matplotlib matplotlib-basemap


【解决方案1】:

(a) 使用动画保存图片

由于代码中已经有了动画,可以通过ani.save命令直接保存动画的每张图片。

ani.save("figure.png", writer="imagemagick")

这将创建 20 个名为 figure-0.pngfigure-19.png 的数字。它需要安装 imagemagick 并在您的环境中可用。

(b) 保存单个数字

如果上述操作因任何原因失败,您可以通过plt.savefig() 保存单个数字。在每个循环步骤结束时,您将从轴上移除艺术家并将其删除。

from matplotlib import pyplot as plt
import numpy as np
from mpl_toolkits.basemap import Basemap

fig, ax = plt.subplots()

m = Basemap(projection='nsper',lon_0=-0,lat_0=90)
m.drawcoastlines()
m.drawparallels(np.arange(0.,180.,30.))
m.drawmeridians(np.arange(0.,360.,60.))

data = np.random.random_sample((20,90,360))
lat = np.arange(len(data[0,:,0]))
lon = np.arange(len(data[0,0,:]))
lons,lats = np.meshgrid(lon,lat)

for i in range(len(data[:,0,0])):
    im = m.contourf(lons,lats,data[i,:,:],latlon=True)
    text = 'title={0!r}'.format(i)
    te = ax.text(90, 90, text)
    an = ax.annotate(text, xy=(0.45, 1.05), xycoords='axes fraction')
    # save the figure
    plt.savefig("figure_{}.png".format(i))
    # remove stuff from axes
    for c in im.collections:
        c.remove()
    te.remove()
    an.remove()
    del im; del te; del an

plt.show()

【讨论】:

  • 感谢您的帮助。但是当我尝试这个时,代码运行没有错误。并且只生成了一个文件很大的“figure.png”。而且打不开。我正在使用来自imagemagick.org/script/binary-releases.php 的 windows、matplotlib 2.0.2 和 imagemagick 安装程序
  • 我不知道出了什么问题,它对我来说很好用。所以我添加了一个不需要动画的替代方案。
  • 感谢您的选择!有用!傻我。我不知道contourf对象可以通过从集合中删除来删除。我认为它不能被删除,因为它没有删除方法。先生,我可以再问你一个问题吗?我可以保存底图状态以便以后使用它而不重绘它吗?谢谢!!!
  • 图形总是要画出来的。所以你不能跳过重绘的步骤,但是你可以在不重新生成的时候节省一些时间。 Matplotlib 数字can be pickled。如果涉及底图,我不确定它是否有效,但肯定值得一试。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-22
  • 1970-01-01
  • 2021-05-19
  • 1970-01-01
  • 2011-03-02
  • 2012-03-25
  • 1970-01-01
相关资源
最近更新 更多