fix(image): fix crosshair intensity and roi slices for rgb image inputs

This commit is contained in:
2026-07-16 13:49:11 +02:00
committed by Jan Wyzula
parent 99f6e0b3dc
commit a87e768b65
2 changed files with 46 additions and 3 deletions
+19 -3
View File
@@ -753,6 +753,12 @@ class ImageBase(PlotBase):
live curves; ignored for the pinned curves.
pinned(bool): Update the pinned reference curves instead of the live ones.
"""
image_item = self.layer_manager["main"].image
image = image_item.image
if image is not None and image.ndim != 2:
self.clear_image_slices()
return
if pinned:
if self._pinned_slice_coords is None:
return
@@ -770,7 +776,6 @@ class ImageBase(PlotBase):
else:
return
image_item = self.layer_manager["main"].image
slices = self._compute_image_slices(image_item, row, col)
if slices is None:
return
@@ -815,10 +820,10 @@ class ImageBase(PlotBase):
Returns:
tuple | None: ``(h_world_x, h_slice, v_world_y, v_slice)`` in world coordinates,
or ``None`` if there is no image or the pixel is out of bounds.
or ``None`` if the image is not scalar 2-D or the pixel is out of bounds.
"""
image = image_item.image
if image is None:
if image is None or image.ndim != 2:
return None
max_row, max_col = image.shape[0] - 1, image.shape[1] - 1
if not (0 <= row <= max_row and 0 <= col <= max_col):
@@ -843,6 +848,17 @@ class ImageBase(PlotBase):
]
return h_world_x, h_slice, v_world_y, v_slice
@SafeSlot()
def clear_image_slices(self):
"""Remove live and pinned profile curves for an unsupported image."""
if self.x_roi_curve is not None:
self.x_roi.plot_item.removeItem(self.x_roi_curve)
self.x_roi_curve = None
if self.y_roi_curve is not None:
self.y_roi.plot_item.removeItem(self.y_roi_curve)
self.y_roi_curve = None
self.clear_pinned_slices()
@SafeSlot(tuple)
def pin_image_slices(self, _coordinates: tuple):
"""Create or update the pinned profile curves at the pinned pixel.
@@ -1160,6 +1160,33 @@ def test_roi_plot_data_from_image(qtbot, mocked_client):
np.testing.assert_array_equal(h_slice, test_data[2])
def test_roi_plots_ignore_rgb_images_and_clear_stale_curves(qtbot, mocked_client):
"""RGB images have vector-valued pixels and cannot produce scalar profile curves."""
bec_image_view = create_widget(qtbot, Image, client=mocked_client)
scalar_image = np.arange(25).reshape(5, 5)
bec_image_view.on_image_update_2d({"data": scalar_image}, {})
switch = bec_image_view.toolbar.components.get_action("image_switch_crosshair")
switch.actions["crosshair_roi"].action.trigger()
bec_image_view.update_image_slices((0, 2, 3))
bec_image_view.crosshair.set_pin(2.0, 3.0)
assert bec_image_view.x_roi_curve is not None
assert bec_image_view.y_roi_curve is not None
assert bec_image_view.x_roi_pinned is not None
assert bec_image_view.y_roi_pinned is not None
rgb_image = np.zeros((5, 5, 3), dtype=np.uint8)
bec_image_view.on_image_update_2d({"data": rgb_image}, {})
assert bec_image_view._compute_image_slices(bec_image_view.main_image, 2, 3) is None
assert bec_image_view.x_roi_curve is None
assert bec_image_view.y_roi_curve is None
assert bec_image_view.x_roi_pinned is None
assert bec_image_view.y_roi_pinned is None
assert bec_image_view.x_roi.plot_item.listDataItems() == []
assert bec_image_view.y_roi.plot_item.listDataItems() == []
def test_pinned_roi_profiles_freeze_and_clear(qtbot, mocked_client):
"""Clicking pins a frozen copy of the X/Y profiles that survives live updates."""
import numpy as np