Szukaj…


Wprowadzenie

Dzięki Python Matplotlib możesz poprawnie tworzyć animowane wykresy.

Podstawowa animacja z FuncAnimation

Pakiet matplotlib.animation oferuje pewne klasy do tworzenia animacji. FuncAnimation tworzy animacje poprzez wielokrotne wywoływanie funkcji. Tutaj używamy funkcji animate() która zmienia współrzędne punktu na wykresie funkcji sinusoidalnej.

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

TWOPI = 2*np.pi

fig, ax = plt.subplots()

t = np.arange(0.0, TWOPI, 0.001)
s = np.sin(t)
l = plt.plot(t, s)

ax = plt.axis([0,TWOPI,-1,1])

redDot, = plt.plot([0], [np.sin(0)], 'ro')

def animate(i):
    redDot.set_data(i, np.sin(i))
    return redDot,

# create animation using the animate() function
myAnimation = animation.FuncAnimation(fig, animate, frames=np.arange(0.0, TWOPI, 0.1), \
                                      interval=10, blit=True, repeat=True)

plt.show()

wprowadź opis zdjęcia tutaj

Zapisz animację do gif

W tym przykładzie używamy save sposobu zapisania Animation obiektu przy użyciu ImageMagick.

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

# make sure the full paths for ImageMagick and ffmpeg are configured
rcParams['animation.convert_path'] = r'C:\Program Files\ImageMagick\convert'
rcParams['animation.ffmpeg_path'] = r'C:\Program Files\ffmpeg\bin\ffmpeg.exe'

TWOPI = 2*np.pi

fig, ax = plt.subplots()

t = np.arange(0.0, TWOPI, 0.001)
s = np.sin(t)
l = plt.plot(t, s)

ax = plt.axis([0,TWOPI,-1,1])

redDot, = plt.plot([0], [np.sin(0)], 'ro')

def animate(i):
    redDot.set_data(i, np.sin(i))
    return redDot,

# create animation using the animate() function with no repeat
myAnimation = animation.FuncAnimation(fig, animate, frames=np.arange(0.0, TWOPI, 0.1), \
                                      interval=10, blit=True, repeat=False)

# save animation at 30 frames per second 
myAnimation.save('myAnimation.gif', writer='imagemagick', fps=30)

Interaktywne elementy sterujące z matplotlib.widgets

Do interakcji z wykresami Matplotlib oferuje neutralne dla GUI widżety . Widżety wymagają obiektu matplotlib.axes.Axes .

Oto demo widgetu z suwakiem, który aktualizuje amplitudę krzywej sinusoidalnej. Funkcja aktualizacji jest uruchamiana przez zdarzenie on_changed() suwaka.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib.widgets import Slider

TWOPI = 2*np.pi

fig, ax = plt.subplots()

t = np.arange(0.0, TWOPI, 0.001)
initial_amp = .5
s = initial_amp*np.sin(t)
l, = plt.plot(t, s, lw=2)

ax = plt.axis([0,TWOPI,-1,1])

axamp = plt.axes([0.25, .03, 0.50, 0.02])
# Slider
samp = Slider(axamp, 'Amp', 0, 1, valinit=initial_amp)

def update(val):
    # amp is the current value of the slider
    amp = samp.val
    # update curve
    l.set_ydata(amp*np.sin(t))
    # redraw canvas while idle
    fig.canvas.draw_idle()

# call update function on slider value change
samp.on_changed(update)

plt.show()

wprowadź opis zdjęcia tutaj Inne dostępne widżety:

Rysuj dane na żywo z potoku za pomocą Matplotlib

Może to być przydatne, gdy chcesz wizualizować przychodzące dane w czasie rzeczywistym. Dane te mogą na przykład pochodzić z mikrokontrolera, który stale próbkuje sygnał analogowy.

W tym przykładzie otrzymamy nasze dane z nazwanego potoku (znanego również jako fifo). W tym przykładzie dane w potoku powinny być liczbami oddzielonymi znakami nowej linii, ale można to dostosować do własnych upodobań.

Przykładowe dane:

100
123.5
1589

Więcej informacji o nazwanych potokach

Będziemy również używać typu danych deque ze standardowych zbiorów bibliotecznych. Obiekt deque działa dość podobnie do listy. Ale w przypadku obiektu deque dość łatwo jest do niego dołączyć, utrzymując obiekt deque na stałej długości. To pozwala nam utrzymać oś x na stałej długości zamiast zawsze powiększać i ściskać wykres razem. Więcej informacji o obiektach deque

Wybór odpowiedniego backendu ma kluczowe znaczenie dla wydajności. Sprawdź, jakie backendy działają w twoim systemie operacyjnym i wybierz szybki. Dla mnie działał tylko qt4agg i domyślny backend, ale domyślny był zbyt wolny. Więcej informacji o backendach w matplotlib

Ten przykład jest oparty na matplotlibowym schemacie losowych danych .

Żaden ze znaków w tym kodzie nie powinien zostać usunięty.

import matplotlib
import collections
#selecting the right backend, change qt4agg to your desired backend
matplotlib.use('qt4agg')
import matplotlib.pyplot as plt
import matplotlib.animation as animation

#command to open the pipe
datapipe = open('path to your pipe','r')

#amount of data to be displayed at once, this is the size of the x axis
#increasing this amount also makes plotting slightly slower
data_amount = 1000

#set the size of the deque object
datalist = collections.deque([0]*data_amount,data_amount)

#configure the graph itself
fig, ax = plt.subplots()
line, = ax.plot([0,]*data_amount)

#size of the y axis is set here
ax.set_ylim(0,256)

def update(data):
        line.set_ydata(data)
        return line,

def data_gen():
    while True:
        """
        We read two data points in at once, to improve speed
        You can read more at once to increase speed
        Or you can read just one at a time for improved animation smoothness
        data from the pipe comes in as a string,
        and is seperated with a newline character,
        which is why we use respectively eval and rstrip.
        """
        datalist.append(eval((datapipe.readline()).rstrip('\n')))
        datalist.append(eval((datapipe.readline()).rstrip('\n')))
        yield datalist

ani = animation.FuncAnimation(fig,update,data_gen,interval=0, blit=True)
plt.show()

Jeśli po pewnym czasie wykres zacznie się opóźniać, spróbuj dodać więcej danych datalist.append, aby więcej linii było czytanych w każdej ramce. Lub wybierz szybszy backend, jeśli możesz.

To działało z danymi 150 Hz z rury na moim 1,7 GHz i3 4005u.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow