我注意到,绘制长度不断增加的不断更新的数据(我发现)的每个解决方案都有一个巨大的挫折-如果没有立即出现数据,则matplotlib窗口会冻结(例如没有响应)。以这个为例:
from matplotlib import pyplot as plt
from matplotlib import animation
from random import randint
from time import sleep
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
line, = ax.plot([])
x = []
y = []
def animate(i):
x.append(i)
y.append(randint(0,10))
for i in range(100000000):
# Do calculations to attain next data point
pass
line.set_data(x, y)
return line,
anim = animation.FuncAnimation(fig, animate,
frames=200, interval=20, blit=True)
plt.show()
此代码可以很好地运行,而无需在动画函数中进行循环的数据获取,但是在该窗口中冻结了图形窗口。还要注意这一点:
plt.ion()
x = []
for i in range(1000):
x.append(randint(0,10))
for i in range(100000000):
# Do calculations to attain next data point
pass
plt.plot(x)
plt.pause(0.001)
也冻结。 (为此,感谢上帝,因为使用该方法无法关闭边界线,因为图表不断在所有内容面前弹出。我不建议您删除睡眠)
这也是:
plt.ion()
x = []
for i in range(1000):
x.append(randint(0,10))
for i in range(100000000):
# Do calculations to attain next data point
pass
plt.plot(x)
plt.draw()
plt.pause(0.001)
plt.clf()
也是这样:(从https://stackoverflow.com/a/4098938/9546874复制)
import matplotlib.pyplot as plt
import numpy as np
from time import sleep
x = np.linspace(0, 6*np.pi, 100)
y = np.sin(x)
# You probably won't need this if you're embedding things in a tkinter plot...
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(111)
line1, = ax.plot(x, y, 'r-') # Returns a tuple of line objects, thus the comma
for phase in np.linspace(0, 10*np.pi, 500):
line1.set_ydata(np.sin(x + phase))
for i in range(100000000):
# Do calculations to attain next data point
pass
fig.canvas.draw()
fig.canvas.flush_events()
这是一个很大的问题,因为天真地认为所有数据都将以一致的间隔出现。我只想要一个图表,该图表在数据到来时会更新,并且不会在停机期间崩溃。请记住,数据之间的间隔可能会更改,可能是2秒或5分钟。
编辑:
经过进一步测试,可以使用FuncAnimation
,但是它非常笨拙,并且仍然有些破损。如果将interval
增加到animate
的预期时间以上,则可以使用,但是每次平移或缩放图形时,所有数据都会消失,直到下一次更新。因此,一旦有了视图,就无法触摸。
编辑:
为了清晰起见,将睡眠更改为for循环
答案 0 :(得分:1)
更新的答案: 问题在于数据获取或生成以及matplotlib窗口在同一线程上运行,因此前者阻止了后者。为了克服这个问题,将数据采集移到一个单独的过程中,如this example所示。除了进程和管道,您还可以使用线程和队列。
答案 1 :(得分:0)
请参见此示例,了解睡眠情况,效果很好:
= ^ .. ^ =
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
fig, ax = plt.subplots()
x = np.arange(0, 2*np.pi, 0.01)
line, = ax.plot(x)
def animate(i):
y_data = 0
for j in range(10):
y_data = np.random.uniform(-1, j, 1)
line.set_ydata(y_data)
plt.pause(1)
return line,
ani = animation.FuncAnimation(
fig, animate, interval=2, blit=True, save_count=50)
plt.ylim(-2, 11)
plt.show()