Как да ускорим графиката на чако изображение

Опитвам се да анимирам куп 2D изображения с chaco, но за съжаление не изглежда толкова бързо, колкото е необходимо на приложението ми. В момента изграждам chaco Plot и използвам img_plot, напр.:

pd = ArrayPlotData()
pd.set_data("imagedata", myarray)
plot = Plot(pd)
plot.img_plot("imagedata", interpolation="nearest")

И за да актуализирам изображението, използвам следното:

pd.set_data("imagedata", my_new_array)

Това работи, но не е достатъчно бързо. Има ли някакъв начин да го ускоря? Някаква функция от по-ниско ниво, която позволява по-бързо актуализиране на изображението?


person tiago    schedule 24.09.2015    source източник
comment
Имате ли вече придобити изображения или ги показвате, докато придобивате?   -  person J. Corson    schedule 25.09.2015
comment
@J.Corson Изображенията вече са в 3D масив, съхранен в паметта (nt, nx, ny). Единственото тясно място е актуализацията на сюжета.   -  person tiago    schedule 25.09.2015
comment
Ако масивът вече е в паметта, можете ли просто да set_data на друг срез? Трябва да внимавате да не правите по невнимание копия на масива.   -  person Tim D    schedule 29.09.2015
comment
@TimD Не правя копия на масива. Във всеки случай съхраняването им в паметта, макар и възможно в някои случаи, не е крайната ми цел. В идеалния случай бих искал да имам тогава като memmapped масиви, защото времевите серии могат да бъдат много по-големи от системната памет.   -  person tiago    schedule 01.10.2015


Отговори (2)


Ето пример за това как правя анимации в Chaco с помощта на таймер. Обикновено трикът (както каза J Corson) е да заредите вашите данни в масив и след това просто да използвате индекс, за да вземете последователни части от масива.

from chaco.api import ArrayPlotData, Plot
from enable.api import ComponentEditor
import numpy as np
from pyface.timer.api import Timer
from traits.api import Array, Bool, Event, HasTraits, Instance, Int
from traitsui.api import ButtonEditor, Item, View


class AnimationDemo(HasTraits):
    plot = Instance(Plot)
    x = Array
    y = Array
    run = Bool(False)
    go = Event
    idx = Int

    def _x_default(self):
        x = np.linspace(-np.pi, np.pi, 100)
        return x

    def _y_default(self):
        phi = np.linspace(0, 2 * np.pi, 360)
        y = np.sin(self.x[:, np.newaxis] + phi[np.newaxis, :]) - \
            0.1 * np.sin(13 * self.x[:, np.newaxis] - 7 * phi[np.newaxis, :])
        return y

    def _plot_default(self):
        plot_data = ArrayPlotData(y=self.y[:, 0], x=self.x)
        plot = Plot(plot_data)
        plot.plot(('x', 'y'))
        return plot

    def _go_fired(self):
        if not self.run:
            self.run = True
        else:
            self.run = False

    def _run_changed(self):
        if self.run:
            self.timer.Start()
        else:
            self.timer.Stop()

    def _run_default(self):
        self.timer = Timer(5, self._timer_tick)
        return False

    def _timer_tick(self):
        if not self.run:
            raise StopIteration
        else:
            if self.idx >= 360:
                self.idx = 0
            self.plot.data.set_data('y', self.y[:, self.idx])
            self.idx += 1

    traits_view = View(
        Item('plot', editor=ComponentEditor(), show_label=False),
        Item('go', editor=ButtonEditor(label="Start/Stop"), show_label=False),
    )


if __name__ == "__main__":
    ad = AnimationDemo()
    ad.edit_traits()

Получавам нещо подобно:

Демо Чако

person Tim D    schedule 29.09.2015
comment
Благодаря ви за пълния пример. Вашият случай обаче използва същото, което използвах аз (set_data), така че това не променя нещата за мен. - person tiago; 01.10.2015

Това е само мисъл, но добавянето на всяко изображение първоначално във вашия ArrayPlotData ще реши ли проблема ви? Тогава вие не добавяте ново изображение на всяка стъпка от вашата анимация, а просто извиквате img_plot() на следващата серия. Например, ако вашите изображения се съхраняват в numpy масив, наречен images[nt, nx, ny]:

pd = ArrayPlotData()
for index in range(images.shape[0]): #Assuming you want to iterate over nt
    pd.set_data('', images[index,:,:], generate_name = True)
plot = Plot(pd)

Това автоматично наименува всяко изображение 'series1', 'series2' и т.н. След това можете да извикате:

plot.img_plot('series1', interpolation = 'nearest') #or 'series2' etc. 

за всяко изображение във вашата анимация, без да се налага да извиквате set_data().

Можете да получите сортиран списък с имената на вашите изображения ['series1, 'series2', ...], за да ги повторите, като използвате:

from natsort import natsorted #sort using natural sorting
names = natsorted(pd.list_data())

Това би ли помогнало с тясното място?

person J. Corson    schedule 25.09.2015
comment
-1. Най-накрая имам време да приложа предложението ви. За съжаление, той е 20 пъти по-бавен от първоначалния ми подход. Не разбирам защо правенето на img_plot от нулата всеки път е по-бързо от простото актуализиране на данните. Тестовете в реалния свят изглежда са съгласни. - person tiago; 06.10.2015