"""The array tool and the 2D map's look: what the operator sees and what the tool offers.""" from __future__ import annotations import numpy as np from orisys_app_shared.i18n import t from orisys_autocal.array_plan import Candidate from orisys_autocal.ui.sensor_panel import FlatSurfaceView from PySide6.QtGui import QColor def _synthetic_flat(size: int = 64): from orisys_autocal.sensor.uv_flat import FlatSurface image = np.zeros((size, size, 3), dtype=np.uint8) image[..., 2] = 200 # a plain blue map: any yellow on it is a mark return FlatSurface( size_hw=(size, size), image_rgb=image, positions_mm=np.zeros((size, size, 3)), normals=np.tile(np.array([0.0, 0.0, 1.0]), (size, size, 1)), face_index=np.zeros((size, size), dtype=np.int32), uv_min=(0.0, 0.0), uv_max=(1.0, 1.0), ) def test_marks_stay_visible_when_the_map_is_scaled_down(qt_app): view = FlatSurfaceView() view.resize(32, 32) # half the map's size view.set_flat(_synthetic_flat(64)) view.set_marker_colour("#ffd60a") view.set_sequence_points([(32, 32, "", False)]) shown = view.pixmap().toImage() centre = QColor(shown.pixel(shown.width() // 2, shown.height() // 2)) # The mark is drawn after the scale, so its colour is at the centre of the # shown image instead of being smeared into the blue by the downscale. assert centre.red() > 220 and centre.green() > 180 and centre.blue() < 80 def test_the_background_can_be_changed_and_marks_survive_it(qt_app): view = FlatSurfaceView() view.resize(64, 64) view.set_flat(_synthetic_flat(64)) before = QColor(view.pixmap().toImage().pixel(2, 2)) for mode in ("gray", "dim", "outline"): view.set_background(mode) after = QColor(view.pixmap().toImage().pixel(2, 2)) assert after != before, mode assert view.background == mode view.set_background("nonsense") assert view.background == "original" def test_unusable_candidates_are_drawn_apart_from_usable_ones(qt_app): view = FlatSurfaceView() view.resize(64, 64) view.set_flat(_synthetic_flat(64)) view.set_marker_colour("#ffd60a") view.set_candidates([(32, 32, False)]) shown = view.pixmap().toImage() red_pixels = sum( 1 for x in range(24, 41) for y in range(24, 41) if QColor(shown.pixel(x, y)).red() > 200 and QColor(shown.pixel(x, y)).green() < 110 ) assert red_pixels > 0 def test_the_look_is_chosen_on_the_page_and_reported(make_window): window = make_window() panel = window.finger_panel seen: list[tuple[str, str]] = [] panel.viewStyleChanged.connect(lambda mode, colour: seen.append((mode, colour))) panel.bg_combo.setCurrentIndex(panel.bg_combo.findData("dim")) panel.colour_combo.setCurrentIndex(panel.colour_combo.findData("white")) assert panel.view_style() == ("dim", "white") assert seen[-1] == ("dim", "white") assert window.prefs["finger_view_background"] == "dim" assert panel.view.marker_colour == QColor("#ffffff") window.close() def test_the_grid_has_rows_times_columns_candidates_and_follows_its_fields(make_window): window = make_window() tool = window.sequence_panel.array_tool assert len(tool.candidates()) == 9 tool.spin("rows").setValue(2) tool.spin("cols").setValue(5) assert len(tool.candidates()) == 10 tool.mode_combo.setCurrentIndex(tool.mode_combo.findData("preset")) assert tool.mode == "preset" tool.preset_combo.setCurrentIndex(tool.preset_combo.findData("stage0")) assert tool.candidates() == [("C13", 0, 470)] window.close() def test_only_usable_candidates_can_be_added(make_window): window = make_window() tool = window.sequence_panel.array_tool added: list = [] tool.addRequested.connect(added.append) tool.set_checked([Candidate(0, 0, False, "off_surface")]) assert not tool.add_button.isEnabled() tool.set_checked([Candidate(0, 0, True), Candidate(5, 5, False, "near_edge")]) assert tool.add_button.isEnabled() assert tool.add_button.text() == t("array.btn_add", count=1) tool.add_button.click() assert [c.u for c in added[0]] == [0] window.close() def test_adding_candidates_skips_a_point_already_in_the_sequence(make_window, monkeypatch): window = make_window() panel = window.sequence_panel monkeypatch.setattr(window, "_map_origin", lambda: (100, 150)) monkeypatch.setattr( window.finger_panel, "solve_pixel_row", lambda x, y: {"X": 1.0, "Y": 2.0, "Z": 3.0, "u_px": x - 100.0, "v_px": 150.0 - y}, ) before = panel.point_row_count() window._on_array_add([Candidate(10, 20), Candidate(30, 40)]) # noqa: SLF001 window._on_array_add([Candidate(10, 20), Candidate(50, 60)]) # noqa: SLF001 assert panel.point_row_count() == before + 3 window.close()