[Python / matplotlib] Comprendre et utiliser FuncAnimation

Il y a deux façons de créer une animation avec matplotlib: matplotlib.animation.ArtistAnimation et matplotlib.animation.FuncAnimation. ʻArtistAnimationest plus facile et vous pouvez le créer comme vous le souhaitez. Cependant, il y avait un problème parce que c'était lourd car tous les éléments ont été créés à l'avance et conservés en mémoire.FuncAnimation` semble être plus léger car il est généré séquentiellement, mais je ne comprends pas bien le comportement et c'est toujours gênant J'ai écrit les images du numéro de série et les ai converties en mp4 plus tard. J'ai donc étudié avec beaucoup d'efforts pour les comprendre et les utiliser. Ceci est une note de synthèse.

De base

Vous pouvez créer une animation en passant les informations nécessaires à la création de l'animation à matplotlib.animation.FuncAnimation, donc ce que vous devez comprendre ce sont ses arguments et le comportement de cette fonction.

Les deux premiers arguments sont obligatoires et vous définirez généralement les arguments frames, ʻinterval` en plus d'eux.

L'idée de FuncAnimation

L'idée de FuncAnimation est résumée dans l'exemple de code suivant (extrait de API doc)

for d in frames:
   artists = func(d, *fargs)
   fig.canvas.draw_idle()
   fig.canvas.start_event_loop(interval)

Autrement dit, tournez l'itérateur frames, passez chaque" nom de trame " d à la fonction func, et dessinez le ʻartist retourné. Après ce temps ʻinterval, frames se termine. Répétez jusqu'à ce que vous le fassiez.

Exemple 1: déplacement du point P

Alors faisons-le maintenant. Créons une animation du point P qui se déplace de 0, 1, 2, ... sur l'axe des X. Mettons simplement ce que nous venons d'apprendre dans le code. Qu'il sera?

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

fig = plt.figure()
ax = fig.add_subplot(111)

def update(frame):
    ax.plot(frame, 0, "o")

anim = FuncAnimation(fig, update, frames=range(8), interval=1000)

anim.save("c01.gif", writer="imagemagick") #Si vous voulez l'afficher sur l'écran plt.show()Est bon
plt.close()

Cliquez ici pour les résultats.

c01.gif

Ce n'est pas ce que je voulais. Ce qui est différent, c'est que la position passée du point P dessiné dans l'image précédente est toujours dessinée. Pour résoudre ce problème, ʻupdate` Il semble que tous les éléments écrits en axes doivent être effacés au début de la fonction.

Exemple 2: déplacement du point P (après modification)

Voici donc le code modifié et les résultats de l'exécution.

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

fig = plt.figure()
ax = fig.add_subplot(111)

def update(frame):
    ax.cla() #Hache claire
    ax.plot(frame, 0, "o")

anim = FuncAnimation(fig, update, frames=range(8), interval=1000)

anim.save("c02.gif", writer="imagemagick")
plt.close()

c02.gif

L'animation a été réalisée comme prévu.

Notez que l'appel ʻax.cla () efface l'étiquette d'axe ʻax.set_xlabel (), les lignes de grille ʻax.grid () , la plage de dessin ʻax.set_xlim (), etc. Vous devez reconfigurer après avoir lu ʻax.cla () `.

application

Effacer uniquement un artiste spécifique

Dans l'exemple ci-dessus, tout le contenu du dessin a été effacé à chaque image, mais je pense que vous voulez souvent effacer uniquement certains artistes. Par exemple, l'exemple suivant est un point qui se déplace sur le cercle unité P Bien que ce soit une animation de, cela semble inutile car je dessine une grille et un cercle unitaire à chaque fois.

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

fig = plt.figure()
ax = fig.add_subplot(111, aspect=1)

theta = np.linspace(0, 2*np.pi, 128)

def update(f):
    ax.cla() #Hache claire
    ax.grid()
    ax.plot(np.cos(theta), np.sin(theta), c="gray")
    ax.plot(np.cos(f), np.sin(f), "o", c="red")

anim = FuncAnimation(fig, update, frames=np.pi*np.arange(0,2,0.25), interval=200)

anim.save("c03.gif", writer="imagemagick")
plt.close()

c03.gif

Dans ce cas, au lieu de tout effacer, vous pouvez atteindre votre objectif en supprimant explicitement l'artiste que vous souhaitez effacer.

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

fig = plt.figure()
ax = fig.add_subplot(111, aspect=1)

theta = np.linspace(0, 2*np.pi, 128)
p = []
ax.grid()
ax.plot(np.cos(theta), np.sin(theta), c="gray")
    
def update(f):
    if len(p) > 0:
        item = p.pop(0)
        ax.lines.remove(item)
    p.append( ax.plot([np.cos(f)], [np.sin(f)], "o", c="red")[0] )

