Cómo trazar datos en tiempo real usando Matplotlib

  1. Función FuncAnimation()
  2. canvas.draw() junto con canvas_flush_events()
  3. Diagrama de dispersión en tiempo real

Para trazar datos en tiempo real usando Matplotlib, o hacer una animación en Matplotlib, actualizamos constantemente las variables a trazar iterando en un bucle y luego trazando los valores actualizados. Para ver la trama actualizada en tiempo real a través de la animación, utilizamos varios métodos como la función FuncAnimation(), canvas.draw() junto con canvas_flush_events().

Función FuncAnimation()

Podemos actualizar la gráfica en tiempo real actualizando las variables x e y y luego mostrando las actualizaciones a través de la animación usando matplotlib.animation.FuncAnimation.

Sintaxis:

matplotlib.animation.FuncAnimation(fig, 
                                   func, 
                                   frames=None,
                                   init_func=None, 
                                   fargs=None,
                                   save_count=None, 
                                   *, 
                                   cache_frame_data=True,
                                   **kwargs)

Código:

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

x = []
y = []

figure, ax = plt.subplots(figsize=(4,3))
line, = ax.plot(x, y)
plt.axis([0, 4*np.pi, -1, 1])

def func_animate(i):
    x = np.linspace(0, 4*np.pi, 1000)
    y = np.sin(2 * (x - 0.1 * i))
    
    line.set_data(x, y)
    
    return line,

ani = FuncAnimation(figure,
                    func_animate,
                    frames=10,
                    interval=50)

ani.save(r'animation.gif', fps=10)

plt.show()

trazar en tiempo real usando la función FuncAnimation.png

ani = FuncAnimation(figure,
                    func_animate,
                    frames=10,
                    interval=50)

figure es el objeto de figura cuya trama se actualizará.

func_animate es la función que se llamará en cada cuadro. Su primer argumento proviene del siguiente valor frames.

frames = 10 es igual a range(10). Los valores del 0 al 9 se pasan al func_animate en cada frame. También podríamos asignar un interalbe a frames, como una lista [0, 1, 3, 7, 12].

intervalo es el retraso entre cuadros en la unidad de ms.

ani.save('animation.gif', fps=10)

Podríamos guardar la animación en un gif o mp4 con parámetros como fps y dpi.

canvas.draw() junto con canvas_flush_events()

Podemos actualizar el gráfico en tiempo real actualizando las variables x e y con set_xdata() y set_ydata() y luego mostrando las actualizaciones a través de la animación usando canvas.draw(), que es un método basado en JavaScript.

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

x = np.linspace(0, 10, 100)
y = np.cos(x)

plt.ion()

figure, ax = plt.subplots(figsize=(8,6))
line1, = ax.plot(x, y)

plt.title("Dynamic Plot of sinx",fontsize=25)

plt.xlabel("X",fontsize=18)
plt.ylabel("sinX",fontsize=18)

for p in range(100):
    updated_y = np.cos(x-0.05*p)
    
    line1.set_xdata(x)
    line1.set_ydata(updated_y)
    
    figure.canvas.draw()
    
    figure.canvas.flush_events()
    time.sleep(0.1)

Trama en tiempo real en Matplotlib usando canvas_draw

Aquí los valores de x e y se actualizan repetidamente y la gráfica también se actualiza en tiempo real.

plt.ion() activa el modo interactivo. La trama no se actualizará si no se llama.

canvas.flush_events() es un método basado en JavaScript para borrar cifras en cada iteración para que las sucesivas figuras no se superpongan.

Diagrama de dispersión en tiempo real

Sin embargo, para hacer una dispersión en tiempo real, solo podemos actualizar los valores de x e y y agregar puntos de dispersión en cada iteración. En este caso, no necesitamos borrar todas las figuras, ya que un diagrama de dispersión generalmente representa un punto distinto en el plano y los puntos tienen muy pocas posibilidades de superponerse.

import numpy as np
import matplotlib.pyplot as plt
x=0
for i in range(100):
    x=x+0.04
    y = np.sin(x)
    plt.scatter(x, y)
    plt.title("Real Time plot")
    plt.xlabel("x")
    plt.ylabel("sinx")
    plt.pause(0.05)

plt.show()

dispersión de la trama en tiempo real