0

我需要为我在 chaco 所做的现有情节添加一些要点。我试过了,plot.request_redraw()但没有用。我还可以做些什么?

这是一段代码:

class PlotApp(HasTraits):

plotdata = Instance(ArrayPlotData)
returns_plot = Instance(Plot)

plot_type = Enum('line', 'scatter')

corr_renderer = Any()

x_min = Float()
x_max = Float()

traits_view = View(
                VGroup(
                    HGroup(spring, Label('Click point to select/unselect'), 
                        spring),
                    #Item('plot_type'),
                    Item('returns_plot', editor=ComponentEditor(size=size,
                                                        bgcolor=bg_color),
                         show_label=False),
                    #Item('num_medicion', width=-225),
                    orientation = "vertical"),
                resizable=True, title=title
                )

def _create_returns_plot(self):
    plot = Plot(self.plotdata)
    plot.legend.visible = True
    plot.x_axis = None
    x_axis = PlotAxis(plot, orientation="bottom") 
    plot.overlays.append(x_axis)

    renderer = plot.plot(("index", "value"), type="scatter",name = "Mediciones")[0]

    #Agrego todas las tools necesarias
    renderer.tools.append(ScatterInspector(renderer, selection_mode="toggle", persistent_hover=False))
    renderer.overlays.append(
            ScatterInspectorOverlay(renderer,
                hover_color = "transparent",
                hover_marker_size = 10,
                hover_outline_color = "purple",
                hover_line_width = 2,
                selection_marker_size = 8,
                selection_color = "red")
            )

    renderer.tools.append(RangeSelection(renderer, left_button_selects = False, disable_left_mouse = True, \
                                        rigth_button_selects = True, \
                                        auto_handle_event = False, metadata_name = "annotations"))
    renderer.overlays.append(RangeSelectionOverlay(component=renderer, metadata_name = "annotations"))

    renderer.tools.append(PanTool(renderer))
    renderer.overlays.append(ZoomTool(renderer, drag_button="right"))

    self.index_datasource = renderer.index
    self.index_datasource.on_trait_change(self._selections_changed, "metadata_changed")                                     
    self.returns_plot = plot

def _create_data(self):
    #genero los datos, más adelante los voy a leer con pandas
    npts = 40
    x_max = 10
    x = np.random.random(npts)
    x = x * x_max
    error = np.random.random(npts)
    y = 2 + 3*x + 5*error

    #Esta parte es para ordenar los elementos
    x_ordenado = np.array([])
    y_ordenado = np.array([])
    orden = range(x.size)
    nuevo_orden = np.array([])

    for i in range(x.size):
        arg_min = x.argmin()
        x_ordenado = np.append(x_ordenado, x[arg_min])
        y_ordenado = np.append(y_ordenado, y[arg_min])
        nuevo_orden = np.append(nuevo_orden, orden[arg_min])
        x = np.delete(x, arg_min)
        y = np.delete(y, arg_min)
        orden = np.delete(orden, arg_min)

    self.x_ordenado = x_ordenado
    self.y_ordenado = y_ordenado

    #Genero el retorno para el plot
    plotdata = ArrayPlotData()
    plotdata.set_data("index", x_ordenado)
    plotdata.set_data("value", y_ordenado)

    self.plotdata = plotdata


def _selections_changed(self):

    #Obtengo los puntos marcados manualmente
    self.posicion_puntos_selec = self.index_datasource.metadata.get('selections', ())
    #obtengo los puntos que marque con el rectangulo
    seleccionado_range = self.index_datasource.metadata.get('annotations', ())
    #Cuando desmarcon con el rectangu, el tipo de annotations es NoneType, 
    #con este if lo cambio a tuple
    type_range = type(self.index_datasource.metadata['annotations'])

    if type_range != tuple:
        self.index_datasource.metadata['annotations'] = []
    else:
        self.x_min, self.x_max = seleccionado_range

@on_trait_change("posicion_puntos_selec, x_min, x_max")
def _perform_calculations(self):
    plot = self.returns_plot
    x_nuevo = np.append(self.x_calcular, [11, 12])
    y_nuevo = np.append(self.y_calcular, [11, 12])
    self.corr_renderer = plot.plot((x_nuevo, y_nuevo),
                            type="scatter", color="blue")[0]

    plot.request_redraw()
4

1 回答 1

4

要更新现有绘图的数据,最好和最简单的方法是更新正在显示的现有绘图实例的现有 ArrayPlotData。Chaco 内部有监听器负责重绘。下面是一个受您的代码启发的示例:

from traits.api import HasTraits, Enum, Instance, Button
from traitsui.api import View, Item, VGroup
from enable.api import ComponentEditor
from chaco.api import Plot, ArrayPlotData, PlotAxis

from numpy import arange

class PlotApp(HasTraits):

    plotdata = Instance(ArrayPlotData)
    returns_plot = Instance(Plot)

    plot_type = Enum('line', 'scatter')

    add_points = Button

    traits_view = View(
                VGroup(Item("add_points"),
                    Item('returns_plot', editor=ComponentEditor(),
                        show_label=False),
                    orientation = "vertical"),
                resizable=True, title="Test"
                )

    def _returns_plot_default(self):
        self.plotdata = ArrayPlotData(index=arange(100), value=arange(100))
        plot = Plot(self.plotdata)
        plot.legend.visible = True
        plot.x_axis = None
        x_axis = PlotAxis(plot, orientation="bottom")
        plot.overlays.append(x_axis)

        plot.plot(("index", "value"), type="scatter", name = "Mediciones")
        return plot

    def _add_points_fired(self):
        current_length = len(self.plotdata["index"])
        self.plotdata.set_data("index", arange(current_length+1))
        self.plotdata.set_data("value", arange(current_length+1))

if __name__ == "__main__":
    app = PlotApp()
    app.configure_traits()

HTH,乔纳森

于 2013-08-21T04:18:37.673 回答