From eef3fcdd803d6e32c138ad4a64643fc3e7cfd697 Mon Sep 17 00:00:00 2001 From: Alex Sauer Date: Wed, 15 May 2024 23:33:30 +0100 Subject: [PATCH 1/2] Interactive cropping This commit addresses issue #42. The user can click with the left mouse to set the top right corner of the crop and a right click sets the bottom right corner --- docs/crop.ipynb | 3 ++- stackview/_crop.py | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/docs/crop.ipynb b/docs/crop.ipynb index ddbefb4..2083743 100644 --- a/docs/crop.ipynb +++ b/docs/crop.ipynb @@ -37,7 +37,8 @@ "id": "deec8f67-28d2-4823-9f0e-f98feb8c8f3c", "metadata": {}, "source": [ - "The widget contains 2 or 3 sliders, for 2D and 3D images respectively. It also supports `stackview`'s typical parameters such as `continuous_update`, `zoom_factor`, etc." + "The widget contains 2 or 3 sliders, for 2D and 3D images respectively. It also supports `stackview`'s typical parameters such as `continuous_update`, `zoom_factor`, etc.\n", + "The crop can either be selected via the sliders or with two mouse clicks (left click for top left corner, right lick for bottom right corner of the cropped rectangle)." ] }, { diff --git a/stackview/_crop.py b/stackview/_crop.py index a01121d..5160fa6 100644 --- a/stackview/_crop.py +++ b/stackview/_crop.py @@ -131,6 +131,47 @@ def __init__(self, if len(image.shape) > 2: widgets.append(slice_slider) + from ipyevents import Event + + event_handler_top_left = Event(source=view, watched_events=["click"]) + event_handler_bottom_right = Event(source=view, watched_events=["auxclick"]) + + def update_rec_top_left(event=None): + relative_position_x = event["relativeX"] / zoom_factor + relative_position_y = event["relativeY"] / zoom_factor + positions = [int(relative_position_y), int(relative_position_x)] + + for i in [-1, -2]: + cmin, cmax = self._range_sliders[i].value + cvalue = positions[i] + cmin # Adjust position for current crop + self._range_sliders[i].value = (cvalue, cmax) + + if len(self._image.shape) > 2: + cvalue = slice_slider.value + cmin, cmax = self._range_sliders[0].value + self._range_sliders[0].value = (cvalue, cmax) + self.update() + + def update_rec_bottom_right(event=None): + relative_position_x = event["relativeX"] / zoom_factor + relative_position_y = event["relativeY"] / zoom_factor + positions = [int(relative_position_y), int(relative_position_x)] + + for i in [-1, -2]: + cmin, cmax = self._range_sliders[i].value + cvalue = positions[i] + cmin # Adjust position for current crop + self._range_sliders[i].value = (cmin, cvalue) + + if len(self._image.shape) > 2: + cvalue = slice_slider.value + cmin, cmax = self._range_sliders[0].value + + self._range_sliders[0].value = (cmin, cvalue) + self.update() + + event_handler_top_left.on_dom_event(update_rec_top_left) + event_handler_bottom_right.on_dom_event(update_rec_bottom_right) + super(_Cropper, self).__init__(widgets) def update(self, event=None): From 3ea248caed99fd17e5c33a03b6b7cd9d0b75ac44 Mon Sep 17 00:00:00 2001 From: Alex Sauer Date: Fri, 17 May 2024 16:18:01 +0100 Subject: [PATCH 2/2] Adjust z crop for position when cropping --- stackview/_crop.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stackview/_crop.py b/stackview/_crop.py index 5160fa6..ce7128a 100644 --- a/stackview/_crop.py +++ b/stackview/_crop.py @@ -147,9 +147,10 @@ def update_rec_top_left(event=None): self._range_sliders[i].value = (cvalue, cmax) if len(self._image.shape) > 2: - cvalue = slice_slider.value cmin, cmax = self._range_sliders[0].value + cvalue = slice_slider.value + cmin self._range_sliders[0].value = (cvalue, cmax) + slice_slider.value = 0 self.update() def update_rec_bottom_right(event=None): @@ -163,10 +164,10 @@ def update_rec_bottom_right(event=None): self._range_sliders[i].value = (cmin, cvalue) if len(self._image.shape) > 2: - cvalue = slice_slider.value cmin, cmax = self._range_sliders[0].value - + cvalue = slice_slider.value + cmin + 1 self._range_sliders[0].value = (cmin, cvalue) + slice_slider.value = cvalue - cmin + 1 self.update() event_handler_top_left.on_dom_event(update_rec_top_left)