动态更新matplotlib中的条形图

时间:2013-04-27 07:20:23

标签: python matplotlib

我的Raspberry Pi附带了许多传感器;我使用TCP每秒两次将数据发送到我的PC。我想使用matplotlib连续绘制这些值。

我目前正在使用的方法似乎效率低下(我正在清理子图并每次都重新绘制它)并且有一些不良缺点(每次都会重新调整比例;我希望它保持在0.0 - 5.0之间)。我知道有一种方法可以做到这一点,而不必清除和重绘,但似乎无法搞清楚。以下是我目前的代码:

import socket
import sys
import time
from matplotlib import pyplot as plt

# Create a TCP/IP socket
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# Connect the socket to the port where the server is listening
server_address = ('192.168.0.10', 10000)
print >>sys.stderr, 'connecting to %s port %s' % server_address
sock.connect(server_address)

# Initial setup for the bar plot
plt.ion()
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
x = [1,2,3]
labels = ['FSR', 'Tilt', 'IR']
ax.set_xticklabels(labels)
y = [5.0,5.0,5.0]
ax.bar(x,y)
fig.autofmt_xdate()
plt.draw()

#Grab and continuously plot sensor values
try:
    for i in range(300):
        amount_received = 0
        amount_expected = len("0.00,0.00,0.00")

        # Receive data from RasPi
        while amount_received < amount_expected:
            data = sock.recv(14)
            amount_received += len(data)
            print >>sys.stderr, 'received "%s"' % data

        # Plot received data
        y = [float(datum) for datum in data.split(',')]
        ax.clear()
        ax.bar(x,y)
        plt.draw()
        time.sleep(0.5)

#Close the socket       
finally:
    print >>sys.stderr, 'closing socket'
    sock.close()

2 个答案:

答案 0 :(得分:18)

您可以使用animation.FuncAnimation。 绘制条形图一次并保存返回值,这是Rects的集合:

rects = plt.bar(range(N), x, align='center')

然后,要更改小节的高度,请拨打rect.set_height

    for rect, h in zip(rects, x):
        rect.set_height(h)

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

def animate(frameno):
    x = mu + sigma * np.random.randn(N)
    n, _ = np.histogram(x, bins, normed=True)
    for rect, h in zip(patches, n):
        rect.set_height(h)
    return patches

N, mu, sigma = 10000, 100, 15
fig, ax = plt.subplots()
x = mu + sigma * np.random.randn(N)
n, bins, patches = plt.hist(x, 50, normed=1, facecolor='green', alpha=0.75)

frames = 100
ani = animation.FuncAnimation(fig, animate, blit=True, interval=0,
                              frames=frames,
                              repeat=False)
plt.show()

答案 1 :(得分:2)

如果matplotlib不是强制选项,我建议在服务器上使用基于Web Socket的推送系统,并为客户端推荐基于Javascript的绘图。我将首先列出一些优点:

  1. 客户端(您的其他PC)必须只安装现代Web浏览器并且可以运行任何操作系统,并且不需要安装Python,安装Matplotlib
  2. 由于WebSockets可以广播方式工作,因此您可以让任意数量的客户使用相同的Feed,在让用户使用您的系统演示时非常有用
  3. 客户端代码也很有效,它保留了最后的'x'值并且实时运行良好,所以不必重新绘制所有内容
  4. 由于我正在做与我的Raspberry Pi非常相似的事情,我可以分享我的相同细节。它的灵感来自this博文。 可以找到推送数据的服务器端代码here。您可能会看到在安装依赖项后,它与您的代码非常相似,最终您甚至会在我的代码中找到socket.send()。 对于客户端,this是HTML文件的链接,this是在浏览器上执行的JS,它使用Flot绘图库。我确信他们主页上的演示非常棒,值得注意!