0
0
mirror of https://github.com/bec-project/bec_widgets.git synced 2025-07-13 11:11:49 +02:00

fix(crosshair): label decimal precision is dynamically scaled with the plot zoom; API of all affected widgets adjusted; option added to PlotBase; closes #637

This commit is contained in:
2025-05-27 11:18:30 +02:00
committed by Jan Wyzula
parent 6b65a94c81
commit c8128faf79
12 changed files with 436 additions and 146 deletions

View File

@ -236,7 +236,7 @@ def test_update_coord_label_1D(plot_widget_with_crosshair):
# Provide a test position
pos = (10, 20)
crosshair.update_coord_label(pos)
expected_text = f"({10:.3g}, {20:.3g})"
expected_text = f"({10:.3f}, {20:.3f})"
# Verify that the coordinate label shows only the 1D coordinates (no intensity line)
assert crosshair.coord_label.toPlainText() == expected_text
label_pos = crosshair.coord_label.pos()
@ -260,10 +260,54 @@ def test_update_coord_label_2D(image_widget_with_crosshair):
ix = int(np.clip(0.5, 0, known_image.shape[0] - 1)) # 0
iy = int(np.clip(1.2, 0, known_image.shape[1] - 1)) # 1
intensity = known_image[ix, iy] # Expected: 20
expected_text = f"({0.5:.3g}, {1.2:.3g})\nIntensity: {intensity:.3g}"
expected_text = f"({0.5:.3f}, {1.2:.3f})\nIntensity: {intensity:.3f}"
assert crosshair.coord_label.toPlainText() == expected_text
label_pos = crosshair.coord_label.pos()
assert np.isclose(label_pos.x(), 0.5)
assert np.isclose(label_pos.y(), 1.2)
assert crosshair.coord_label.isVisible()
def test_crosshair_precision_properties(plot_widget_with_crosshair):
"""
Ensure Crosshair.precision and Crosshair.min_precision behave correctly
and that _current_precision() reflects changes immediately.
"""
crosshair, plot_item = plot_widget_with_crosshair
assert crosshair.precision == 3
assert crosshair._current_precision() == 3
crosshair.precision = None
plot_item.vb.setXRange(0, 1_000, padding=0)
plot_item.vb.setYRange(0, 1_000, padding=0)
assert crosshair._current_precision() == crosshair.min_precision == 2 # default floor
crosshair.min_precision = 5
assert crosshair._current_precision() == 5
crosshair.precision = 1
assert crosshair._current_precision() == 1
def test_crosshair_precision_properties_image(image_widget_with_crosshair):
"""
The same precision/min_precision behaviour must apply for crosshairs attached
to ImageItem-based plots.
"""
crosshair, plot_item = image_widget_with_crosshair
assert crosshair.precision == 3
assert crosshair._current_precision() == 3
crosshair.precision = None
plot_item.vb.setXRange(0, 1_000, padding=0)
plot_item.vb.setYRange(0, 1_000, padding=0)
assert crosshair._current_precision() == crosshair.min_precision == 2
crosshair.min_precision = 6
assert crosshair._current_precision() == 6
crosshair.precision = 2
assert crosshair._current_precision() == 2

View File

@ -349,3 +349,39 @@ def test_enable_fps_monitor_property(qtbot, mocked_client):
pb.enable_fps_monitor = False
assert pb.fps_monitor is None
def test_minimal_crosshair_precision_default(qtbot, mocked_client):
"""
By default PlotBase should expose a floor of 3 decimals, with no crosshair yet.
"""
pb = create_widget(qtbot, PlotBase, client=mocked_client)
assert pb.minimal_crosshair_precision == 3
assert pb.crosshair is None
def test_minimal_crosshair_precision_before_hook(qtbot, mocked_client):
"""
If the floor is changed before hook_crosshair(), the new crosshair must pick it up.
"""
pb = create_widget(qtbot, PlotBase, client=mocked_client)
pb.minimal_crosshair_precision = 5
pb.hook_crosshair()
assert pb.crosshair is not None
assert pb.crosshair.min_precision == 5
def test_minimal_crosshair_precision_after_hook(qtbot, mocked_client):
"""
Changing the floor after the crosshair exists should update it immediately
and emit the property_changed signal.
"""
pb = create_widget(qtbot, PlotBase, client=mocked_client)
pb.hook_crosshair()
assert pb.crosshair is not None
with qtbot.waitSignal(pb.property_changed, timeout=500) as sig:
pb.minimal_crosshair_precision = 1
assert sig.args == ["minimal_crosshair_precision", 1]
assert pb.crosshair.min_precision == 1