Skip to content

Commit ac10737

Browse files
committed
TST: add tests for rotation by mpl_selector
1 parent 52f9749 commit ac10737

File tree

4 files changed

+175
-13
lines changed

4 files changed

+175
-13
lines changed

regions/shapes/ellipse.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,8 @@ def as_mpl_selector(self, ax, active=True, sync=True, callback=None,
271271
you can enable/disable the selector at any point by calling
272272
``selector.set_active(True)`` or ``selector.set_active(False)``.
273273
"""
274+
from matplotlib import __version__ as MPL_VER_STR # noqa: N812
274275
from matplotlib.widgets import EllipseSelector
275-
from matplotlib import __version__ as MPL_VER_STR
276276

277277
if hasattr(self, '_mpl_selector'):
278278
raise AttributeError('Cannot attach more than one selector to a region.')

regions/shapes/rectangle.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,8 @@ def as_mpl_selector(self, ax, active=True, sync=True, callback=None,
267267
you can enable/disable the selector at any point by calling
268268
``selector.set_active(True)`` or ``selector.set_active(False)``.
269269
"""
270+
from matplotlib import __version__ as MPL_VER_STR # noqa: N812
270271
from matplotlib.widgets import RectangleSelector
271-
from matplotlib import __version__ as MPL_VER_STR
272272

273273
if hasattr(self, '_mpl_selector'):
274274
raise AttributeError('Cannot attach more than one selector to a region.')

regions/shapes/tests/test_ellipse.py

+86-4
Original file line numberDiff line numberDiff line change
@@ -114,8 +114,8 @@ def test_region_bbox_zero_size(self):
114114
def test_as_mpl_selector(self, sync):
115115

116116
plt = pytest.importorskip('matplotlib.pyplot')
117+
from matplotlib import __version_info__ as MPL_VERSION # noqa: N812
117118
from matplotlib.testing.widgets import do_event
118-
from matplotlib import __version_info__ as MPL_VERSION
119119

120120
rng = np.random.default_rng(0)
121121
data = rng.random((16, 16))
@@ -173,8 +173,8 @@ def test_mpl_selector_drag(self, anywhere, rotate):
173173
Test dragging of entire region from central handle and anywhere.
174174
"""
175175
plt = pytest.importorskip('matplotlib.pyplot')
176+
from matplotlib import __version_info__ as MPL_VERSION # noqa: N812
176177
from matplotlib.testing.widgets import do_event
177-
from matplotlib import __version_info__ as MPL_VERSION
178178

179179
if rotate != 0 and MPL_VERSION < (3, 6, 0):
180180
pytest.xfail('Creating selectors for rotated shapes is not yet supported')
@@ -234,8 +234,8 @@ def test_mpl_selector_resize(self):
234234
Test resizing of region on edge and corner handles.
235235
"""
236236
plt = pytest.importorskip('matplotlib.pyplot')
237-
from matplotlib.testing.widgets import (
238-
do_event) # click_and_drag # MPL_VERSION >= 36
237+
# if MPL_VERSION >= 36:
238+
from matplotlib.testing.widgets import do_event # click_and_drag
239239

240240
rng = np.random.default_rng(0)
241241
data = rng.random((16, 16))
@@ -274,6 +274,88 @@ def update_mask(reg):
274274

275275
assert_equal(mask, region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape))
276276

