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

Я пытаюсь анимировать кучу 2D-изображений с помощью 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 Изображения уже находятся в трехмерном массиве, хранящемся в памяти (nt, nx, ny). Единственным узким местом является обновление сюжета.   -  person tiago    schedule 25.09.2015
comment
Если массив уже находится в памяти, можете ли вы просто set_data на другом срезе? Вы должны быть осторожны, чтобы случайно не сделать копии массива.   -  person Tim D    schedule 29.09.2015
comment
@TimD Я не делаю копии массива. В любом случае, хранение их в памяти, хотя и возможно в некоторых случаях, не является моей конечной целью. В идеале я хотел бы иметь массивы с памятью, потому что временной ряд может быть намного больше, чем системная память.   -  person tiago    schedule 01.10.2015


Ответы (2)


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

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)

Это автоматически называет каждое изображение «серия1», «серия2» и т. д. Затем вы можете вызвать:

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