[Python / matplotlib] Understand and use FuncAnimation

There are two ways to create animations with matplotlib: matplotlib.animation.ArtistAnimation and matplotlib.animation.FuncAnimation. ʻArtistAnimationis easier and you can create it as you wish. However, there was a problem that it was heavy because all the elements were created in advance and kept in memory.FuncAnimation` seems to be lighter because it is generated sequentially, but I do not understand the behavior well and it is always troublesome. I wrote out the serial number images and converted them to mp4 later. So I studied with a lot of effort to understand and use them. This is a summary note.

Basic

If you pass the information needed to create the animation to matplotlib.animation.FuncAnimation, it will create the animation, so what you need to understand is its arguments and the behavior of this function.

The first two arguments are required, and you will usually set the arguments frames, ʻinterval` in addition to them.

--The first argument fig is Figure. This is something I use a lot, so I don't need to explain it. --The second argument, func, is the main subject. We will see this in detail in the next bar. --The argument frames is an iterator that produces the equivalent of the" name "of each frame, for example passingrange (128)ornp.linspace (0, 2 * np.pi, 128). In this case, both create an animation with 128 frames. --The argument ʻinterval` specifies the time to switch frames in milliseconds. The default is 200.

The idea of FuncAnimation

The idea of FuncAnimation is summarized in the following code example. (Quoted from API doc)

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

That is, iterator frames is turned, each" frame name " d is passed to the function func, and the returned ʻartist is drawn. After this time ʻinterval, frames ends. Repeat until you do. That's it.

Example 1: Moving point P

So let's do it now. Let's create an animation of the point P that moves 0, 1, 2, ... on the x-axis. Will it be?

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") #If you want to display it on the screen plt.show()Is good
plt.close()

Click here for the results.

c01.gif

It's not what I intended. What's different is that the past position of the point P drawn in the previous frame is still drawn. To fix this, ʻupdate` It seems that all the elements written in axes should be cleared at the beginning of the function.

Example 2: Moving point P (after modification)

So here is the modified code and execution results.

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

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

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

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

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

c02.gif

The animation was as intended.

Note that calling ʻax.cla () clears the axis label ʻax.set_xlabel (), grid lines ʻax.grid () , drawing range ʻax.set_xlim (), etc. You need to reconfigure after reading ʻax.cla () `.

application

Clear only specific artists

In the above example, all the drawing contents were erased at each frame, but I think that you often want to clear only some artists. For example, the following example is a point that moves on the unit circle P Although it is an animation of, it seems to be useless because I draw a grid and a unit circle every time.

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() #Clear ax
    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

In this case, instead of clearing everything, you can achieve your goal by explicitly removing the Artist you want to erase.

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

However, I'm not sure which of these two examples is better in terms of drawing speed, although it seems better to use it with blit = True in the FuncAnimation argument.

Animation with multiple subplots

If you use plt.cla () to clear the drawing content, this has the same meaning as ʻax.cla () (ʻax is the Axes you touched immediately before), so multiple subplots. Animations with have some subplots that fail to clear what is displayed. For all Axes, let's do ʻ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() #Clear ax
        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

References

Recommended Posts

[Python / matplotlib] Understand and use FuncAnimation
Use matplotlib on Ubuntu 12 & Python
Understand Python packages and modules
Installation of SciPy and matplotlib (Python)
[Python] font family and font with matplotlib
Read and use Python files from Python
[Python] Use and and or when creating variables
How to install and use pandas_datareader [Python]
Use PIL and Pillow with Cygwin Python
python: How to use locals () and globals ()
How to use Python zip and enumerate
[Python] Understand how to use recursive functions
Understand python lists, dictionaries, and so on.
How to use is and == in Python
Use Python and MeCab with Azure Functions
#Python basics (#matplotlib)
My matplotlib (python)
Firebase: Use Cloud Firestore and Cloud Storage from Python
python development environment -use of pyenv and virtualenv-
[Python] How to use hash function and tuple.
Use Python and word2vec (learned) with Azure Databricks
Python> Sort by number and sort by alphabet> Use sorted ()
Use libsixel to output Sixel in Python and output a Matplotlib graph to the terminal.
[python] Compress and decompress
Use thingsspeak from python
Python and numpy tips
Use config.ini in Python
[Python] [Django] How to use ChoiceField and how to add options
[Python] pip and wheel
Use fluentd from python
I tried to summarize how to use matplotlib of python
Use dates in Python
Batch design and python
Python packages and modules
Vue-Cli and Python integration
Use Valgrind in Python
Use MySQL from Python
Carefully understand the exponential distribution and draw in Python
Use mecab with Python3
Ruby, Python and map
Use LiquidTap Python Client ③
Include and use external Kv files in Python Kivy
Use DynamoDB with Python
Use SQLAlchemy and multiprocessing
Plot and understand the multivariate normal distribution in Python
Heatmap with Python + matplotlib
python input and output
Carefully understand the Poisson distribution and draw in Python
Python and Ruby split
% And str.format () in Python. Which one do you use?
Use Python 3.8 with Anaconda
How to use Matplotlib
[Python] format methodical use
Use python with docker
Use MySQL from Python
Use LiquidTap Python Client ②
Ubuntu 20.04 on raspberry pi 4 with OpenCV and use with python
Use BigQuery from python.
Use profiler in Python
matplotlib this and that
Python3, venv and Ansible