web-dev-qa-db-fra.com

python matplotlib mise à jour du nuage de points d'une fonction

J'essaie de mettre à jour automatiquement un nuage de points. La source de mes valeurs X et Y est externe et les données sont automatiquement transférées dans mon code dans un intervalle de temps non prévu (tours).

Je n'ai réussi à tracer toutes les données qu'à la fin de l'ensemble du processus, alors que j'essaie constamment d'ajouter et de tracer des données dans ma toile.

Ce que j'obtiens (à la fin de toute la course) est le suivant: enter image description here

Attendu que ce que je recherche c'est: enter image description here

Une version simplifiée de mon code:

import matplotlib.pyplot as plt

def read_data():
    #This function gets the values of xAxis and yAxis
    xAxis = [some values]  #these valuers change in each run
    yAxis = [other values] #these valuers change in each run

    plt.scatter(xAxis,yAxis, label  = 'myPlot', color = 'k', s=50)     
    plt.xlabel('x')
    plt.ylabel('y')
    plt.show()
10
Yair

Il existe plusieurs façons d'animer un tracé matplotlib. Dans ce qui suit, regardons deux exemples minimaux utilisant un nuage de points.

(a) utiliser le mode interactif plt.ion()

Pour qu'une animation ait lieu, nous avons besoin d'une boucle d'événement. Une façon d'obtenir la boucle d'événement est d'utiliser plt.ion() ("interactive on"). Il faut alors d'abord dessiner la figure et ensuite mettre à jour le tracé en boucle. À l'intérieur de la boucle, nous devons dessiner le canevas et introduire une petite pause pour que la fenêtre traite d'autres événements (comme les interactions avec la souris, etc.). Sans cette pause, la fenêtre se figerait. Enfin, nous appelons plt.waitforbuttonpress() pour laisser la fenêtre ouverte même après la fin de l'animation.

import matplotlib.pyplot as plt
import numpy as np

plt.ion()
fig, ax = plt.subplots()
x, y = [],[]
sc = ax.scatter(x,y)
plt.xlim(0,10)
plt.ylim(0,10)

plt.draw()
for i in range(1000):
    x.append(np.random.Rand(1)*10)
    y.append(np.random.Rand(1)*10)
    sc.set_offsets(np.c_[x,y])
    fig.canvas.draw_idle()
    plt.pause(0.1)

plt.waitforbuttonpress()

(b) en utilisant FuncAnimation

Une grande partie de ce qui précède peut être automatisée en utilisant matplotlib.animation.FuncAnimation . Le FuncAnimation prendra en charge la boucle et le redessin et appellera en permanence une fonction (dans ce cas animate()) après un intervalle de temps donné. L'animation ne démarre qu'une fois que plt.show() est appelée, s'exécutant ainsi automatiquement dans la boucle d'événements de la fenêtre de tracé.

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

fig, ax = plt.subplots()
x, y = [],[]
sc = ax.scatter(x,y)
plt.xlim(0,10)
plt.ylim(0,10)

def animate(i):
    x.append(np.random.Rand(1)*10)
    y.append(np.random.Rand(1)*10)
    sc.set_offsets(np.c_[x,y])

ani = matplotlib.animation.FuncAnimation(fig, animate, 
                frames=2, interval=100, repeat=True) 
plt.show()
20

D'après ce que je comprends, vous souhaitez mettre à jour de manière interactive votre intrigue. Si c'est le cas, vous pouvez utiliser le tracé au lieu du nuage de points et mettre à jour les données de votre tracé comme ceci.

import numpy
import matplotlib.pyplot as plt 
fig = plt.figure()
axe = fig.add_subplot(111)
X,Y = [],[]
sp, = axe.plot([],[],label='toto',ms=10,color='k',marker='o',ls='')
fig.show()
for iter in range(5):
    X.append(numpy.random.Rand())
    Y.append(numpy.random.Rand())
    sp.set_data(X,Y)
    axe.set_xlim(min(X),max(X))
    axe.set_ylim(min(Y),max(Y))
    raw_input('...')
    fig.canvas.draw()

Si c'est le comportement que vous recherchez, il vous suffit de créer une fonction en ajoutant les données de sp, et d'obtenir dans cette fonction les nouveaux points que vous souhaitez tracer (soit avec la gestion des E/S ou quel que soit le processus de communication que vous êtes en utilisant). J'espère que ça aide.

3
aTben0