Как добавить панель управления временем в FuncAnimation из matplotlib

В настоящее время я использую matplotlib.animation.FuncAnimation() для отображения анимации моей работы на фигура.

Это работает очень хорошо, и я понимаю аргументы, которые я использую (интервал, временной диапазон, ...). Однако мне было интересно, есть ли способ реализовать (возможно, непосредственно на рисунке) панель, содержащую анимацию, полоса прокрутки или что-то еще, что позволяет мне:

  • Быстро перемещайтесь вперед или назад к интересующему часовому поясу.
  • Показать, в какой точке анимации я нахожусь (10%, затем 20%,...).

По сути, это способ управления анимацией в python на фигуре, такой же, как я бы управлял ею как видеофайлом, воспроизводимым видеоплеером?

Если нужно, вот как выглядит код этой анимации:

    def init():
        im1.set_data(XYslice[0, :, :])
        im2.set_data(XZslice[0, Nplans/2:, :])
        return([im1, im2])

    def animate(t):
       im1.set_data(XYslice[t, :, :])
       im2.set_data(XZslice[t, Nplans/2:, :])
       return [im1, im2]

    anim = animation.FuncAnimation(fig, animate, np.arange(Ntime), interval=200,
                                 blit=True, init_func=init, repeat=True)

person Magea    schedule 02.04.2015    source источник


Ответы (1)


То, о чем вы говорите, это графический интерфейс. В самом простом примере используются встроенные в matplotlib виджеты:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import bivariate_normal
from matplotlib.widgets import Slider, Button

#Setup figure and data
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
delta = 0.5
t = np.arange(0.0, 100.0, 0.1)
x = np.arange(-3.0, 4.001, delta)
y = np.arange(-4.0, 3.001, delta)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
Z = (Z1 - Z2) * 5.
cmap = plt.cm.rainbow
im = ax.pcolormesh(X, Y, Z, cmap=cmap)
fig.colorbar(im)
axcolor = 'lightgoldenrodyellow'
axtime = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
stime = Slider(axtime, 'Time', 0.0, 100.0, valinit=50.0)

#Routines to reset and update sliding bar
def reset(event):
    stime.reset()

def update(val):
    time = stime.val/10.
    Z = (Z1 - Z2) * time
    im.set_array(Z.ravel())
    fig.canvas.draw()

#Bind sliding bar and reset button  
stime.on_changed(update)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
button.on_clicked(reset)

plt.show()

Это должно быть началом. Если вы хотите, чтобы он выглядел лучше (и добавил больше функциональности), вам нужно перейти к графическому интерфейсу, такому как wxpython, проверить этот пример.

Пример, который более соответствует вашей структуре данных, будет выглядеть следующим образом:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.mlab import bivariate_normal
from matplotlib.widgets import Slider, Button

#Setup figure and data
fig, ax = plt.subplots()
plt.subplots_adjust(bottom=0.25)
delta = 0.5
t = np.linspace(0.0, 100.0, 256)
x = np.linspace(-4.0, 4.001, 512)
y = np.linspace(-4.0, 4.001, 512)
X, Y = np.meshgrid(x, y)
Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0)
Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1)
XZslice = np.zeros((256,512,512))
for i in range(t.shape[0]):
    XZslice[i,:,:] = (Z1 - Z2) * t[i]/10.
cmap = plt.cm.rainbow
im = ax.pcolormesh(XZslice[128,:,:], cmap=cmap)
fig.colorbar(im)
axcolor = 'lightgoldenrodyellow'
axtime = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
stime = Slider(axtime, 'Time', 0.0, 100.0, valinit=50.0)

#Routines to reset and update sliding bar
def reset(event):
    stime.reset()

def update(val):
    time = int(stime.val/100.* 256)
    im.set_array(XZslice[time,:,:].ravel())
    fig.canvas.draw()

#Bind sliding bar and reset button  
stime.on_changed(update)
resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
button.on_clicked(reset)

plt.show()
person Ed Smith    schedule 02.04.2015
comment
Это круто ! Я рад попробовать адаптировать его к моей работе. Большое спасибо ! - person Magea; 02.04.2015
comment
То, что ты мне дал, прекрасно. Но я был слишком увлечен, и теперь у меня проблемы с тем, чтобы заставить его работать в моей конкретной ситуации. Я не знаю, как заменить данные, которые вы выбрали для отображения в качестве примера, моими данными. У меня есть файл с фигурами: 256 512 512. 256 — это временные точки, а 512 — для X и Y. Я думаю, что все мои проблемы связаны со значением Z и с тем, как его использовать, как в вашем примере. - person Magea; 02.04.2015
comment
Программирование с графическим интерфейсом немного странно при первом запуске. Я добавил версию, которая перемещается по результатам в массиве размером 256 512 512. Главное, на что следует обратить внимание, это то, что stime создается как объект ползунка, stime.on_changed(update) связывает подпрограмму update, поэтому эта подпрограмма вызывается каждый раз, когда ползунок изменяет значение, а stime.val дает текущее значение ползунка. Я предположил, что вам нужна цветовая сетка. Вы можете добавить ползунок для местоположения y, который изменяет индекс в вашем массиве, если вы хотите отображать данные линии. - person Ed Smith; 02.04.2015
comment
Спасибо большое за вашу помощь ! Так что я попробовал то, что вы любезно дали мне. Я добавил код в конце моей предыдущей работы. Поэтому я хотел попробовать вашу вещь в третьем рисунке (рисунок 1 - моя анимация, рисунок 2 - некоторые сюжеты, которые я использую). Итак, что я получаю? Я хорошо получаю графический интерфейс, работающий с анимацией, которая может быть сдвинута по времени по мере необходимости, НО данные из моей основной анимации теперь странные, не совсем неправильные, но все же странные, и поэтому я не могу сказать, что это работает ахах - person Magea; 02.04.2015
comment
Я удалил первую часть скрипта. Итак, теперь у меня есть мои данные и то, что вы мне дали. У меня такой же странный результат. Это нормально, что первая картинка, та, что на 50 (определена в скрипте), выглядит совсем не так, как остальные, и когда я возвращаюсь к 50%, у меня не то же самое, что и при открытии? ^^' - person Magea; 02.04.2015
comment
хм, я думаю, у вас будут проблемы с использованием виджетов на одном рисунке с анимацией. Обычно графический интерфейс запускает бесконечный цикл проверки пользовательского ввода (например, в виде изменений ползунка). Сомневаюсь, что это будет хорошо работать с анимацией. Если вам нужно и то, и другое вместе, возможно, попробуйте два экземпляра python, один графический интерфейс и одну анимацию? Я заметил первоначальную разницу при использовании colormesh(X,Y,Z), я думаю, это потому, что первый вызов указывает местоположения X и Z, а set_array нет. Вы можете fig.clf(keep_observers=True) в процедуре обновления и, возможно, полностью воссоздать фигуру. - person Ed Smith; 02.04.2015
comment
Привет ! Я боюсь, что мы подошли к точке, где из-за того, что я неправильно объясняю вам материал, мы начинаем говорить в разных направлениях ^^' Все в порядке, вы мне очень помогли и дали мне правильное направление, это моя работа теперь, чтобы узнать это и заставить его работать ;) Спасибо и хорошего дня. - person Magea; 03.04.2015