Making a Chaco highlight legend

Oct 10 2008 Published by Bryce Hendrix under Chaco, Enthought Tool Suite

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.

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

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

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

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

5 responses so far

Leave a Reply

Featuring Advanced Search Functions plugin by YD