diff --git a/pxiii_bec/device_configs/x06da_device_config.yaml b/pxiii_bec/device_configs/x06da_device_config.yaml index 7d79bde..c1ef2df 100644 --- a/pxiii_bec/device_configs/x06da_device_config.yaml +++ b/pxiii_bec/device_configs/x06da_device_config.yaml @@ -430,7 +430,7 @@ samcam: readoutPriority: monitored readOnly: false softwareTrigger: false -samimg: +samstream: description: Sample camera ZMQ stream deviceClass: pxiii_bec.devices.StdDaqPreviewDetector deviceConfig: @@ -441,6 +441,20 @@ samimg: readoutPriority: async readOnly: false softwareTrigger: false +samimg: + description: Sample camera image from EPICS + deviceClass: pxiii_bec.devices.NDArrayPreview + deviceConfig: + prefix: 'X06DA-SAMCAM:image1:' + deviceTags: + - detector + enabled: true + readoutPriority: async + readOnly: false + softwareTrigger: false + + + bstop_pneum: diff --git a/pxiii_bec/devices/NDArrayPreview.py b/pxiii_bec/devices/NDArrayPreview.py new file mode 100644 index 0000000..343e50c --- /dev/null +++ b/pxiii_bec/devices/NDArrayPreview.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +""" +Standard DAQ preview image stream module + +Created on Thu Jun 27 17:28:43 2024 + +@author: mohacsi_i +""" +import numpy as np +from ophyd import Device, Component, EpicsSignal, Kind, Staged +from ophyd.areadetector.base import NDDerivedSignal + +from bec_lib import bec_logger +logger = bec_logger.logger + + +class NDArrayPreview(Device): + """Wrapper class around AreaDetector's NDStdArray plugins + + This is a monolithic class to display images from AreaDetector's + ImagePlugin without the use of DynamicDeviceComponent or multiple + interitance (that doesn't work with BEC). + """ + # Subscriptions for plotting image + USER_ACCESS = ["image"] + SUB_MONITOR = "device_monitor_2d" + _default_sub = SUB_MONITOR + + # Status attributes + array_size_x = Component(EpicsSignal, "ArraySize0_RBV", kind=Kind.config) + array_size_y = Component(EpicsSignal, "ArraySize1_RBV", kind=Kind.config) + array_size_z = Component(EpicsSignal, "ArraySize2_RBV", kind=Kind.config) + ndimensions = Component(EpicsSignal, "NDimensions_RBV", kind=Kind.config) + array_data = Component(EpicsSignal, "ArrayData", kind=Kind.omitted) + shaped_image = Component( + NDDerivedSignal, + derived_from="array_data", + shape=("array_size_z", "array_size_y", "array_size_x"), + num_dimensions="ndimensions", + kind=Kind.normal, + ) + + def read(self): + """ Stream out data on every read()""" + if self._staged==Staged.yes: + image = self.shaped_image.get() + self._run_subs(sub_type=self.SUB_MONITOR, value=image) + return super().read() + + def image(self): + """ Fallback method in case image streaming fills up the BEC""" + array_size = (self.array_size_z.get(), self.array_size_y.get(), self.array_size_x.get()) + if array_size == (0, 0, 0): + raise RuntimeError("Invalid image; ensure array_callbacks are on") + + if array_size[-1] == 0: + array_size = array_size[:-1] + + pixel_count = np.prod(array_size) + image = self.array_data.get() + if image.size == pixel_count: + return np.array(image).reshape(array_size) + + + +# Automatically connect to SAMCAM at PXIII if directly invoked +if __name__ == "__main__": + img = NDArrayPreview("X06DA-SAMCAM:image1:", name="samimg") + img.wait_for_connection() diff --git a/pxiii_bec/devices/StdDaqPreview.py b/pxiii_bec/devices/StdDaqPreview.py index 2e27801..b0ce8bf 100644 --- a/pxiii_bec/devices/StdDaqPreview.py +++ b/pxiii_bec/devices/StdDaqPreview.py @@ -43,6 +43,9 @@ class StdDaqPreviewMixin(CustomDetectorMixin): self.parent.unstage() sleep(0.5) + logger.info( + f"[{self.parent.name}] Attaching monitor to {self.parent.url.get()}" + ) self.parent.connect() self._stop_polling = False self._mon = Thread(target=self.poll, daemon=True) @@ -107,7 +110,7 @@ class StdDaqPreviewMixin(CustomDetectorMixin): self.parent._last_image = image self.parent._run_subs(sub_type=self.parent.SUB_MONITOR, value=image) t_last = t_curr - logger.debug( + logger.info( f"[{self.parent.name}] Updated frame {header['frame']}\t" f"Shape: {header['shape']}\tMean: {np.mean(image):.3f}" ) diff --git a/pxiii_bec/devices/__init__.py b/pxiii_bec/devices/__init__.py index 03d87ca..85cc367 100644 --- a/pxiii_bec/devices/__init__.py +++ b/pxiii_bec/devices/__init__.py @@ -7,4 +7,5 @@ Ophyd devices for the PX III beamline, including the MX specific Aerotech A3200 from .A3200 import AerotechAbrStage from .A3200utils import A3200Axis from .SmarGon import SmarGonAxis -from .StdDaqPreview import StdDaqPreviewDetector \ No newline at end of file +from .StdDaqPreview import StdDaqPreviewDetector +from .NDArrayPreview import NDArrayPreview \ No newline at end of file