import numpy as np from backend.data_types import DataField, LineData def test_line_cursors(): from backend.nodes.cursors import Cursors node = Cursors() line_spec = Cursors.INPUT_TYPES()["required"]["line"] assert line_spec[0] == "LINE" assert line_spec[1]["accepted_types"] == ["DATA_FIELD"] line = np.linspace(0, 10, 100).astype(np.float64) overlays = [] Cursors._broadcast_overlay_fn = lambda nid, data: overlays.append(data) Cursors._current_node_id = "test" table, coord_pair = node.process(line, x1=0.25, y1=0.5, x2=0.75, y2=0.5) assert isinstance(coord_pair, tuple) and len(coord_pair) == 2 assert len(table) == 6 quantities = {row["quantity"] for row in table} assert "A x" in quantities assert "B x" in quantities assert "dx" in quantities assert "dy" in quantities a_pos = next(r["value"] for r in table if r["quantity"] == "A x") b_pos = next(r["value"] for r in table if r["quantity"] == "B x") assert b_pos > a_pos dy = next(r["value"] for r in table if r["quantity"] == "dy") assert dy > 0 assert len(overlays) == 1 assert overlays[0]["kind"] == "line_plot" assert len(overlays[0]["line"]) == len(line) assert len(overlays[0]["x_axis"]) == len(line) assert 0.0 <= overlays[0]["x1"] <= 1.0 assert 0.0 <= overlays[0]["x2"] <= 1.0 line_data = LineData(data=line, x_axis=np.linspace(0, 1, 100)) table2, _ = node.process(line_data, x1=0.25, y1=0.5, x2=0.75, y2=0.5) assert len(table2) == 6 field = DataField( data=np.arange(100, dtype=np.float64).reshape(10, 10), xreal=2.0, yreal=4.0, si_unit_xy="um", si_unit_z="nm", ) overlays.clear() table3, _ = node.process(field, x1=0.2, y1=0.25, x2=0.7, y2=0.75) assert len(table3) == 9 field_rows = {row["quantity"]: row for row in table3} assert field_rows["dx"]["unit"] == "um" assert field_rows["dy"]["unit"] == "um" assert field_rows["dz"]["unit"] == "nm" assert np.isclose(field_rows["dx"]["value"], 1.0) assert np.isclose(field_rows["dy"]["value"], 2.0) assert len(overlays) == 1 assert overlays[0]["kind"] == "cursor_points" assert overlays[0]["image"].startswith("data:image/png;base64,") Cursors._broadcast_overlay_fn = None