Skip to content

Instantly share code, notes, and snippets.

@scott-maddox
Created July 25, 2019 16:47
Show Gist options
  • Save scott-maddox/2f1103b474c9dcb1a539c65b6d6d8cd6 to your computer and use it in GitHub Desktop.
Save scott-maddox/2f1103b474c9dcb1a539c65b6d6d8cd6 to your computer and use it in GitHub Desktop.
chaco line plots with line labels on hover
from numpy import array, inf, linspace
from scipy.special import jn
from chaco.api import ArrayDataSource, ArrayPlotData, DataLabel, Plot
from chaco.tools.api import SimpleInspectorTool
from enable.api import BaseTool, ComponentEditor
from traits.api import HasTraits, Instance, on_trait_change
from traitsui.api import Item, View
class HoverLinePlots(HasTraits):
inspector = Instance(SimpleInspectorTool)
label = Instance(DataLabel)
plot = Instance(Plot)
@on_trait_change('inspector:new_value')
def handle_inspection(self, value):
point = self.inspector.last_mouse_position
if point:
# run through all the plots in the Plot and find closest within threshhold
best = None
best_distance = inf
# inspector is attached to Plot, so we need to adjust screen coords
# to take into account padding
adjusted_point = (
point[0] - self.plot.padding[0],
point[1] - self.plot.padding[1]
)
for name, plots in self.plot.plots.items():
for renderer in plots:
result = renderer.hittest(adjusted_point, return_distance=True)
if result is not None and result[-1] < best_distance:
best = name
best_distance = result[-1]
# adjust label text and position (or hide if nothing)
if best is not None:
self.label.label_text = best
self.label.data_point = array([value['x'], value['y']])
self.label.visible = True
else:
self.label.visible = False
self.label.invalidate_and_redraw()
def __init__(self, **traits):
super(HoverLinePlots, self).__init__(**traits)
self.init()
def init(self):
""" Set up the plot inspector and label. """
x = linspace(0.0, 10.0, 100)
data = ArrayPlotData(
x=ArrayDataSource(x, 'ascending'),
)
for i in range(10):
data.set_data('j{}'.format(i), jn(x, i))
self.plot = Plot(data)
for i in range(10):
y_name = 'j{}'.format(i)
self.plot.plot(('x', y_name), name=y_name, color='auto')
self.inspector = SimpleInspectorTool(self.plot)
self.plot.tools.append(self.inspector)
self.label = DataLabel(
self.plot,
visible=False,
label_style='bubble',
corner_radius=5,
marker_visible=False,
show_label_coords=False,
border_width=0,
bgcolor=(0.5, 0.5, 0.5, 0.5),
)
self.plot.overlays.append(self.label)
traits_view = View(
Item('plot', show_label=False, editor=ComponentEditor()),
resizable=True,
)
if __name__ == '__main__':
hpl = HoverLinePlots()
hpl.configure_traits()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment