【问题标题】:How to remove contour lines during the animation in matplotlib如何在matplotlib中的动画期间删除轮廓线
【发布时间】:2017-11-19 10:57:26
【问题描述】:

我将 Python 3.6.3 与 matplotlib 2.1.0 一起使用,我想要实现的是能够删除一些在动画之前使用 contour() 函数绘制的轮廓。 等高线图需要在动画开始时可见,并且只有在用户按下某个键后才能删除。困难在于我需要对动画使用 blitting。然而,blitting 会恢复原始画布,因此即使移除轮廓,它仍然在 blitted 背景中保持可见。

这是显示问题的代码:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from numpy import mgrid, sin, cos, pi

def keypress(event):
    if event.key == "delete":
        for c in cs.collections: c.remove() # this doesn't work
        cs.set_alpha(0.0) # this doesn't work either

phi = pi/2

def animate(i):
    global phi
    line.set_data([[0.0, sin(phi)], [0.0, cos(phi)]])
    phi += 0.01
    return line,

x,p = mgrid[-2:2:100*1j,-2:2:100*1j]
fig,ax = plt.subplots(1, 1, figsize=(19.2,10.8), dpi=100)
ax.set_xlim([-2,2])
ax.set_ylim([-2,2])
line, = ax.plot([], [], 'o-', lw=2, color='b')
cs = ax.contour(x, p, x**2 + p**2, levels=2, linewidths=0.8, colors='r')
fig.canvas.mpl_connect('key_press_event', keypress)
ani = animation.FuncAnimation(fig, animate, blit=True, interval=0, frames=2000)
plt.show()

如果无法删除轮廓,那么至少我应该能够使其不可见或透明,但我也找不到这样做的方法。请帮忙! :)

【问题讨论】:

  • 清洁循环后调用 plt.draw()
  • 我试过了,但不幸的是,它所做的只是应该消失的曲线“闪烁”,即它闪烁 --- 瞬间消失,然后再次出现,颜色完全相同因为它最初是绘制的。我假设你的意思是这样做:for c in p.cs.collections: c.remove() plt.draw()
  • 如果您的代码太大而不能成为问题的一部分。那么,代码对于问题来说太大了,因此不是问题的minimal reproducible example。如果您在从画布中删除艺术家时遇到问题,我相信您只需花费 20 行代码即可重现此内容,以便人们能够提供帮助。
  • 好的,我已经编辑了这个问题,包括一个只有 26 行代码的小测试用例。

标签: python python-3.x animation matplotlib


【解决方案1】:

在使用blit=True 制作动画期间,很难更改画布中的任何内容(blitting 的全部意义在于背景不会改变)。在不使用 blit 的情况下,删除线条或将其设置为不可见应该没有任何问题,blitting 将始终恢复原始画布背景,即使某些艺术家已从中删除。

因此,我们需要做的是在艺术家移除后中断动画,重新绘制画布,拍摄新的背景快照并使用新背景重新启动动画。虽然这本身会相当麻烦,但可能的解决方案是模拟画布的调整大小事件,这将准确触发所描述的过程。这是在以下代码中完成的。

(请注意,这与Qt 后端一起正常工作,而使用Tk 会出现一些问题,至少在matplotlib 2.1 版中。)

import matplotlib.pyplot as plt
import matplotlib.animation as animation
from numpy import mgrid, sin, cos, pi

phi = pi/2.

def keypress(event):
    if event.key == "delete":
        try:
            for c in cs.collections: 
                c.remove()
        except ValueError:
            pass
        ani._handle_resize()
        ani._end_redraw(None)


def animate(i):
    global phi
    line.set_data([[0.0, sin(phi)], [0.0, cos(phi)]])
    phi += 0.01
    return line,

x,p = mgrid[-2:2:100*1j,-2:2:100*1j]
fig,ax = plt.subplots(1, 1, figsize=(8,6), dpi=100)
ax.set_xlim([-2,2])
ax.set_ylim([-2,2])
line, = ax.plot([], [], 'o-', lw=2, color='b')
cs = ax.contour(x, p, x**2 + p**2, levels=2, linewidths=2, colors='r')

fig.canvas.mpl_connect('key_press_event', keypress)

ani = animation.FuncAnimation(fig, animate, 
                              blit=True, interval=1, frames=2000)
plt.show()

【讨论】:

  • 谢谢,但首先,使用 blit=True 对我的应用程序来说是绝对必要的,而且绝对必要的是不在 init() 函数中删除轮廓,而是在一些任意的用户选择的时刻(例如按 Del 键)。如果我想在 init() 中删除它,我一开始就不会绘制它 :) 现在,您说的是“在使用 blit=True 的动画期间很难更改画布中的任何内容”。事实上,如果有一种简单的方法,我早就找到了。问题仍然存在:有没有“不那么容易”的方法来解决这个问题?
  • 好的,我编辑了问题以明确这一点。我还用一个可能的解决方案编辑了答案(这有点小技巧,但应该可以工作)。
  • 谢谢。哦,这很有趣!我现在就试试这个,如果它有效,我会告诉你...
  • 不幸的是,这也不起作用。您的建议是:a)在按下 Del 时生成一个刷新画布(即一切都闪烁)和 b)蓝线的当前位置变为“永久”,即保持原位,而“真实”蓝线继续旋转.如果我再次按 Del,我将有 三个 蓝线(两个静态,一个旋转)等等。
  • 你能区分:你是在说上面的代码还是在说你的应用程序?上面的代码运行正常吗?
猜你喜欢
  • 2018-08-10
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
  • 2013-05-24
  • 2021-10-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多