WedX - журнал о программировании и компьютерных науках

Сохранение анимации диаграммы рассеяния с помощью matplotlib

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

Этот код представляет собой модифицированную версию Giggi на Анимация 3D-диаграммы рассеяния в matplotlib с исправлением цветов из ответа Янна на цвет рассеяния Matplotlib 3D потерян после перерисовки (потому что цвета будут важны в моем видео, поэтому я хочу убедиться, что они работают).

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

FLOOR = -10
CEILING = 10

class AnimatedScatter(object):
    def __init__(self, numpoints=5):
        self.numpoints = numpoints
        self.stream = self.data_stream()
        self.angle = 0

        self.fig = plt.figure()
        self.fig.canvas.mpl_connect('draw_event',self.forceUpdate)
        self.ax = self.fig.add_subplot(111,projection = '3d')
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=100, 
                                       init_func=self.setup_plot, blit=True,frames=20)

    def change_angle(self):
        self.angle = (self.angle + 1)%360

    def forceUpdate(self, event):
        self.scat.changed()

    def setup_plot(self):
        X = next(self.stream)
        c = ['b', 'r', 'g', 'y', 'm']
        self.scat = self.ax.scatter(X[:,0], X[:,1], X[:,2] , c=c, s=200, animated=True)

        self.ax.set_xlim3d(FLOOR, CEILING)
        self.ax.set_ylim3d(FLOOR, CEILING)
        self.ax.set_zlim3d(FLOOR, CEILING)

        return self.scat,

    def data_stream(self):
        data = np.zeros(( self.numpoints , 3 ))
        xyz = data[:,:3]
        while True:
            xyz += 2 * (np.random.random(( self.numpoints,3)) - 0.5)
            yield data

    def update(self, i):
        data = next(self.stream)
        #data = np.transpose(data)

        self.scat._offsets3d = ( np.ma.ravel(data[:,0]) , np.ma.ravel(data[:,1]) , np.ma.ravel(data[:,2]) )

        plt.draw()
        return self.scat,

    def show(self):
        plt.show()

if __name__ == '__main__':
    a = AnimatedScatter()
    a.ani.save("movie.avi", codec='avi')
    a.show()

При этом создается совершенно правильный .avi, но он пуст в течение всех четырех секунд, кроме осей. Фактическая цифра всегда показывает именно то, что я хочу видеть. Как я могу заполнить графики функции сохранения так же, как я заполняю обычно работающую анимацию, или это возможно в matplotlib?

EDIT: Использование вызова разброса в обновлении (без установки границ, как в инициализаторе) приводит к тому, что .avi показывает рост осей, показывая, что данные запускаются каждый раз, они просто не отображаются на самом видео. Я использую matplotlib 1.1.1rc с Python 2.7.3.


  • можешь исправить отступ? 07.02.2013
  • Упс. Я должен быть более осторожным при копировании и вставке. Хотя в моем исходнике вместо табуляции есть пробелы, поэтому я не совсем понимаю, что произошло. 07.02.2013
  • и это выглядит нормально, если вы посмотрите на это в цифре? Какую версию MPL вы используете? 07.02.2013
  • Фигура не проблема, .avi есть. Я заметил, что это сработало в первом абзаце, но позвольте мне отредактировать это, чтобы подчеркнуть. Я использую версию 1.1.1rc. 07.02.2013
  • если вы удалите plt.draw() из update, это сломает фигуру, что, я думаю, является подсказкой. 07.02.2013

Ответы:


1

Удалите blit=True из FuncAnimation и animated=True из scatter и все заработает. Я подозреваю, что что-то не так с логикой, которая гарантирует, что между кадрами обновляются/перерисовываются только художники, которых необходимо обновить (а не просто перерисовывать все).

Ниже приведено именно то, что я запустил, и я получил ожидаемый выходной фильм:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

FLOOR = -10
CEILING = 10

class AnimatedScatter(object):
    def __init__(self, numpoints=5):
        self.numpoints = numpoints
        self.stream = self.data_stream()
        self.angle = 0

        self.fig = plt.figure()
        self.fig.canvas.mpl_connect('draw_event',self.forceUpdate)
        self.ax = self.fig.add_subplot(111,projection = '3d')
        self.ani = animation.FuncAnimation(self.fig, self.update, interval=100, 
                                       init_func=self.setup_plot, frames=20)

    def change_angle(self):
        self.angle = (self.angle + 1)%360

    def forceUpdate(self, event):
        self.scat.changed()

    def setup_plot(self):
        X = next(self.stream)
        c = ['b', 'r', 'g', 'y', 'm']
        self.scat = self.ax.scatter(X[:,0], X[:,1], X[:,2] , c=c, s=200)

        self.ax.set_xlim3d(FLOOR, CEILING)
        self.ax.set_ylim3d(FLOOR, CEILING)
        self.ax.set_zlim3d(FLOOR, CEILING)

        return self.scat,

    def data_stream(self):
        data = np.zeros(( self.numpoints , 3 ))
        xyz = data[:,:3]
        while True:
            xyz += 2 * (np.random.random(( self.numpoints,3)) - 0.5)
            yield data

    def update(self, i):
        data = next(self.stream)
        self.scat._offsets3d = ( np.ma.ravel(data[:,0]) , np.ma.ravel(data[:,1]) , np.ma.ravel(data[:,2]) )
        return self.scat,

    def show(self):
        plt.show()

if __name__ == '__main__':
    a = AnimatedScatter()
    a.ani.save("movie.avi", codec='avi')
    a.show()
06.02.2013
  • Это сделало трюк! И мой настоящий проект работал с этим исправлением. Спасибо! 07.02.2013
  • Интересно, что удаление blit помогает, учитывая, что код animation.save устанавливает blit в false при вызове _draw_next_frame. Я добавлю полные отчеты об ошибках (или, по крайней мере, запросы в список пожеланий) на сайт matplotlib, когда у меня будет такая возможность. 07.02.2013
  • С SciPy 0.12.0, Numpy 1.7.1 и Matplotlib 1.2.1 я не смог заставить это работать. В лучшем случае это создаст видео с кучей старых точек, перезаписанных новыми точками, или пустой график. Вы можете попробовать код, указанный в моем видео: youtube.com/watch?v= dCIOOjJ1Sk0 Наконец-то я воспользовался CamStudio, и он работал лучше и выводил видео более высокого качества. 30.04.2013
  • Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]