Updating data for a component of Chaco HPlotContainer

88 Views Asked by At

I have an HPlotContainer with 2 empty LinePlots as defaults, created using create_line_plot() factory function. I then perform some calculations and would like to update the plots. How do I access the ArrayPlotData of a LinePlot? I have tried something like container.components[0].data and I got an

AttributeError: 'LinePlot' object has no attribute 'data'

Clearly I am not doing the right thing here.

1

There are 1 best solutions below

2
Tim D On

The LinePlot object you are manipulating is actually what Chaco calls a "renderer" and doesn't have access to the data. To update the plots dynamically, you want to call the set_data method on the ArrayPlotData object. You can access that on the Plot objects, but in your case it makes most sense to keep a reference directly to the ArrayPlotData object. If you want to update the LinePlot object then make a reference to it. This example shows the standard way to do that kind of thing with TraitsUI and Chaco:

from chaco.api import ArrayPlotData, HPlotContainer, Plot, LinePlot
from enable.api import ComponentEditor
import numpy as np
from traits.api import Array, Event, HasTraits, Instance, Int
from traitsui.api import ButtonEditor, Item, View


class DataUpdateDemo(HasTraits):
    plots = Instance(HPlotContainer)
    plot_data = Instance(ArrayPlotData)
    line_plot_1 = Instance(LinePlot)
    line_plot_2 = Instance(LinePlot)
    x = Array
    y = Array
    go = Event
    w = Int(1)

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

    def _y_default(self):
        y = np.sin(self.w * self.x)
        return y

    def _plots_default(self):
        self.plot_data = ArrayPlotData(y=self.y, x=self.x)
        plot1 = Plot(self.plot_data)
        self.line_plot_renderer1 = plot1.plot(('x', 'y'), kind='line')[0]
        plot2 = Plot(self.plot_data)
        self.line_plot_renderer_2 = plot2.plot(('y', 'x'), kind='line')[0]
        plots = HPlotContainer(plot1, plot2)
        return plots

    def _go_fired(self):
        self.w += 1
        y = np.sin(self.w * self.x)
        self.plot_data.set_data("y", y)

    traits_view = View(
        Item('plots', editor=ComponentEditor(), show_label=False),
        Item('go', editor=ButtonEditor(label="update"), show_label=False),
    )


if __name__ == "__main__":
    dud = DataUpdateDemo()
    dud.configure_traits()

Now you can do whatever manipulations you want on the LinePlot object.

I get output that looks like this:

enter image description here