Making a Chaco highlight legend

Last week I posted an example of how to use an interactive Chaco tool to highlight selected plots, this week I’m providing a working example using it.

First we need to define the tool, which inherits from Enable’s BaseTool. We override the normal_mouse_move method, which is called every time the mouse moves when neither mouse button is down. The normal_mouse_move method performs a hit test on the legend, highlighting the selected lines and dimming the others.

[sourcecode language=python]
class HighlightLegend(BaseTool):
_selected_plot = Any
_selected_renderers = List

def _get_hit_plots(self, event):
legend=self.component
if legend is None or not legend.is_in(event.x, event.y):
return []

label = legend.get_label_at(event.x, event.y)
if label is None:
return []

index = legend._cached_labels.index(label)
label_name = legend._cached_label_names[index]
return legend.plots[label_name]

def normal_mouse_move(self, event):
new = set(self._get_hit_plots(event))
old = set(self._selected_renderers)

if old == new:
new = set()

# select the new ones:
for renderer in new – old:
self._select(renderer)

# deselect the old ones that are not new
for renderer in old – new:
self._deselect(renderer)

self._selected_renderers = list(new)

def _select(self, selected):
“”” Decorates a plot to indicate it is selected “””
for plot in reduce(operator.add, selected.container.plots.values()):
if plot != selected:
plot.alpha /= 3
else:
plot.line_width *= 2

plot.request_redraw()

def _deselect(self, selected):
for plot in reduce(operator.add, selected.container.plots.values()):
if plot != selected:
plot.alpha *= 3
else:
plot.line_width /= 2

plot.request_redraw()
[/sourcecode]

All that is left to do is attach the new tool to the legend. In this example a plot is created with 2 data series then the plot is made visible and hooked up to the new tool

[sourcecode language=python]
class MyPlot(HasTraits):
plot = Instance(Plot)

traits_view = View(Item(‘plot’, editor=ComponentEditor()))

def __init__(self, index, series1, series2, **kw):
super(MyPlot, self).__init__(**kw)

plot_data = ArrayPlotData(index=index)
plot_data.set_data(‘series1’, series1)
plot_data.set_data(‘series2’, series2)
self.plot = Plot(plot_data)
self.plot.plot((‘index’, ‘series1’))
self.plot.plot((‘index’, ‘series2’))

self.plot.legend.visible = True
self.plot.legend.tools.append(HighlightLegend(self.plot.legend))
[/sourcecode]

By popular demand, here are two screenshots, one without any highlighting, and another with one series highlighted:
not highlighed
highlighted

5 thoughts on “Making a Chaco highlight legend

  1. avatarJason Jacobs

    Very nice. I implemented selection and highlighting in my own Chaco app, but not as elegantly and the legend based selector was still on the “to-do” list.

    Do other plot types (scatter, bar) have the alpha property? Would your approach work for those types as well?

    Reply
  2. avatarbryce

    I added support for changing alpha values in subclasses of BaseXYPlot, which are ScatterPlot, LinePlot, and PolygonPlot. Support can be added easily for other plot types, I only addressed the ones that met my needs.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

Please leave these two fields as-is:

Protected by Invisible Defender. Showed 403 to 101,046 bad guys.