matplotlib 动画:绘图更新问题
我正在测试用随机数据制作的matplotlib动画图表,遇到了一些问题:
- 坐标轴的范围xlim和ylim几乎是随机更新的,而且当我在程序窗口和其他窗口之间切换时,这种情况更明显。
- 注释只会在坐标轴范围更新的那一帧显示,之后的帧里就消失了,直到图表再次更新。
- 有时候,图表的默认菜单会卡住或者消失。
这些问题在Linux和Windows上都有可能出现(表现得稍微不同)。
我应该使用线程处理,还是多进程?或者是其他什么原因呢?
# -*- coding: utf-8 -*-
import re
import time
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import animation
from mpl_toolkits.axes_grid.anchored_artists import AnchoredText
import random
def init():
line.set_data([], [])
return line,
def animate(i):
y = random.randint(750, 2000)
xdata.append(i)
ydata.append(y)
xmin, xmax = ax.get_xlim()
ymin, ymax = ax.get_ylim()
print xmin, xmax
print ymin, ymax
###changing the xmax dynamically
if i >= xmax:
ax.set_xlim(xmin, xmax+(xmax/2))
ax.figure.canvas.draw()
###changing the ymax dynamically
if y >= ymax:
ax.set_ylim(ymin, y+(y/10))
ax.figure.canvas.draw()
#line.set_data(x, y)
line.set_data(xdata, ydata)
if y < 900:
annotation = ax.annotate('Min', xy=(i, y-5))
return line, annotation
#------------------------------------------
#initial max x axis
init_xlim = 5
init_ylim = 2000
fig = plt.figure()
ax = plt.axes(xlim=(0, init_xlim), ylim=(0, init_ylim))
ax.grid()
line, = ax.plot([], [], lw=2)
xdata, ydata = [], []
annotation = ax.annotate('Min', xy=(-1,-1))
annotation.set_animated(True)
anim = animation.FuncAnimation(fig, animate, init_func=init,frames=2000, interval=1000, blit=True)
plt.show()
1 个回答
3
简而言之,关闭“blitting”功能,一切就会“正常运作”,但可能会比较慢。
你遇到的问题是因为底层代码在使用“blitting”时做了一些假设,认为只有坐标轴区域的内容会改变(也就是说,不包括刻度),而且你是在一个固定的背景上重新绘制。简单来说,“blitting”的工作原理是,每次你更新画面时,都会在图形界面上复制一张图像,然后把这张复制的图像放回到窗口里(保存的状态是init
函数结束时的状态,这个函数是由FuncAnimation
调用的)。你函数返回的绘图对象会在这个保存的画布上绘制。通过这种方式更新的区域就是你坐标轴“内部”的区域。刻度标签并不是每次都重新绘制,因为绘制文本是比较耗费资源的。
因此,刻度标签只有在系统触发完全重绘时才会更新(比如改变窗口时),注释也是如此,它们会出现是因为重绘时会绘制所有的绘图对象。但在下一帧时它们又会消失,因为它们不在保存的“基础”画布上,也不在你回调函数返回的绘制对象列表中。
如果你真的必须使用“blitting”并且每次都添加新的绘图对象,你就需要做更多的工作,并且要清楚动画的基础设施是如何运作的。