feat(LamNI): measure camera live-mode FPS and smear-sweep capture FPS
Neither rate was previously measured anywhere, making it hard to tell a real acquisition bottleneck from a display/overhead one. - IDSCamera.get_live_fps() (new USER_ACCESS entry): rolling-buffer measurement of the live-mode push rate in _live_mode_loop(), readable as dev.cam_xeye.get_live_fps(). SimIDSCamera inherits it unchanged, so it works against the simulated deployment too. - XrayEyeAlign._smear_sweep() now tracks timestamps of the first and most recent distinct frame it captures, storing the computed rate as self.last_smear_fps and printing it in the sweep-done summary line. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit was merged in pull request #277.
This commit is contained in:
@@ -424,6 +424,53 @@ def test_smear_sweep_max_projection(bec_client_mock):
|
||||
assert [c.args[0] for c in align.gui.set_smear_active.call_args_list] == [True, False]
|
||||
|
||||
|
||||
def test_smear_sweep_computes_capture_fps(bec_client_mock):
|
||||
client = bec_client_mock
|
||||
align, dev_mock = _make_calibration_align(client)
|
||||
|
||||
frame_a = np.array([[1, 5], [3, 2]], dtype=np.uint8)
|
||||
frame_b = np.array([[4, 2], [3, 6]], dtype=np.uint8)
|
||||
frame_c = np.array([[0, 1], [9, 0]], dtype=np.uint8)
|
||||
dev_mock.cam_xeye.get_last_image.side_effect = [frame_a, frame_b, frame_c]
|
||||
report = _report_with_status_sequence("RUNNING", "RUNNING", "RUNNING", "COMPLETED")
|
||||
|
||||
# Deterministic clock: each time.time() call advances by 0.05s. With
|
||||
# frame_a (first frame, uncounted per the existing off-by-one) then
|
||||
# frame_b and frame_c as the 2 distinct frames that follow, the elapsed
|
||||
# time between the first frame and the last distinct one spans exactly
|
||||
# 4 of these ticks (0.20s) -- see the call trace in _smear_sweep().
|
||||
clock = {"t": 0.0}
|
||||
|
||||
def fake_time():
|
||||
clock["t"] += 0.05
|
||||
return clock["t"]
|
||||
|
||||
with mock.patch(f"{XRAY_EYE_ALIGN}.dev", dev_mock):
|
||||
with mock.patch(f"{XRAY_EYE_ALIGN}.mv", return_value=report):
|
||||
with mock.patch(f"{XRAY_EYE_ALIGN}.time.sleep"):
|
||||
with mock.patch(f"{XRAY_EYE_ALIGN}.time.time", side_effect=fake_time):
|
||||
align._smear_sweep()
|
||||
|
||||
assert align.last_smear_fps == pytest.approx(10.0)
|
||||
|
||||
|
||||
def test_smear_sweep_fps_none_with_fewer_than_two_distinct_frames(bec_client_mock):
|
||||
client = bec_client_mock
|
||||
align, dev_mock = _make_calibration_align(client)
|
||||
|
||||
frame_a = np.array([[1, 5], [3, 2]], dtype=np.uint8)
|
||||
dev_mock.cam_xeye.get_last_image.return_value = frame_a
|
||||
report = _report_with_status_sequence("RUNNING", "COMPLETED")
|
||||
|
||||
with mock.patch(f"{XRAY_EYE_ALIGN}.dev", dev_mock):
|
||||
with mock.patch(f"{XRAY_EYE_ALIGN}.mv", return_value=report):
|
||||
with mock.patch(f"{XRAY_EYE_ALIGN}.time.sleep"):
|
||||
align._smear_sweep()
|
||||
|
||||
# only the first (uncounted) frame was seen -- frames_seen stays 0
|
||||
assert align.last_smear_fps is None
|
||||
|
||||
|
||||
def test_smear_sweep_issues_single_continuous_move(bec_client_mock):
|
||||
client = bec_client_mock
|
||||
align, dev_mock = _make_calibration_align(client)
|
||||
|
||||
Reference in New Issue
Block a user