2013-04-27 18 views
8

Ho un numero di sensori collegato al mio Raspberry Pi; Sto inviando i loro dati al mio PC due volte al secondo usando TCP. Mi piacerebbe graficare continuamente questi valori usando matplotlib.Aggiornamento dinamico di un grafico a barre in matplotlib

Il metodo Attualmente sto usando sembra inefficiente (sto aprendo la sottotrama e ridisegnando ogni volta) e ha alcuni inconvenienti indesiderati (la scala viene riadattato ogni volta, mi sarebbe piaciuto rimanere 0,0-5,0). So che c'è un modo per farlo senza dover cancellare e ridisegnare, ma non riesco a capirlo. Quello che segue è il mio codice corrente:

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() 

risposta

16

È possibile utilizzare animation.FuncAnimation. Tracciare il grafico a barre, una volta e salvare il valore di ritorno, che è una raccolta di Rect:

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

Poi, per cambiare l'altezza di una barra, chiamata 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() 
2

Se matplotlib non è un'opzione forzata, mi sento di raccomandare un sistema push basato sul Web Socket sul server e un tracciamento basato su JavaScript per il lato client. Voglio elencare alcuni vantaggi per prime:

  1. Il cliente (l'altra PC) deve avere solo un moderno browser web installato e può eseguire qualsiasi sistema operativo e non ha bisogno di avere Python, Matplotlib installato
  2. Dal WebSockets sarebbe funziona in modalità broadcast, è possibile che un numero qualsiasi di client utilizzi lo stesso feed, può essere molto utile lasciando agli utenti una demo del proprio sistema
  3. Anche il codice lato client è efficiente, mantiene gli ultimi valori "x" e funziona bene in tempo reale, quindi tutto non deve essere ridisegnato

Dato che sto facendo qualcosa di molto simile con il mio Raspberry Pi, posso condividere i miei dettagli dello stesso. È ispirato al post del blog this. Il codice per il lato server che trasmette i dati può essere trovato here. Probabilmente puoi vedere che dopo aver installato le dipendenze, è molto simile al tuo codice e alla fine troverai uno socket.send() anche nel mio codice. Per il lato client, this è il collegamento al file HTML e this è il JS che viene eseguito sul browser, che utilizza la libreria di stampa Flot. Sono sicuro che la demo sulla loro home page è abbastanza impressionante da essere notata!

+0

Mille grazie per questo, cercherò di implementarlo come aggiornamento. Tuttavia, vorrei ancora sapere se esiste una semplice soluzione al mio problema originale con l'aggiornamento del grafico matplotlib senza compensazione? – hfaran

Problemi correlati