使用matplotlib绘制动态数据

时间:2014-04-14 11:10:00

标签: python numpy matplotlib plot scipy

我编写应用程序会显示动态变化的数据(从套接字读取的数据)。

作为一个虚拟案例,我尝试绘制一个幅度乘以每秒1.1的正弦值:

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

x = np.arange(0, 10, 0.1);
y = np.sin(x)


for i in xrange(100):
    plt.plot(x, y)
    time.sleep(1)
    y=y*1.1

这显然不是这样做的,但它表明了我的意图。

如何正确完成?

修改 以下是@mskimm答案中建议的代码的回溯输出:

plt.show() #Exception in thread Thread-2:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
    self.run()
  File "/usr/lib/python2.7/threading.py", line 505, in run
    self.__target(*self.__args, **self.__kwargs)
  File "<ipython-input-5-ed773f8e3e84>", line 7, in update
    plt.draw()
  File "/usr/lib/pymodules/python2.7/matplotlib/pyplot.py", line 466, in draw
    get_current_fig_manager().canvas.draw()
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py", line 240, in draw
    tkagg.blit(self._tkphoto, self.renderer._renderer, colormode=2)
  File "/usr/lib/pymodules/python2.7/matplotlib/backends/tkagg.py", line 12, in blit
    tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode, id(bbox_array))
RuntimeError: main thread is not in main loop

编辑2:

事实证明,在qtconsole中运行相同的代码...(任何想法为什么?) 然而,每次打印重新缩放到情节,所以&#34;动画效果&#34;不见了。 我尝试使用plt.autoscale_view(False,False,False),但这根本没有引起任何情节。

3 个答案:

答案 0 :(得分:10)

有更好的方法可以使用matplotlib animation API执行此操作, 但这是一个快速而肮脏的方法:

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 10, 0.1)
y = np.sin(x)

plt.ion()
ax = plt.gca()
ax.set_autoscale_on(True)
line, = ax.plot(x, y)

for i in xrange(100):
    line.set_ydata(y)
    ax.relim()
    ax.autoscale_view(True,True,True)
    plt.draw()
    y=y*1.1
    plt.pause(0.1)

关键步骤是:

  1. 使用plt.ion()启用互动模式。
  2. 跟踪您要更新的行,并覆盖他们的数据,而不是再次拨打plot
  3. 通过调用plt.pause
  4. 让Python有时间更新绘图窗口

    我包含了自动缩放视口的代码,但这并不是绝对必要的。

答案 1 :(得分:2)

申请animated难吗?如何使用thread更新图形。 即使plt.show()阻止,thread也会更新数字。

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

def update(x, y):
    for i in xrange(100):
        # clear
        plt.clf()
        plt.plot(x, y)
        # draw figure
        plt.draw()
        time.sleep(1)
        y=y*1.1

x = np.arange(0, 10, 0.1);
y = np.sin(x)
plt.plot(x, y)

# use thread
t = threading.Thread(target=update, args=(x, y))
t.start()

plt.show() # blocking but thread will update figure.

答案 2 :(得分:0)

另一种解决方案是从头开始重新绘制图。当然,它比逐点更新要慢,但是如果您没有很多点,则开销可以忽略不计。

from IPython import display

def dynamic_plot(X,Y, figsize=[10,5], max_x=None, min_y=None, max_y=None):
    '''plots dependency between X and Y dynamically: after each call current graph is redrawn'''
    gcf().set_size_inches(figsize)
    cla()
    plot(X,Y)
    if max_x: 
        plt.gca().set_xlim(right=max_x)
    if min_y: 
        plt.gca().set_ylim(bottom=min_y)
    if max_y: 
        plt.gca().set_ylim(top=max_y)

    display.display(gcf())
    display.clear_output(wait=True)  

以及jupyter笔记本的演示用途:

import time

X=[]
Y=[]
for i in range(10):
    X.append(i)
    Y.append(i**.5)
    dynamic_plot(X,Y,[14,10], max_x=10, max_y=4)  
    time.sleep(0.3)