matplotlib.animation
Оглавление
Диаграммы наследования
Анимация
Самый простой способ создания живой анимации в Matplotlib — использование одного из классов Animation.
Базовый класс для анимаций. | |
Создание анимации путём многократного вызова функции func. | |
Анимация с использованием фиксированного набора объектов |
В обоих случаях крайне важно сохранять ссылку на экземпляр объекта. Анимация продвигается таймером (обычно из фреймворка GUI), и у объекта Animation имеется единственная ссылка на него. Если вы не сохраняете ссылку на объект Animation, он (и, следовательно, таймеры) будут удалены сборщиком мусора, что приведёт к остановке анимации.
Для сохранения анимации используйте Animation.save, Animation.to_html5_video или Animation.to_jshtml.
Подробнее о поддерживаемых форматах видео см. в разделе Вспомогательные классы ниже.
FuncAnimation
Внутренняя работа FuncAnimation примерно такова:
for d in frames: artists = func(d, *fargs) fig.canvas.draw_idle() fig.canvas.start_event_loop(interval)
с деталями для обработки «блиттинга» (чтобы значительно улучшить производительность в реальном времени), чтобы быть неблокирующим, не повторять запуск/остановку цикла обработки событий GUI, обрабатывать повторы, несколько осей анимации и легко сохранять анимацию в файл видео.
«Блиттинг» — это стандартная техника в компьютерной графике. Суть в том, чтобы взять существующий битмап (в нашем случае — в основном растрированную фигуру) и затем «блитнуть» на него ещё один элемент. Таким образом, управляя сохранённым «чистым» битмапом, мы можем перерисовать только те немногие элементы, которые изменяются в каждом кадре, и, возможно, сэкономить значительное количество времени. Когда мы используем блиттинг (передав blit=True), основной цикл FuncAnimation становится немного сложнее:
ax = fig.gca()
def update_blit(artists):
fig.canvas.restore_region(bg_cache)
for a in artists:
a.axes.draw_artist(a)
ax.figure.canvas.blit(ax.bbox)
artists = init_func()
for a in artists:
a.set_animated(True)
fig.canvas.draw()
bg_cache = fig.canvas.copy_from_bbox(ax.bbox)
for f in frames:
artists = func(f, *fargs)
update_blit(artists)
fig.canvas.start_event_loop(interval)
Это, конечно, опускает много деталей (например, обновление фона при изменении размера или полном перерисовании фигуры). Однако, надеюсь, этот минимальный пример даёт представление о том, как init_func и func используются внутри FuncAnimation и о теории работы «блиттинга».
Ожидаемая сигнатура для func и init_func очень проста, чтобы избавить FuncAnimation от вашей логики ведения записей и построения графиков, но это означает, что вызываемые объекты, которые вы передаёте, должны знать, за какими элементами им нужно следить. Есть несколько подходов к решению этой задачи, различающихся по сложности и инкапсуляции. Самый простой подход, который работает довольно хорошо в случае скрипта, заключается в определении элемента на глобальном уровне и предоставлении Python возможности разобраться со всем.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
fig, ax = plt.subplots()
xdata, ydata = [], []
ln, = plt.plot([], [], 'ro')
def init():
ax.set_xlim(0, 2*np.pi)
ax.set_ylim(-1, 1)
return ln,
def update(frame):
xdata.append(frame)
ydata.append(np.sin(frame))
ln.set_data(xdata, ydata)
return ln,
ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
init_func=init, blit=True)
plt.show()
Второй метод заключается в использовании functools.partial для «связывания» элементов с функцией. Третий метод — использование замыканий для создания необходимых элементов и функций. Четвёртый — создание класса.
Примеры
ArtistAnimation
Примеры
Классы записи
Представленные классы записи делятся на несколько широких категорий.
Класс записи Pillow использует библиотеку Pillow для записи анимации, сохраняя все данные в памяти.
Класс записи HTML генерирует анимации на основе JavaScript.
Запись для HTML-видео на основе JavaScript. |
Классы записи, основанные на каналах, передают захваченные кадры по каналу во внешний процесс. Классы записи, основанные на каналах, как правило, более производительны, но могут не работать на всех системах.
Запись ffmpeg, основанная на каналах. | |
Анимированный GIF, основанный на каналах. |
Классы записи, основанные на файлах, сохраняют временные файлы для каждого кадра, которые склеиваются в один файл в конце. Хотя они медленнее, эти классы записи могут быть легче отлаживать.
Запись ffmpeg, основанная на файлах. | |
Запись анимированного GIF, основанная на файлах. |
В основе MovieWriter лежит возможность получения последовательных кадров из одного базового объекта Figure. Базовый класс MovieWriter реализует 3 метода и менеджер контекста. Единственное отличие между классами записи, основанными на каналах и файлах, заключается в аргументах их соответствующих методов setup.
Метод setup() используется для подготовки записи (возможно, открытия канала), последующие вызовы grab_frame() захватывают по одному кадру за раз, а finish() завершает создание фильма и записывает выходной файл на диск. Например
moviewriter = MovieWriter(...)
moviewriter.setup(fig, 'my_movie.ext', dpi=100)
for j in range(n):
update_figure(j)
moviewriter.grab_frame()
moviewriter.finish()
Если вы используете классы записи напрямую (а не через Animation.save), настоятельно рекомендуется использовать менеджер контекста saving
with moviewriter.saving(fig, 'myfile.mp4', dpi=100):
for j in range(n):
update_figure(j)
moviewriter.grab_frame()
чтобы гарантировать выполнение необходимой настройки и очистки.
Примеры
Вспомогательные классы
Базовые классы анимации
Базовый класс для анимаций. | |
Подкласс |
Регистр записи
Предоставлен модульный реестр для сопоставления имени записи с классом, что позволяет передать строку в Animation.save вместо экземпляра записи.
Реестр доступных классов записи по удобочитаемому имени. |
Базовые классы записи
Для сокращения дублирования кода предоставлены базовые классы
Абстрактный базовый класс для записи фильмов. | |
Базовый класс для записи фильмов. | |
|
и миксины
Миксин-класс для вывода FFMpeg. | |
Миксин-класс для вывода ImageMagick. |
предоставлены.
См. исходный код, чтобы узнать, как легко реализовать новые классы MovieWriter.
© 2012–2021 Matplotlib Development Team. All rights reserved.
Licensed under the Matplotlib License Agreement.
https://matplotlib.org/3.5.1/api/animation_api.html