anim = FuncAnimation(fig, update, frames=np.pi*np.arange(0,2,0.25), interval=200)

anim.save("c03.gif", writer="imagemagick")
plt.close()

Cependant, je ne sais pas lequel de ces deux exemples est le meilleur en termes de vitesse de dessin, bien qu'il semble préférable de l'utiliser avec blit = True dans l'argument FuncAnimation.

Animation avec plusieurs sous-graphiques

Si vous utilisez plt.cla () pour effacer le contenu du dessin, cela a la même signification que ʻax.cla () (ʻax sont les axes que vous avez touchés immédiatement avant), donc plusieurs sous-tracés. Les animations avec ont des sous-tracés qui ne parviennent pas à effacer ce qui est affiché. Pour tous les axes, ʻax.cla () `.

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

fig = plt.figure()
axs = [
    fig.add_subplot(121),
    fig.add_subplot(122, aspect=1),
]
theta = np.linspace(0, 4*np.pi, 128)

def update(f):
    for ax in axs:
        ax.cla() #Hache claire
        ax.grid()
    axs[0].set_xlim([0, 4*np.pi])
    axs[0].plot(theta, np.cos(theta - f), c="blue")
    axs[0].plot(0, np.cos(f), "o", c="blue")

    axs[1].plot(np.cos(theta), np.sin(theta), c="gray")
    axs[1].plot(np.cos(f), np.sin(f), "o", c="blue")
    axs[1].plot(np.cos(f), 0        , "o", c="blue")
    axs[1].plot([np.cos(f), np.cos(f)], [0, np.sin(f)], c="blue")

anim = FuncAnimation(fig, update, frames=np.pi*np.arange(0,2,0.1), interval=200)

anim.save("c04.gif", writer="imagemagick")
plt.close()

c04.gif

Les références

Recommended Posts

[Python / matplotlib] Comprendre et utiliser FuncAnimation
Utilisez matplotlib sur Ubuntu 12 et Python
Apprenez à connaître les packages et les modules Python
Installer SciPy et matplotlib (Python)
Lire et utiliser des fichiers Python à partir de Python
[Python] Utiliser et et ou lors de la création de variables
Comment installer et utiliser pandas_datareader [Python]
Utilisez PIL ou Pillow avec Cygwin Python
python: Comment utiliser les locals () et globals ()
Comment utiliser le zip Python et énumérer
[Python] Comprendre comment utiliser les fonctions récursives
Comprenez les listes Python, les dictionnaires, etc.
Comment utiliser is et == en Python
Utiliser Python et MeCab avec Azure Functions
Les bases de #Python (#matplotlib)
Mon matplotlib (Python)
Firebase: utilisez Cloud Firestore et Cloud Storage depuis Python
environnement de développement python -utilisation de pyenv et virtualenv-
[Python] Comment utiliser la fonction de hachage et taple.
Utiliser Python et word2vec (appris) avec Azure Databricks
Python> Trier par nombre et trier par alphabet> Utiliser trié ()
Utilisez libsixel pour générer Sixel en Python et générer le graphe Matplotlib vers le terminal.
[python] Compresser et décompresser
Utilisez Thingsspeak de Python
Astuces Python et Numpy
Utilisez config.ini avec Python
[Python] [Django] Comment utiliser le champ de choix et comment ajouter des options
[Python] pip et roue
Utiliser fluentd de python
J'ai essayé de résumer comment utiliser matplotlib de python
Utiliser des dates en Python
Paquets et modules Python
Intégration Vue-Cli et Python
Utiliser Valgrind avec Python
Utilisez MySQL depuis Python
Comprenez attentivement la distribution exponentielle et dessinez en Python
Utiliser mecab avec Python 3
Ruby, Python et carte
Utiliser le client LiquidTap Python ③
Inclure et utiliser des fichiers Kv externes avec Python Kivy
Utiliser DynamoDB avec Python
Utilisez SQL Alchemy et le multitraitement
Tracer et comprendre la distribution normale multivariée en Python
Carte thermique par Python + matplotlib
entrée et sortie python
Comprendre attentivement la distribution de Poisson et dessiner en Python
Python et Ruby se séparent
% Et str.format () en Python. Lequel utilisez-vous?
Utilisez Python 3.8 avec Anaconda
Comment utiliser Matplotlib
Utilisation méthodique du format [Python]
Utiliser python avec docker
Utiliser MySQL depuis Python
Utiliser le client LiquidTap Python ②
Ubuntu 20.04 sur raspberry pi 4 avec OpenCV et utilisation avec python
Utilisez BigQuery depuis Python.
Utiliser le profileur en Python
matplotlib ceci et cela