Skip to content

Commit

Permalink
TST: add tests for rotation by mpl_selector
Browse files Browse the repository at this point in the history
  • Loading branch information
dhomeier committed Feb 5, 2025
1 parent 52f9749 commit ba13e10
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 9 deletions.
2 changes: 1 addition & 1 deletion regions/shapes/ellipse.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,8 +271,8 @@ def as_mpl_selector(self, ax, active=True, sync=True, callback=None,
you can enable/disable the selector at any point by calling
``selector.set_active(True)`` or ``selector.set_active(False)``.
"""
from matplotlib import __version__ as MPL_VER_STR # noqa: N812
from matplotlib.widgets import EllipseSelector
from matplotlib import __version__ as MPL_VER_STR

if hasattr(self, '_mpl_selector'):
raise AttributeError('Cannot attach more than one selector to a region.')
Expand Down
2 changes: 1 addition & 1 deletion regions/shapes/rectangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ def as_mpl_selector(self, ax, active=True, sync=True, callback=None,
you can enable/disable the selector at any point by calling
``selector.set_active(True)`` or ``selector.set_active(False)``.
"""
from matplotlib import __version__ as MPL_VER_STR # noqa: N812
from matplotlib.widgets import RectangleSelector
from matplotlib import __version__ as MPL_VER_STR

if hasattr(self, '_mpl_selector'):
raise AttributeError('Cannot attach more than one selector to a region.')
Expand Down
90 changes: 86 additions & 4 deletions regions/shapes/tests/test_ellipse.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ def test_region_bbox_zero_size(self):
def test_as_mpl_selector(self, sync):

plt = pytest.importorskip('matplotlib.pyplot')
from matplotlib import __version_info__ as MPL_VERSION # noqa: N812
from matplotlib.testing.widgets import do_event
from matplotlib import __version_info__ as MPL_VERSION

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

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

rng = np.random.default_rng(0)
data = rng.random((16, 16))
Expand Down Expand Up @@ -274,6 +274,88 @@ def update_mask(reg):

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

def test_mpl_selector_rotate(self):
"""
Test rotating region on corner handles and by setting angle.
"""
plt = pytest.importorskip('matplotlib.pyplot')
from matplotlib.testing.widgets import do_event # click_and_drag

rng = np.random.default_rng(0)
data = rng.random((16, 16))
mask = np.zeros_like(data)

ax = plt.subplot(1, 1, 1)
ax.imshow(data)

def update_mask(reg):
mask[:] = reg.to_mask(mode='subpixels', subpixels=10).to_image(data.shape)

region = self.reg.copy(angle=0 * u.deg)
selector = region.as_mpl_selector(ax, callback=update_mask)

# Need rotation implementation from matplotlib#26833, hopefully to change once released
if not hasattr(selector, '_geometry_state'):
pytest.xfail('Rotating selectors is not yet supported')

assert region._mpl_selector.drag_from_anywhere is False
assert_allclose(region.center.xy, (3.0, 4.0), atol=1e-12, rtol=0)
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
assert_quantity_allclose(region.angle, 0 * u.deg)
assert_allclose(region._mpl_selector.rotation, 0.0, atol=1e-12)
assert_allclose(region._mpl_selector.edge_centers,
(np.array([1, 3, 5, 3]), np.array([4, 2.5, 4, 5.5])),
atol=0.01)
assert_allclose(region.bounding_box.extent, (0.5, 5.5, 2.5, 5.5), atol=1e-12, rtol=0)

# Rotate counter-clockwise using top-right bounding box corner
# click_and_drag(selector, start=(5, 5.5), end=(4.0, 6.0), key='r')
do_event(selector, 'on_key_press', key='r')
do_event(selector, 'press', xdata=5, ydata=5.5, button=1)
do_event(selector, 'onmove', xdata=4, ydata=6, button=1)
do_event(selector, 'release', xdata=4, ydata=6, button=1)
do_event(selector, 'on_key_press', key='r')

ax.figure.canvas.draw()

assert_allclose(region.center.xy, (3.0, 4.0), atol=1e-12, rtol=0)
assert_allclose(region._mpl_selector.edge_centers,
(np.array([1.21, 3.67, 4.79, 2.33]), np.array([3.11, 2.66, 4.89, 5.34])),
atol=0.02)
assert_allclose(region._mpl_selector.rotation, -26.56, atol=0.01)
assert_quantity_allclose(region.angle, 26.56 * u.deg, rtol=0.001)
assert_allclose((region.width, region.height), (4.0, 3.0), atol=1e-2, rtol=0)
assert_allclose(region.bounding_box.extent, (0.5, 5.5, 1.5, 6.5), atol=1e-2, rtol=0)

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

# click_and_drag(selector, start=(3, 4), end=(7, 6)) # (shift center +3|+2)
do_event(selector, 'press', xdata=3, ydata=4, button=1)
do_event(selector, 'onmove', xdata=6, ydata=6, button=1)
do_event(selector, 'release', xdata=6, ydata=6, button=1)

ax.figure.canvas.draw()

assert_allclose(region.center.xy, (6, 6), atol=1e-2, rtol=0)
assert_allclose((region.width, region.height), (4.0, 3.0), atol=1e-2, rtol=0)
assert_allclose(region._mpl_selector.rotation, -26.56, atol=0.01)
assert_quantity_allclose(region.angle, 26.56 * u.deg, rtol=0.001)
assert_allclose(region.bounding_box.extent, (3.5, 8.5, 3.5, 8.5), atol=1e-2, rtol=0)

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

# and de-rotate shifted ellipse
region._mpl_selector.rotation = 0.0
region._update_from_mpl_selector()

assert_allclose(region.center.xy, (6, 6), atol=1e-2, rtol=0)
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
assert_quantity_allclose(region.angle, 0 * u.deg, atol=1e-12 * u.deg)
assert_allclose(region._mpl_selector.rotation, 0.0, atol=1e-12)
assert_allclose(region.bounding_box.extent, (3.5, 8.5, 3.5, 7.5), atol=1e-2, rtol=0)

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

@pytest.mark.parametrize('userargs',
({'useblit': True},
{'grab_range': 20, 'minspanx': 5, 'minspany': 4},
Expand Down
86 changes: 83 additions & 3 deletions regions/shapes/tests/test_rectangle.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ def test_eq(self):
@pytest.mark.parametrize('sync', (False,))
def test_as_mpl_selector(self, sync):
plt = pytest.importorskip('matplotlib.pyplot')
from matplotlib import __version_info__ as MPL_VERSION # noqa: N812
from matplotlib.testing.widgets import do_event
from matplotlib import __version_info__ as MPL_VERSION

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

if rotate != 0 and MPL_VERSION < (3, 6, 0):
pytest.xfail('Creating selectors for rotated shapes is not yet supported')
Expand Down Expand Up @@ -280,6 +281,85 @@ def update_mask(reg):

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

def test_mpl_selector_rotate(self):
"""
Test rotating region on corner handles and by setting angle.
"""
plt = pytest.importorskip('matplotlib.pyplot')
from matplotlib.testing.widgets import do_event

rng = np.random.default_rng(0)
data = rng.random((16, 16))
mask = np.zeros_like(data)

ax = plt.subplot(1, 1, 1)
ax.imshow(data)

def update_mask(reg):
mask[:] = reg.to_mask(mode='subpixels', subpixels=10).to_image(data.shape)

region = self.reg.copy(angle=0 * u.deg)
selector = region.as_mpl_selector(ax, callback=update_mask)

# Need rotation implementation from matplotlib#26833, hopefully to change once released
if not hasattr(selector, '_geometry_state'):
pytest.xfail('Rotating selectors is not yet supported')

assert region._mpl_selector.drag_from_anywhere is False
assert_allclose(region.center.xy, (3.0, 4.0), atol=1e-12, rtol=0)
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
assert_quantity_allclose(region.angle, 0 * u.deg)
assert_allclose(region._mpl_selector.rotation, 0.0, atol=1e-12)
assert_allclose(region.corners, [(1, 2.5), (5, 2.5), (5, 5.5), (1, 5.5)],
atol=1e-12, rtol=0)

# Rotate counter-clockwise using top-right corner
do_event(selector, 'on_key_press', key='r')
do_event(selector, 'press', xdata=5, ydata=5.5, button=1)
do_event(selector, 'onmove', xdata=4, ydata=6, button=1)
do_event(selector, 'release', xdata=4, ydata=6, button=1)
do_event(selector, 'on_key_press', key='r')

ax.figure.canvas.draw()

assert_allclose(region.center.xy, (3.0, 4.0), atol=1e-12, rtol=0)
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
assert_allclose(region._mpl_selector.rotation, -26.56, atol=0.01)
assert_quantity_allclose(region.angle, 26.56 * u.deg, rtol=0.001)
assert_allclose(region.corners, [(1.88, 1.76), (5.46, 3.55), (4.12, 6.24), (0.54, 4.45)],
atol=1e-2, rtol=0)

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

# click_and_drag(selector, start=(3, 4), end=(7, 6)) # (shift center +3|+2)
do_event(selector, 'press', xdata=3, ydata=4, button=1)
do_event(selector, 'onmove', xdata=6, ydata=6, button=1)
do_event(selector, 'release', xdata=6, ydata=6, button=1)

ax.figure.canvas.draw()

assert_allclose(region.center.xy, (6, 6), atol=1e-12, rtol=0)
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
assert_allclose(region._mpl_selector.rotation, -26.56, atol=0.01)
assert_quantity_allclose(region.angle, 26.56 * u.deg, rtol=0.001)
assert_allclose(region.corners, [(4.88, 3.76), (8.46, 5.55), (7.12, 8.24), (3.54, 6.45)],
atol=1e-2, rtol=0)

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

# and de-rotate shifted rectangle
region._mpl_selector.rotation = 0.0
region._update_from_mpl_selector()

assert_allclose(region.center.xy, (6, 6), atol=1e-2, rtol=0)
assert_allclose((region.width, region.height), (4, 3), atol=1e-12, rtol=0)
assert_quantity_allclose(region.angle, 0 * u.deg, atol=1e-12 * u.deg)
assert_allclose(region._mpl_selector.rotation, 0.0, atol=1e-12)
assert_allclose(region.corners, [(4, 4.5), (8, 4.5), (8, 7.5), (4, 7.5)],
atol=1e-12, rtol=0)

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

@pytest.mark.parametrize('userargs',
({'useblit': True},
{'grab_range': 20, 'minspanx': 5, 'minspany': 4},
Expand Down

0 comments on commit ba13e10

Please sign in to comment.