Skip to content

Commit c473c1b

Browse files
committed
Merge pull request #3989 from blink1073/add-cursor-zdata
ENH: Allow Artists to show pixel data in cursor display
2 parents 2568ef2 + bac8dff commit c473c1b

File tree

5 files changed

+81
-8
lines changed

5 files changed

+81
-8
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Allow Artists to Display Pixel Data in Cursor
2+
---------------------------------------------
3+
4+
Adds `get_pixel_data` and `format_pixel_data` methods to artists
5+
which can be used to add zdata to the cursor display
6+
in the status bar. Also adds an implementation for Images.

lib/matplotlib/artist.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,22 @@ def matchfunc(x):
890890
artists.append(self)
891891
return artists
892892

893+
def get_cursor_data(self, event):
894+
"""
895+
Get the cursor data for a given event.
896+
"""
897+
return None
898+
899+
def format_cursor_data(self, data):
900+
"""
901+
Return *cursor data* string formatted.
902+
"""
903+
try:
904+
data[0]
905+
except (TypeError, IndexError):
906+
data = [data]
907+
return ', '.join('{:0.3g}'.format(item) for item in data)
908+
893909

894910
class ArtistInspector(object):
895911
"""

lib/matplotlib/backend_bases.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,15 +1706,9 @@ def onRemove(self, ev):
17061706
17071707
canvas.mpl_connect('mouse_press_event',canvas.onRemove)
17081708
"""
1709-
def sort_artists(artists):
1710-
# This depends on stable sort and artists returned
1711-
# from get_children in z order.
1712-
L = [(h.zorder, h) for h in artists]
1713-
L.sort()
1714-
return [h for zorder, h in L]
1715-
17161709
# Find the top artist under the cursor
1717-
under = sort_artists(self.figure.hitlist(ev))
1710+
under = self.figure.hitlist(ev)
1711+
under.sort(key=lambda x: x.zorder)
17181712
h = None
17191713
if under:
17201714
h = under[-1]
@@ -2814,6 +2808,16 @@ def mouse_move(self, event):
28142808
except (ValueError, OverflowError):
28152809
pass
28162810
else:
2811+
artists = event.inaxes.hitlist(event)
2812+
if event.inaxes.patch in artists:
2813+
artists.remove(event.inaxes.patch)
2814+
2815+
if artists:
2816+
artists.sort(key=lambda x: x.zorder)
2817+
a = artists[-1]
2818+
data = a.get_cursor_data(event)
2819+
if data is not None:
2820+
s += ' [%s]' % a.format_cursor_data(data)
28172821
if len(self.mode):
28182822
self.set_message('%s, %s' % (self.mode, s))
28192823
else:

lib/matplotlib/image.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,20 @@ def get_extent(self):
684684
else:
685685
return (-0.5, numcols-0.5, -0.5, numrows-0.5)
686686

687+
def get_cursor_data(self, event):
688+
"""Get the cursor data for a given event"""
689+
xmin, xmax, ymin, ymax = self.get_extent()
690+
if self.origin == 'upper':
691+
ymin, ymax = ymax, ymin
692+
arr = self.get_array()
693+
data_extent = mtransforms.Bbox([[ymin, xmin], [ymax, xmax]])
694+
array_extent = mtransforms.Bbox([[0, 0], arr.shape[:2]])
695+
trans = mtransforms. BboxTransform(boxin=data_extent,
696+
boxout=array_extent)
697+
y, x = event.ydata, event.xdata
698+
i, j = trans.transform_point([y, x]).astype(int)
699+
return arr[i, j]
700+
687701

688702
class NonUniformImage(AxesImage):
689703
def __init__(self, ax, **kwargs):

lib/matplotlib/tests/test_image.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,39 @@ def test_imsave_color_alpha():
158158

159159
assert_array_equal(data, arr_buf)
160160

161+
162+
@cleanup
163+
def test_cursor_data():
164+
from matplotlib.backend_bases import MouseEvent
165+
166+
fig, ax = plt.subplots()
167+
im = ax.imshow(np.arange(100).reshape(10, 10), origin='upper')
168+
169+
x, y = 4, 4
170+
xdisp, ydisp = ax.transData.transform_point([x, y])
171+
172+
event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
173+
assert im.get_cursor_data(event) == 44
174+
175+
ax.clear()
176+
im = ax.imshow(np.arange(100).reshape(10, 10), origin='lower')
177+
178+
x, y = 4, 4
179+
xdisp, ydisp = ax.transData.transform_point([x, y])
180+
181+
event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
182+
assert im.get_cursor_data(event) == 44
183+
184+
fig, ax = plt.subplots()
185+
im = ax.imshow(np.arange(100).reshape(10, 10), extent=[0, 0.5, 0, 0.5])
186+
187+
x, y = 0.25, 0.25
188+
xdisp, ydisp = ax.transData.transform_point([x, y])
189+
190+
event = MouseEvent('motion_notify_event', fig.canvas, xdisp, ydisp)
191+
assert im.get_cursor_data(event) == 55
192+
193+
161194
@image_comparison(baseline_images=['image_clip'])
162195
def test_image_clip():
163196
from math import pi

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy