I need to add some points to an existent plot I do in chaco. I have tried with plot.request_redraw()
but it didn't work. What else can I do?
This is the piece of code:
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()
To update the data of an existing plot, the best and simplest is to update the existing ArrayPlotData of the existing Plot instance being displayed. There are listeners inside Chaco that will take care of the redraw. Below is an example inspired from your code:
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, Jonathan