fix(LamNI): push smear composite via new IDSCamera RPC method
dev.cam_xeye.image.put(composite) failed on real hardware -- PreviewSignal is a BECMessageSignal subclass, and BEC hardcodes rpc_access=False for that signal_info, so the client-side device proxy never exposes `image` as an attribute at all (confirmed: this is a structural BEC constraint, not specific to this device -- no existing RPC surface, device or widget, offers a raw-array setter either). Add IDSCamera.push_preview_image(data), a small device-server-side method (alongside the existing get_last_image()) that does self.image.put(data) from within the device-server process, where PreviewSignal is a normal ophyd attribute. _push_smear_composite now calls dev.cam_xeye.push_preview_image(composite) instead of writing to the signal directly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -674,9 +674,15 @@ class XrayEyeAlign:
|
||||
between this push and the next raw frame the live thread would
|
||||
otherwise publish to the same PreviewSignal/device_preview
|
||||
channel the GUI is subscribed to.
|
||||
|
||||
dev.cam_xeye.image is a PreviewSignal, which is not remotely
|
||||
writable from client code (BEC excludes BECMessageSignal
|
||||
subclasses from the client-side device RPC proxy) -- push via the
|
||||
push_preview_image() device method instead, which runs
|
||||
device-server side where self.image is a normal ophyd attribute.
|
||||
"""
|
||||
dev.cam_xeye.live_mode_enabled.put(False)
|
||||
dev.cam_xeye.image.put(composite)
|
||||
dev.cam_xeye.push_preview_image(composite)
|
||||
time.sleep(hold_display_s)
|
||||
dev.cam_xeye.live_mode_enabled.put(True)
|
||||
|
||||
|
||||
@@ -51,7 +51,14 @@ class IDSCamera(PSIDeviceBase):
|
||||
kind=Kind.config,
|
||||
)
|
||||
|
||||
USER_ACCESS = ["start_live_mode", "stop_live_mode", "mask", "set_rect_roi", "get_last_image"]
|
||||
USER_ACCESS = [
|
||||
"start_live_mode",
|
||||
"stop_live_mode",
|
||||
"mask",
|
||||
"set_rect_roi",
|
||||
"get_last_image",
|
||||
"push_preview_image",
|
||||
]
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -195,6 +202,20 @@ class IDSCamera(PSIDeviceBase):
|
||||
if image:
|
||||
return image.data
|
||||
|
||||
def push_preview_image(self, data: np.ndarray) -> None:
|
||||
"""Push an arbitrary array to this camera's own preview signal.
|
||||
|
||||
self.image is a PreviewSignal, which is deliberately excluded from
|
||||
the client-side device RPC/signal proxy (rpc_access defaults to
|
||||
False for BECMessageSignal subclasses, with no override) -- so
|
||||
client code cannot do dev.cam_xeye.image.put(...) directly. This
|
||||
method runs device-server side, where self.image is a normal ophyd
|
||||
attribute, and is the supported way for a client to publish a
|
||||
custom (e.g. composite/processed) image through the same
|
||||
device_preview channel the GUI already subscribes to.
|
||||
"""
|
||||
self.image.put(data)
|
||||
|
||||
############## User Interface Methods ##############
|
||||
|
||||
def on_connected(self):
|
||||
|
||||
@@ -395,7 +395,7 @@ def test_push_smear_composite_duty_cycles_live_mode(bec_client_mock):
|
||||
False,
|
||||
True,
|
||||
]
|
||||
dev_mock.cam_xeye.image.put.assert_called_once_with(composite)
|
||||
dev_mock.cam_xeye.push_preview_image.assert_called_once_with(composite)
|
||||
|
||||
|
||||
def test_smear_sweep_max_projection(bec_client_mock):
|
||||
|
||||
Reference in New Issue
Block a user