Skip to content

Commit ed6cdc8

Browse files
2285 Crop Coordinates Operation Window: Restrict ROI MaxBounds and Handle Dialog Window Closure (#2302)
2 parents 52ac46e + b074c81 commit ed6cdc8

File tree

7 files changed

+25
-21
lines changed

7 files changed

+25
-21
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
#2285: Resolve operations windows crop co-ordinates ROI size from being larger than stack bounds. Additionally resolve ROI crop co-ordinate dialog window persistence if parent window closed.

mantidimaging/gui/test/gui_system_operations_test.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@
4949
ALLOWED_ERRORS = [
5050
'Negative values found in result preview for slice 0.',
5151
'Flat-fielding completed. Slices containing negative values in IMAT_Flower_Tomo_000000: all slices.',
52-
'Error applying filter for preview: could not broadcast input array from shape (1,80,80) into shape (1,90,90)'
5352
]
5453

5554

mantidimaging/gui/widgets/mi_image_view/view.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from typing import TYPE_CHECKING
88
from collections.abc import Callable
99

10-
from PyQt5.QtCore import Qt
10+
from PyQt5.QtCore import Qt, QRectF
1111
from PyQt5.QtWidgets import QApplication, QHBoxLayout, QLabel, QPushButton, QSizePolicy
1212
from pyqtgraph import ROI, ImageItem, ImageView, ViewBox
1313
from pyqtgraph.GraphicsScene.mouseEvents import HoverEvent
@@ -148,6 +148,9 @@ def angles(self, angles: ProjectionAngles | None) -> None:
148148
self._angles = angles
149149
self._update_message(self._last_mouse_hover_location)
150150

151+
def _set_roi_max_bounds(self):
152+
self.roi.maxBounds = QRectF(0, 0, self.image_data.shape[2], self.image_data.shape[1])
153+
151154
def setImage(self, image: np.ndarray, *args, **kwargs):
152155
dimensions_changed = self.image_data is None or self.image_data.shape != image.shape
153156
if image.ndim == 3:
@@ -195,6 +198,7 @@ def roiChanged(self) -> None:
195198
roi = self._update_roi_region_avg()
196199
if self.roi_changed_callback and roi is not None:
197200
self.roi_changed_callback(roi)
201+
self._set_roi_max_bounds()
198202
self._refresh_message()
199203

200204
def _update_roi_region_avg(self) -> SensibleROI | None:

mantidimaging/gui/widgets/roi_selector/view.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,7 @@ def toggle_average_images(self) -> None:
6969
self.roi_view_averaged = not self.roi_view_averaged
7070
self.roi_view.roi.show()
7171
self.roi_view.ui.roiPlot.hide()
72+
73+
def closeEvent(self, event) -> None:
74+
self.roi_view.close()
75+
event.accept()

mantidimaging/gui/windows/operations/presenter.py

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -284,14 +284,9 @@ def _post_filter(self, updated_stacks: list[ImageStack], task):
284284
if np.any(stack.data < 0):
285285
negative_stacks.append(stack)
286286

287-
if self.view.roi_view is not None:
288-
self.view.roi_view.close()
289-
self.view.roi_view = None
290-
291287
self.applying_to_all = False
292-
self.do_update_previews()
293288

294-
if task.error is not None:
289+
if task.error:
295290
# task failed, show why
296291
self.view.show_error_dialog(f"Operation failed: {task.error}")
297292
elif use_new_data:
@@ -312,6 +307,7 @@ def _post_filter(self, updated_stacks: list[ImageStack], task):
312307
self.view.filter_applied.emit()
313308
self._set_apply_buttons_enabled(self.prev_apply_single_state, self.prev_apply_all_state)
314309
self.filter_is_running = False
310+
self.do_update_previews()
315311

316312
def _do_apply_filter(self, apply_to: list[ImageStack]):
317313
self.filter_is_running = True
@@ -454,11 +450,8 @@ def init_roi_field(self, roi_field: QLineEdit):
454450
if self.stack is None:
455451
return
456452

457-
larger = np.greater(self.stack.data[0].shape, (200, 200))
458-
if all(larger):
459-
return
460-
x = min(self.stack.data[0].shape[0], 200)
461-
y = min(self.stack.data[0].shape[1], 200)
453+
x = self.stack.data.shape[1] // 2
454+
y = self.stack.data.shape[2] // 2
462455
crop_string = ", ".join(["0", "0", str(y), str(x)])
463456
roi_field.setText(crop_string)
464457

mantidimaging/gui/windows/operations/test/presenter_test.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -448,14 +448,14 @@ def test_init_roi_field_does_nothing_when_stack_is_none(self):
448448
self.presenter.init_roi_field(mock_roi_field)
449449
mock_roi_field.setText.assert_not_called()
450450

451-
def test_init_roi_field_does_nothing_when_image_is_greater_than_200_by_200(self):
451+
def test_init_roi_field_called_with_smaller_values_if_image_is_greater_than_200_by_200(self):
452452
mock_roi_field = mock.Mock()
453453
self.presenter.stack = mock.Mock()
454454
self.presenter.stack.data = np.ones((2, 201, 201))
455455
self.presenter.init_roi_field(mock_roi_field)
456-
mock_roi_field.setText.assert_not_called()
456+
mock_roi_field.setText.assert_called_once_with("0, 0, 100, 100")
457457

458-
@parameterized.expand([(190, 201, "0, 0, 200, 190"), (201, 80, "0, 0, 80, 200"), (200, 200, "0, 0, 200, 200")])
458+
@parameterized.expand([(190, 201, "0, 0, 100, 95"), (201, 80, "0, 0, 40, 100"), (200, 200, "0, 0, 100, 100")])
459459
def test_set_text_called_when_image_not_greater_than_200_by_200(self, shape_x, shape_y, expected):
460460
mock_roi_field = mock.Mock()
461461
self.presenter.stack = mock.Mock()

mantidimaging/gui/windows/operations/view.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ def __init__(self, main_window: MainWindowView):
6464
self.main_window = main_window
6565
self.presenter = FiltersWindowPresenter(self, main_window)
6666
self.roi_view = None
67+
self.roi_selector_dialog: ROISelectorView | None = None
6768
self.roi_view_averaged = False
6869
self.splitter.setSizes([200, 9999])
6970
self.splitter.setStretchFactor(0, 1)
@@ -122,8 +123,9 @@ def closeEvent(self, e):
122123
def cleanup(self):
123124
self.stackSelector.unsubscribe_from_main_window()
124125
if self.roi_view is not None:
125-
self.roi_view.close()
126126
self.roi_view = None
127+
self.roi_selector_dialog.close()
128+
127129
self.presenter.set_stack(None)
128130
self.auto_update_triggered.disconnect()
129131
self.main_window.filters = None
@@ -255,16 +257,17 @@ def roi_changed_callback(callback):
255257
except ValueError:
256258
roi_values = None
257259

258-
window = ROISelectorView(self, self.presenter.stack, self.presenter.model.preview_image_idx, roi_values,
259-
roi_changed_callback)
260+
self.roi_selector_dialog = ROISelectorView(self, self.presenter.stack, self.presenter.model.preview_image_idx,
261+
roi_values, roi_changed_callback)
260262

261263
def close_event(event):
262264
roi_field.setEnabled(True)
263265
roi_button.setEnabled(True)
264266
event.accept()
265267

266-
window.closeEvent = functools.partial(close_event)
267-
window.show()
268+
self.roi_view = self.roi_selector_dialog.roi_view
269+
self.roi_selector_dialog.closeEvent = functools.partial(close_event)
270+
self.roi_selector_dialog.show()
268271

269272
def toggle_filters_section(self):
270273
if self.collapseToggleButton.text() == "<<":

0 commit comments

Comments
 (0)