Создание анимации из предварительно рассчитанного набора сюжетов: ArtistAnimation - PullRequest
0 голосов
/ 27 декабря 2018

Я пытаюсь изучить некоторые из функций анимации Matplotlib.

Рассмотрим эту попытку попытаться нарисовать увеличение амплитуды кривых синуса и косинуса.

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

fig = plt.figure()


ims = []
x   = np.linspace(0,10,20)
for i in range(60):
    y1 = map (lambda t: i*np.sin(t) , x)
    y2 = map (lambda t: i*np.cos(t) , x)

    im1 = plt.plot(x, y1, 'bo-')
    im2 = plt.plot(x, y2, 'go-')

    ims.extend([im1,im2])

ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True, repeat_delay=1000)

plt.show()

Это рисует для меня чередующийся набор кривых синего синуса и зеленого косинуса.Если вы попытаетесь построить их, вы увидите, что результирующий график представляет собой очень быстрый чередующийся набор изображений между синусом и косинусом.

Я знаю, что это, вероятно, ims.extend([im1,im2]), которая является оскорбительной командой здесь.Однако, когда вместо .extend я использовал .append(), чтобы ims стал списком изображений, я получаю ошибку

Traceback (most recent call last):
  File "dynamic_image.py", line 29, in <module>
    ani.save("movie.mp4")
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/animation.py", line 1254, in save
    anim._init_draw()
  File "/usr/local/lib/python2.7/dist-packages/matplotlib/animation.py", line 1618, in _init_draw
    artist.set_visible(False)
AttributeError: 'list' object has no attribute 'set_visible'

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

Проблема в том, что значение, возвращаемое из plt.plot, является списком.Например, im1 будет выглядеть примерно так:

[<matplotlib.lines.Line2D at 0x11a0f62e8>]

Когда вы добавляете художников в свой список, вы добавляете двух художников по отдельности.Поэтому измените эту строку:

ims.extend([im1,im2])

На это:

ims.extend([im1 + im2])

Теперь длина ims равна 60 вместо 120, и косинус и синус будут нанесены вместе.

Я написал библиотеку, чтобы сделать это проще, под названием celluloid .Это черный ящик, поэтому, если ваша цель - изучить matplotlib, вы можете пропустить.Пожалуйста, прочитайте ограничения, если вы решите использовать его.Вот как будет выглядеть код для воспроизведения вашей анимации:

from celluloid import Camera
fig = plt.figure()
camera = Camera(fig)
x   = np.linspace(0,10,20)
for i in range(60):
    plt.plot(x, i*np.sin(x), 'go-')
    plt.plot(x, i*np.cos(x), 'bo-')
    camera.snap()
ani = camera.animate(interval=50, blit=True, repeat_delay=1000)
0 голосов
/ 27 декабря 2018

Я не уверен, причина, но если вам нужен только результат, вы можете попробовать следующий код.Если вам нужно знать причину, давайте подождем, чтобы узнать, сможет ли кто-нибудь ответить на нее.

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

fig, ax = plt.subplots()
x = np.linspace(0, 10, 50)
line1, = ax.plot(x, np.sin(x), 'bo-')
line2, = ax.plot(x, np.cos(x), 'go-')
ax.set_ylim(-60, 60)

def init():
    line1.set_ydata([np.nan] * len(x))
    line2.set_ydata([np.nan] * len(x))
    return [line1, line2]

def animate(i):
    line1.set_ydata(i * np.sin(x))
    line2.set_ydata(i * np.cos(x))
    return [line1, line2]

ani = animation.FuncAnimation(fig, animate, init_func=init, 
                              blit=True, frames=60, repeat=True,
                              interval=50, repeat_delay=1000)
ani.save('result.mp4')
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...