Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
138 views
in Technique[技术] by (71.8m points)

python - Dynamically updating a bar plot in matplotlib

I have a number of sensors attached to my Raspberry Pi; I'm sending their data to my PC twice a second using TCP. I would like to continuously graph these values using matplotlib.

The method I'm currently using seems inefficient (I'm clearing the subplot and redrawing it every time) and has some undesirable drawbacks (the scale gets readjusted every time; I would like it stay from 0.0 - 5.0). I know there's a way of doing this without having to clear and redraw but can't seem to figure it out. The following is my current code:

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()
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You could use animation.FuncAnimation. Plot the bar plot once and save the return value, which is a collection of Rects:

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

Then, to change the height of a bar, call 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()

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...