1
"""Simple Inspector tool for plots
3
This module provides a simple tool that reports the data-space coordinates of
4
the current mouse cursor position in a plot. It is intended for use with
5
SimpleInspectorOverlay, but other objects can potentially hook into its API.
8
from enthought.chaco.image_plot import ImagePlot
9
from enthought.enable.api import BaseTool, KeySpec
10
from enthought.traits.api import Bool, Event, Tuple, Enum, Callable
12
class SimpleInspectorTool(BaseTool):
13
""" Simple inspector tool for plots
15
This is a simple tool that reports the data-space coordinates of the
16
current mouse cursor position in a plot.
18
Interested overlays and other objects can listen for new_value events,
19
which is a dictionary of data about the current location in data space,
20
and can look at the last_mouse_position trait which holds the mouse
21
position in screen space.
23
The tool also provides a visible trait which listeners can use to hide
24
themselves. By default the 'p' key toggles this.
26
Instances can provide a value_generator function that performs computations
27
to generate additional values in the dictionary that is passed to the
28
new_value event. Subclasses can override gather_values() to similar
32
# This event fires whenever the mouse moves over a new image point.
33
# Its value is a dict with default keys "x", "y", "index" and "value".
36
# Indicates whether overlays listening to this tool should be visible.
39
# Stores the last mouse position. This can be used by overlays to
40
# position themselves around the mouse.
41
last_mouse_position = Tuple
43
# This key will show and hide any overlays listening to this tool.
44
inspector_key = KeySpec('p')
46
# A callable that computes other values for the new_value event
47
# this takes a dictionary as an argument, and returns a dictionary
48
value_generator = Callable
50
# Private Trails ########################################################
52
# Stores the value of self.visible when the mouse leaves the tool,
53
# so that it can be restored when the mouse enters again.
54
_old_visible = Enum(None, True, False) #Trait(None, Bool(True))
56
#########################################################################
57
# SimpleInspectorTool API
58
#########################################################################
60
def gather_values(self, event):
61
""" Generate the values for the new_value dictionary.
63
By default this returns a dictionary with keys "x", "y", "index" and
64
"value". If there is a value_generator callable, this will be called
65
to modify the dictionary.
78
x, y, index, value = self.map_to_data(event.x, event.y)
79
d = {'index': index, 'value': value, 'x': x, 'y': y}
81
if isinstance(self.component, ImagePlot):
82
x_ndx, y_ndx = self.component.map_index((event.x, event.y),
83
outside_returns_none=False)
85
# FIXME: off-by-one error. The size of the index is +1 to the size of
87
if y_ndx == self.component.value.data.shape[0]:
89
if x_ndx == self.component.value.data.shape[1]:
92
z = self.component.value.data[y_ndx, x_ndx]
96
if self.value_generator is not None:
97
d = self.value_generator(d)
100
def map_to_data(self, x, y):
101
""" Returns the data space coordinates of the given x and y.
103
Takes into account orientation of the plot and the axis setting.
106
plot = self.component
107
if plot.orientation == "h":
108
index = x = plot.x_mapper.map_data(x)
109
value = y = plot.y_mapper.map_data(y)
111
index = y = plot.y_mapper.map_data(y)
112
value = x = plot.x_mapper.map_data(x)
113
return x, y, index, value
115
#########################################################################
117
#########################################################################
119
def normal_key_pressed(self, event):
120
if self.inspector_key.match(event):
121
self.visible = not self.visible
123
def normal_mouse_leave(self, event):
124
if self._old_visible is None:
125
self._old_visible = self.visible
128
def normal_mouse_enter(self, event):
129
if self._old_visible is not None:
130
self.visible = self._old_visible
131
self._old_visible = None
133
def normal_mouse_move(self, event):
134
plot = self.component
136
self.new_value = self.gather_values(event)
137
self.last_mouse_position = (event.x, event.y)