【问题标题】:How to speed up chaco image plot如何加快 chaco 图像绘图
【发布时间】:2015-09-24 21:23:02
【问题描述】:

我正在尝试使用 chaco 为一堆 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)

这可行,但不够快。有什么办法可以加快速度吗?任何允许更快更新图像的低级函数?

【问题讨论】:

  • 您是否已经获取了图像或正在获取时显示?
  • @J.Corson 图像已经在存储在内存中的 3D 数组中(nt、nx、ny)。唯一的瓶颈是剧情更新。
  • 如果数组已经在内存中,你可以在另一个切片上 set_data 吗?你要小心,不要无意中复制了数组。
  • @TimD 我没有制作数组的副本。无论如何,将它们存储在内存中,虽然在某些情况下是可能的,但这并不是我的最终目标。理想情况下,我希望将其作为 memmapped 数组,因为时间序列可能比系统内存大得多。

标签: python enthought chaco


【解决方案1】:

这是我如何使用计时器在 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()

我得到这样的东西:

【讨论】:

  • 感谢您提供完整的示例。但是,您的案例使用与我一直使用的相同 (set_data),所以它不会改变我的情况。
【解决方案2】:

这只是一个想法,但是最初将每个图像添加到 ArrayPlotData 中会解决您的问题吗?然后,您不会在动画的每一步都添加新图像,而只是在下一个系列中调用 img_plot()。例如,如果您的图像存储在一个名为 images[nt, nx, ny] 的 numpy 数组中:

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())

这对瓶颈有帮助吗?

【讨论】:

  • -1。终于有时间实施你的建议了。不幸的是,它比我原来的方法慢了 20 倍。我不明白为什么每次从头开始做一个 img_plot 比仅仅更新数据要快。现实世界的测试似乎同意。
猜你喜欢
  • 1970-01-01
  • 2012-03-13
  • 2013-07-03
  • 2019-09-13
  • 2016-02-09
  • 2015-04-04
  • 2018-10-16
  • 2020-10-16
  • 1970-01-01
相关资源
最近更新 更多