Python 在matplotlib中动态更新条形图

Python 在matplotlib中动态更新条形图,python,matplotlib,Python,Matplotlib,我有许多传感器连接到我的树莓圆周率;我正在使用TCP每秒向我的电脑发送两次他们的数据。我想使用matplotlib连续绘制这些值 我目前使用的方法似乎效率低下(我每次都清除子图并重新绘制),并且有一些不希望出现的缺点(每次都会重新调整比例;我希望它保持在0.0-5.0之间)。我知道有一种方法可以做到这一点,而不必清除和重新绘制,但似乎无法找到它。以下是我当前的代码: import socket import sys import time from matplotlib import pyplo

我有许多传感器连接到我的树莓圆周率;我正在使用TCP每秒向我的电脑发送两次他们的数据。我想使用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()
导入套接字
导入系统
导入时间
从matplotlib导入pyplot作为plt
#创建TCP/IP套接字
sock=socket.socket(socket.AF\u INET,socket.sock\u流)
#将套接字连接到服务器正在侦听的端口
服务器地址=('192.168.0.10',10000)
打印>>sys.stderr,“连接到%s端口%s”%server\u地址
sock.connect(服务器地址)
#条形图的初始设置
plt.ion()
图=plt.图()
ax=图add_子批次(1,1,1)
x=[1,2,3]
标签=['FSR'、'Tilt'、'IR']
ax.set_xticklabel(标签)
y=[5.0,5.0,5.0]
轴杆(x,y)
图autofmt_xdate()
plt.draw()
#抓取并连续绘制传感器值
尝试:
对于范围(300)内的i:
收到的金额=0
预期金额=len(“0.00,0.00,0.00”)
#从RasPi接收数据
当收到的金额小于预期金额时:
数据=sock.recv(14)
收到的金额+=len(数据)
打印>>sys.stderr,'收到“%s”数据
#打印接收到的数据
y=[data.split(',')中的基准的浮点(基准)]
ax.clear()
轴杆(x,y)
plt.draw()
睡眠时间(0.5)
#合上插座
最后:
打印>>sys.stderr,“关闭插座”
sock.close()

如果matplotlib不是强制选项,我建议在服务器上使用基于Web套接字的推送系统,在客户端使用基于Javascript的打印。我将首先列出几个优点:

  • 客户端(您的另一台电脑)必须只安装了现代web浏览器,并且可以运行任何操作系统,不需要安装Python、Matplotlib
  • 由于WebSocket将以广播方式工作,您可以让任意数量的客户端使用相同的提要,这在让用户演示您的系统时非常有用
  • 客户端代码也很有效,它保留了最后的“x”值,并且实时工作良好,因此不必重新绘制所有内容
  • 由于我正在做一些与我的树莓圆周率非常相似的事情,我可以分享我的细节相同。它的灵感来自博客文章。 可以找到推送数据的服务器端的代码。您可能会看到,在安装依赖项之后,它与您的代码非常相似,最终您会在我的代码中找到一个
    socket.send()
    。 对于客户端,是指向HTML文件的链接,是在使用绘图库的浏览器上执行的JS。我确信他们主页上的演示非常棒,足以引起注意

    你可以用。 绘制一次条形图并保存返回值,返回值是一组矩形:

    rects = plt.bar(range(N), x, align='center')
    
    然后,要更改条形图的高度,请调用
    rect.set\u height

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


    非常感谢,我将把它作为一个升级来实现。但是,我仍然想知道是否有一个简单的方法可以解决我的原始问题,即在不清除的情况下更新matplotlib图表?对我有效的方法是
    bar.set_height(x)
    ,其中x是一个数组。
    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()