【问题标题】:Increase the speed of redrawing contour plot in matplotlib提高matplotlib中重绘等高线图的速度
【发布时间】:2017-07-12 04:48:25
【问题描述】:

我有一个 python 程序,可以将文件中的数据绘制为该文本文件中每一行的等高线图。目前,我的界面中有 3 个单独的等高线图。不管我是从文件中读取数据还是在执行脚本之前将其加载到内存中,我只能从等高线图中获得约 6fps 的数据。

我也尝试只使用一个等高线和其他正常图,但速度仅提高到 7fps。我不相信画几条线在计算上会如此繁重。有没有办法让它大大加快速度?理想情况下,获得至少 30fps 会很好。

我绘制轮廓的方式是,对于我的每一行数据,我都会删除前一行:

for coll in my_contour[0].collections:
    coll.remove()

并添加一个新的

my_contour[0] = ax[0].contour(x, y, my_func, [0])

在代码的开头,我有 plt.ion() 在添加时更新图。

任何帮助将不胜感激。

谢谢

【问题讨论】:

  • 更新绘图的速度取决于两件事:(a) 计算新数据所需的时间和 (b) 绘制坐标轴所需的时间。一般来说,很难说在你的情况下哪一个需要更多时间。不幸的是,contour 需要在每次迭代中重新计算数据,因此预期收益不大。使用 blitting 可能会减少绘制时间,但我怀疑这会将您的速度从 7 fps 提高到 30 fps。
  • 好吧,添加更多轮廓并不会大幅降低 fps。现在我尝试了 6 个轮廓,我得到了 5.5-6.5 fps,当我得到 7-7.5fps 时,matplotlib 中发生了一些事情,当它更新需要永远进行动画处理的绘图时。此外,如果我大幅降低等高线图的网格密度,它只会将帧速率提高几分之一 fps。
  • 这听起来像blitting 确实可以提供优势。
  • @ImportanceOfBeingErnest 与链接建议不同,我不能在等高线图上使用ax[0].draw_artist(my_contour[0])。它给了我一个错误。如果我按照那里的说明做所有其他事情,除了 ax[0].draw_artist(my_contour[0]) 我使用 fig.canvas.draw() 我会增加 2fps。我应该如何使用等高线图正确处理 blitting?

标签: python matplotlib plot contour


【解决方案1】:

这是一个关于如何在动画中使用contour 绘图的示例。它使用matplotlib.animation.FuncAnimation,这使得打开和关闭blitting 变得很容易。 使用 blit=True 它在我的机器上以 ~64 fps 的速度运行,而不会出现 ~55 fps。请注意,interval 当然必须允许快速动画;将其设置为interval=10(毫秒)将允许最高 100 fps,但绘制时间将其限制为比这更慢的速度。

import matplotlib.pyplot as plt
import matplotlib.animation
import numpy as np
import time

x= np.linspace(0,3*np.pi)
X,Y = np.meshgrid(x,x)
f = lambda x,y, alpha, beta :(np.sin(X+alpha)+np.sin(Y*(1+np.sin(beta)*.4)+alpha))**2
alpha=np.linspace(0, 2*np.pi, num=34)
levels= 10
cmap=plt.cm.magma


fig, ax=plt.subplots()
props = dict(boxstyle='round', facecolor='wheat')
timelabel = ax.text(0.9,0.9, "", transform=ax.transAxes, ha="right", bbox=props)
t = np.ones(10)*time.time()
p = [ax.contour(X,Y,f(X,Y,0,0), levels, cmap=cmap ) ]

def update(i):
    for tp in p[0].collections:
        tp.remove()
    p[0] = ax.contour(X,Y,f(X,Y,alpha[i],alpha[i]), levels, cmap= cmap) 
    t[1:] = t[0:-1]
    t[0] = time.time()
    timelabel.set_text("{:.3f} fps".format(-1./np.diff(t).mean()))  
    return p[0].collections+[timelabel]

ani = matplotlib.animation.FuncAnimation(fig, update, frames=len(alpha), 
                                         interval=10, blit=True, repeat=True)
plt.show()

请注意,在上面的动画 gif 中显示的是较慢的帧速率,因为保存图像的过程需要更长的时间。

【讨论】:

  • 这太棒了,我所有的 6 个轮廓都以 50fps 运行!巨大的进步!谢谢!
  • 非常感谢您的帮助。令人沮丧的是这些动画是多么不直观——尝试在QuadContour 对象上使用set_array 失败,尝试创建所有艺术家然后使用ArtistAnimation 失败。唯一的答案是执行后面的过程 ArtistAnimation FuncAnimation 一起工作。 matplotlib 真的需要在这里工作。
  • @LukeDavis 我不清楚问题是什么。我认为 4 行评论实在是太短了,无法进行足够清晰的描述,因此您可能会就遇到的问题提出一个新问题。
猜你喜欢
  • 2022-08-19
  • 2012-05-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-09
相关资源
最近更新 更多