Skip to content

Commit

Permalink
Merge pull request #3222 from ericpre/fix_resizers
Browse files Browse the repository at this point in the history
Fix resizers
  • Loading branch information
jlaehne committed Sep 2, 2023
2 parents 04388a4 + 50b0dec commit c9a3881
Show file tree
Hide file tree
Showing 9 changed files with 90 additions and 10 deletions.
13 changes: 8 additions & 5 deletions hyperspy/drawing/widget.py
Expand Up @@ -323,7 +323,7 @@ class DraggableWidgetBase(WidgetBase):

def __init__(self, axes_manager, **kwargs):
super(DraggableWidgetBase, self).__init__(axes_manager, **kwargs)
self.is_pointer=False
self.is_pointer = False
self.events.moved = Event(doc="""
Event that triggers when the widget was moved.
Expand Down Expand Up @@ -831,7 +831,7 @@ def _update_patch_geometry(self):
self.draw_patch()


class ResizersMixin(object):
class ResizersMixin:
"""
Widget mix-in for adding resizing manipulation handles.
Expand Down Expand Up @@ -901,7 +901,9 @@ def _set_resizers(self, value, ax):
r.set_animated(self.blit)
else:
for r in self._resizer_handles:
r.remove()
# check that the matplotlib patch is present before removing it
if r in ax.get_children():
r.remove()
self._resizers_on = value

def _get_resizer_size(self):
Expand Down Expand Up @@ -977,7 +979,8 @@ def set_on(self, value):
super(ResizersMixin, self).set_on(value)

def onpick(self, event):
"""Picking of main patch is same as for widget base, but this also
"""
Picking of main patch is same as for widget base, but this also
handles picking of the resize handles. If a resize handle is picked,
`picked` is set to `True`, and `resizer_picked` is set to an integer
indicating which handle was picked (0-3 for top left, top right, bottom
Expand Down Expand Up @@ -1009,7 +1012,7 @@ def _add_patch_to(self, ax):
"""Same as widget base, but also adds resizers if 'resizers' property
is True.
"""
if self.resizers:
if self.resizers and self._resizers_on:
self._set_resizers(True, ax)
if hasattr(super(ResizersMixin, self), '_add_patch_to'):
super(ResizersMixin, self)._add_patch_to(ax)
3 changes: 2 additions & 1 deletion hyperspy/misc/test_utils.py
Expand Up @@ -125,7 +125,7 @@ def check_running_tests_in_CI():
def mock_event(fig, canvas,
button=None, key=None,
xdata=None, ydata=None,
inaxes=True, artist=None):
inaxes=True, artist=None, mouseevent=None):
event = mock.Mock()
event.button = button
event.key = key
Expand All @@ -136,4 +136,5 @@ def mock_event(fig, canvas,
event.guiEvent = None
event.name = 'MockEvent'
event.artist = artist
event.mouseevent = mouseevent
return event
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified hyperspy/tests/drawing/plot_roi/test_plot_circle_roi_signal.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 1 addition & 2 deletions hyperspy/tests/drawing/test_plot_widgets.py
Expand Up @@ -479,7 +479,7 @@ def count_calls(obj):
assert count_calls.counter == 5
assert im.axes_manager.navigation_axes[0].index == 5

def test_drag_continuous_update1d(self):
def test_drag_continuous_update1d_no_change(self):
# drag down and check that it doesn't change the index
im = Signal2D(np.arange(10 * 10 * 10).reshape((10, 10, 10)))
im.axes_manager[0].scale = 1
Expand Down Expand Up @@ -517,4 +517,3 @@ def count_calls(obj):
assert count_calls.counter == 0
assert im.axes_manager.navigation_axes[0].index == 0
# drag down and check that it doesn't change

80 changes: 78 additions & 2 deletions hyperspy/tests/drawing/test_widget.py
Expand Up @@ -15,10 +15,12 @@
# You should have received a copy of the GNU General Public License
# along with HyperSpy. If not, see <https://www.gnu.org/licenses/#GPL>.

from matplotlib.backend_bases import MouseEvent, PickEvent
import numpy as np

from hyperspy.drawing import widget, widgets
from hyperspy import signals
from hyperspy import signals, roi
from hyperspy.misc.test_utils import mock_event


def test_get_step():
Expand Down Expand Up @@ -68,9 +70,83 @@ def test_remove_widget_line():
assert len(ax.lines) == 1
assert len(im._plot.pointer.patch) == 1


def test_calculate_size():
s = signals.Signal2D(np.arange(10000).reshape(10,10,10,10))

#Test that scalebar.calculate_size passes only positive value to closest_nice_number
s.axes_manager[0].scale = -1
s.plot()
s.plot()


def test_adding_removing_resizers_on_pick_event():
"""
Test adding and removing resizers on pick events
"""
s = signals.Signal2D(np.random.random((10, 10)))

xx2, yy2, xx1, yy1 = 0, 0, 2, 2

shiftx = 5
shifty = 3

rect_roi0 = roi.RectangularROI(xx2, yy2, xx1, yy1)
rect_roi1 = roi.RectangularROI(xx2 + shiftx , yy2 + shifty, xx1 + shiftx, yy1 + shifty)
s.plot()

_ = rect_roi0.interactive(s)
_ = rect_roi1.interactive(s)
widget0 = list(rect_roi0.widgets)[0]
widget1 = list(rect_roi1.widgets)[0]

assert not widget0.picked
assert not widget1.picked

fig = s._plot.signal_plot.figure

# PickEvent on widget0
mouseevent0 = mock_event(fig, fig.canvas, xdata=1, ydata=1, artist=widget0.patch[0])
pickevent0 = mock_event(fig, fig.canvas, artist=widget0.patch[0], mouseevent=mouseevent0)

# PickEvent on widget1
mouseevent1 = mock_event(fig, fig.canvas, xdata=6, ydata=4, artist=widget1.patch[0])
pickevent1 = mock_event(fig, fig.canvas, artist=widget1.patch[0], mouseevent=mouseevent1)

# PickEvent outside widget0 and widget1
mouseevent2 = mock_event(fig, fig.canvas, xdata=8, ydata=8)
pickevent2 = mock_event(fig, fig.canvas, mouseevent=mouseevent2)

widget0.onpick(pickevent0)
widget1.onpick(pickevent0)
assert widget0.picked
assert widget0._resizers_on
assert not widget1.picked
assert not widget1._resizers_on

widget0.onpick(pickevent2)
widget1.onpick(pickevent2)
assert not widget0.picked
assert not widget0._resizers_on
assert not widget1.picked
assert not widget1._resizers_on

widget0.onpick(pickevent1)
widget1.onpick(pickevent1)
assert not widget0.picked
assert not widget0._resizers_on
assert widget1.picked
assert widget1._resizers_on

widget0.onpick(pickevent0)
widget1.onpick(pickevent0)
assert widget0.picked
assert widget0._resizers_on
assert not widget1.picked
assert not widget1._resizers_on

widget0.onpick(pickevent2)
widget1.onpick(pickevent2)
assert not widget0.picked
assert not widget0._resizers_on
assert not widget1.picked
assert not widget1._resizers_on
1 change: 1 addition & 0 deletions upcoming_changes/3222.bugfix.rst
@@ -0,0 +1 @@
Fix harmless error message when using multiple RectangleROI: check if resizer patches are drawn before removing them. Don't display resizers when adding the widget to the figure (widget in unselected state) for consistency with unselected state

0 comments on commit c9a3881

Please sign in to comment.