277+
def test_mpl_selector_rotate(self):
278+
"""
279+
Test rotating region on corner handles and by setting angle.
280+
"""
281+
plt = pytest.importorskip('matplotlib.pyplot')
282+
from matplotlib.testing.widgets import do_event # click_and_drag
283+
284+
rng = np.random.default_rng(0)
285+
data = rng.random((16, 16))
286+
mask = np.zeros_like(data)
287+
288+
ax = plt.subplot(1, 1, 1)
289+
ax.imshow(data)
290+
291+
def update_mask(reg):
292+
mask[:] = reg.to_mask(mode='subpixels', subpixels=10).to_image(data.shape)
293+
294+
region = self.reg.copy(angle=0 * u.deg)
295+
selector = region.as_mpl_selector(ax, callback=update_mask)
296+
297+
# Need rotation implementation from matplotlib#26833, hopefully to change once released
298+
if not hasattr(selector, '_geometry_state'):
299+
pytest.xfail('Rotating selectors is not yet supported')
300+
301+
assert region._mpl_selector.drag_from_anywhere is False
302+
assert_allclose(region.center.xy, (3.0, 4.0), atol=1e-12, rtol=0)
303+
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
304+
assert_quantity_allclose(region.angle, 0 * u.deg)
305+
assert_allclose(region._mpl_selector.rotation, 0.0, atol=1e-12)
306+
assert_allclose(region._mpl_selector.edge_centers,
307+
(np.array([1, 3, 5, 3]), np.array([4, 2.5, 4, 5.5])),
308+
atol=0.01)
309+
assert_allclose(region.bounding_box.extent, (0.5, 5.5, 2.5, 5.5), atol=1e-12, rtol=0)
310+
311+
# Rotate counter-clockwise using top-right bounding box corner
312+
# click_and_drag(selector, start=(5, 5.5), end=(4.0, 6.0), key='r')
313+
do_event(selector, 'on_key_press', key='r')
314+
do_event(selector, 'press', xdata=5, ydata=5.5, button=1)
315+
do_event(selector, 'onmove', xdata=4, ydata=6, button=1)
316+
do_event(selector, 'release', xdata=4, ydata=6, button=1)
317+
do_event(selector, 'on_key_press', key='r')
318+
319+
ax.figure.canvas.draw()
320+
321+
assert_allclose(region.center.xy, (3.0, 4.0), atol=1e-12, rtol=0)
322+
assert_allclose(region._mpl_selector.edge_centers,
323+
(np.array([1.21, 3.67, 4.79, 2.33]), np.array([3.11, 2.66, 4.89, 5.34])),
324+
atol=0.02)
325+
assert_allclose(region._mpl_selector.rotation, -26.56, atol=0.01)
326+
assert_quantity_allclose(region.angle, 26.56 * u.deg, rtol=0.001)
327+
assert_allclose((region.width, region.height), (4.0, 3.0), atol=1e-2, rtol=0)
328+
assert_allclose(region.bounding_box.extent, (0.5, 5.5, 1.5, 6.5), atol=1e-2, rtol=0)
329+
330+
assert_equal(mask, region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape))
331+
332+
# click_and_drag(selector, start=(3, 4), end=(7, 6)) # (shift center +3|+2)
333+
do_event(selector, 'press', xdata=3, ydata=4, button=1)
334+
do_event(selector, 'onmove', xdata=6, ydata=6, button=1)
335+
do_event(selector, 'release', xdata=6, ydata=6, button=1)
336+
337+
ax.figure.canvas.draw()
338+
339+
assert_allclose(region.center.xy, (6, 6), atol=1e-2, rtol=0)
340+
assert_allclose((region.width, region.height), (4.0, 3.0), atol=1e-2, rtol=0)
341+
assert_allclose(region._mpl_selector.rotation, -26.56, atol=0.01)
342+
assert_quantity_allclose(region.angle, 26.56 * u.deg, rtol=0.001)
343+
assert_allclose(region.bounding_box.extent, (3.5, 8.5, 3.5, 8.5), atol=1e-2, rtol=0)
344+
345+
assert_equal(mask, region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape))
346+
347+
# and de-rotate shifted ellipse
348+
region._mpl_selector.rotation = 0.0
349+
region._update_from_mpl_selector()
350+
351+
assert_allclose(region.center.xy, (6, 6), atol=1e-2, rtol=0)
352+
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
353+
assert_quantity_allclose(region.angle, 0 * u.deg, atol=1e-12 * u.deg)
354+
assert_allclose(region._mpl_selector.rotation, 0.0, atol=1e-12)
355+
assert_allclose(region.bounding_box.extent, (3.5, 8.5, 3.5, 7.5), atol=1e-2, rtol=0)
356+
357+
assert_equal(mask, region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape))
358+
277359
@pytest.mark.parametrize('userargs',
278360
({'useblit': True},
279361
{'grab_range': 20, 'minspanx': 5, 'minspany': 4},

regions/shapes/tests/test_rectangle.py

+87-7
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ def test_eq(self):
120120
@pytest.mark.parametrize('sync', (False,))
121121
def test_as_mpl_selector(self, sync):
122122
plt = pytest.importorskip('matplotlib.pyplot')
123+
from matplotlib import __version_info__ as MPL_VERSION # noqa: N812
123124
from matplotlib.testing.widgets import do_event
124-
from matplotlib import __version_info__ as MPL_VERSION
125125

126126
rng = np.random.default_rng(0)
127127
data = rng.random((16, 16))
@@ -180,8 +180,9 @@ def test_mpl_selector_drag(self, anywhere, rotate):
180180
Test dragging of entire region from central handle and anywhere.
181181
"""
182182
plt = pytest.importorskip('matplotlib.pyplot')
183-
from matplotlib.testing.widgets import do_event # click_and_drag # MPL_VERSION >= 36
184-
from matplotlib import __version_info__ as MPL_VERSION
183+
from matplotlib import __version_info__ as MPL_VERSION # noqa: N812
184+
# if MPL_VERSION >= 36:
185+
from matplotlib.testing.widgets import do_event # click_and_drag
185186

186187
if rotate != 0 and MPL_VERSION < (3, 6, 0):
187188
pytest.xfail('Creating selectors for rotated shapes is not yet supported')
@@ -220,9 +221,9 @@ def update_mask(reg):
220221
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
221222

222223
# click_and_drag from outside centre handle, but inside region
223-
do_event(selector, 'press', xdata=3.0, ydata=5.0, button=1)
224-
do_event(selector, 'onmove', xdata=4.0, ydata=7.0, button=1)
225-
do_event(selector, 'release', xdata=4.0, ydata=7.0, button=1)
224+
do_event(selector, 'press', xdata=2.0, ydata=5.0, button=1)
225+
do_event(selector, 'onmove', xdata=3.0, ydata=7.0, button=1)
226+
do_event(selector, 'release', xdata=3.0, ydata=7.0, button=1)
226227

227228
ax.figure.canvas.draw()
228229

@@ -231,7 +232,7 @@ def update_mask(reg):
231232
assert_allclose(region.center.xy, (4.5, 6.5), atol=1e-12, rtol=0)
232233
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
233234
else:
234-
assert_allclose(region.center.xy, (3.5, 6.0), atol=1e-12, rtol=0)
235+
assert_allclose(region.center.xy, (2.5, 6.0), atol=1e-12, rtol=0)
235236
assert_allclose((region.width, region.height), (1, 2), atol=1e-12, rtol=0)
236237

237238
assert_equal(mask, region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape))
@@ -280,6 +281,85 @@ def update_mask(reg):
280281

281282
assert_equal(mask, region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape))
282283

284+
def test_mpl_selector_rotate(self):
285+
"""
286+
Test rotating region on corner handles and by setting angle.
287+
"""
288+
plt = pytest.importorskip('matplotlib.pyplot')
289+
from matplotlib.testing.widgets import do_event
290+
291+
rng = np.random.default_rng(0)
292+
data = rng.random((16, 16))
293+
mask = np.zeros_like(data)
294+
295+
ax = plt.subplot(1, 1, 1)
296+
ax.imshow(data)
297+
298+
def update_mask(reg):
299+
mask[:] = reg.to_mask(mode='subpixels', subpixels=10).to_image(data.shape)
300+
301+
region = self.reg.copy(angle=0 * u.deg)
302+
selector = region.as_mpl_selector(ax, callback=update_mask)
303+
304+
# Need rotation implementation from matplotlib#26833, hopefully to change once released
305+
if not hasattr(selector, '_geometry_state'):
306+
pytest.xfail('Rotating selectors is not yet supported')
307+
308+
assert region._mpl_selector.drag_from_anywhere is False
309+
assert_allclose(region.center.xy, (3.0, 4.0), atol=1e-12, rtol=0)
310+
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
311+
assert_quantity_allclose(region.angle, 0 * u.deg)
312+
assert_allclose(region._mpl_selector.rotation, 0.0, atol=1e-12)
313+
assert_allclose(region.corners, [(1, 2.5), (5, 2.5), (5, 5.5), (1, 5.5)],
314+
atol=1e-12, rtol=0)
315+
316+
# Rotate counter-clockwise using top-right corner
317+
do_event(selector, 'on_key_press', key='r')
318+
do_event(selector, 'press', xdata=5, ydata=5.5, button=1)
319+
do_event(selector, 'onmove', xdata=4, ydata=6, button=1)
320+
do_event(selector, 'release', xdata=4, ydata=6, button=1)
321+
do_event(selector, 'on_key_press', key='r')
322+
323+
ax.figure.canvas.draw()
324+
325+
assert_allclose(region.center.xy, (3.0, 4.0), atol=1e-12, rtol=0)
326+
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
327+
assert_allclose(region._mpl_selector.rotation, -26.56, atol=0.01)
328+
assert_quantity_allclose(region.angle, 26.56 * u.deg, rtol=0.001)
329+
assert_allclose(region.corners, [(1.88, 1.76), (5.46, 3.55), (4.12, 6.24), (0.54, 4.45)],
330+
atol=1e-2, rtol=0)
331+
332+
assert_equal(mask, region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape))
333+
334+
# click_and_drag(selector, start=(3, 4), end=(7, 6)) # (shift center +3|+2)
335+
do_event(selector, 'press', xdata=3, ydata=4, button=1)
336+
do_event(selector, 'onmove', xdata=6, ydata=6, button=1)
337+
do_event(selector, 'release', xdata=6, ydata=6, button=1)
338+
339+
ax.figure.canvas.draw()
340+
341+
assert_allclose(region.center.xy, (6, 6), atol=1e-12, rtol=0)
342+
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
343+
assert_allclose(region._mpl_selector.rotation, -26.56, atol=0.01)
344+
assert_quantity_allclose(region.angle, 26.56 * u.deg, rtol=0.001)
345+
assert_allclose(region.corners, [(4.88, 3.76), (8.46, 5.55), (7.12, 8.24), (3.54, 6.45)],
346+
atol=1e-2, rtol=0)
347+
348+
assert_equal(mask, region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape))
349+
350+
# and de-rotate shifted rectangle
351+
region._mpl_selector.rotation = 0.0
352+
region._update_from_mpl_selector()
353+
354+
assert_allclose(region.center.xy, (6, 6), atol=1e-2, rtol=0)
355+
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
356+
assert_quantity_allclose(region.angle, 0 * u.deg, atol=1e-12 * u.deg)
357+
assert_allclose(region._mpl_selector.rotation, 0.0, atol=1e-12)
358+
assert_allclose(region.corners, [(4, 4.5), (8, 4.5), (8, 7.5), (4, 7.5)],
359+
atol=1e-12, rtol=0)
360+
361+
assert_equal(mask, region.to_mask(mode='subpixels', subpixels=10).to_image(data.shape))
362+
283363
@pytest.mark.parametrize('userargs',
284364
({'useblit': True},
285365
{'grab_range': 20, 'minspanx': 5, 'minspany': 4},

0 commit comments

Comments
 (0)