Skip to content

Commit

Permalink
Added a function for generating NDAttributeParam objects for an xspre…
Browse files Browse the repository at this point in the history
…ss3 detector.
  • Loading branch information
canismarko committed Jan 9, 2025
1 parent d4366f5 commit 83a87d5
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 1 deletion.
22 changes: 22 additions & 0 deletions docs/topic_guides/fluorescence_detectors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,28 @@ The device can then be retrieved by its name for use in Bluesky plans.
detectors = haven.beamline.devices.findall(label="fluorescence_detectors")
Adding NDAttributes (Xspress3)
=============================

The EPICS support for an Xspress3 detector provides several additional
values besides the spectra, many of them useful for dead-time
correction. These can be saved using the Ophyd-async NDAttribute
support. Haven includes a function for generating these parameters so
they can be set on the IOC in a way that allows Tiled to read the
resulting values from the HDF5 file. This only needs to be done once
for each detector IOC.

.code-block:: python

from haven.devices.detectors.xspress import Xspress3Detector, ndattribute_params
from ophyd_async.plan_stubs import setup_ndattributes

# Assuming a 4-element detector
detector = Xspress3Detector(...)
params = ndattribute_params(device_name=detector.name, elements=range(4))
setup_ndattributes(detector, params)


Why can't I…
############

Expand Down
83 changes: 83 additions & 0 deletions src/haven/devices/detectors/xspress.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
TriggerInfo,
)
from ophyd_async.epics import adcore
from ophyd_async.epics.adcore import NDAttributeParam
from ophyd_async.epics.adcore._utils import ADBaseDataType, convert_ad_dtype_to_np
from ophyd_async.epics.core import epics_signal_rw, epics_signal_x

Expand Down Expand Up @@ -126,3 +127,85 @@ async def stage(self) -> None:
self.drv.erase_on_start.set(False),
self.drv.erase.trigger(),
)


def ndattribute_params(
device_name: str, elements: Sequence[int]
) -> Sequence[NDAttributeParam]:
"""Create a set of ndattribute params that can be written to the AD's
HDF5 file.
These parameters can then be used with something like
:py:func:`ophyd_async.plan_stubs.setup_ndattributes` to build the
XML.
"""
params = []
for idx in elements:
new_params = [
NDAttributeParam(
name=f"{device_name}-element{idx}-deadtime_factor",
param="XSP3_CHAN_DTFACTOR",
datatype="DOUBLE",
addr=idx,
description=f"Chan {idx} DTC Factor",
),
NDAttributeParam(
name=f"{device_name}-element{idx}-deadtime_percent",
param="XSP3_CHAN_DTPERCENT",
datatype="DOUBLE",
addr=idx,
description=f"Chan {idx} DTC Percent",
),
NDAttributeParam(
name=f"{device_name}-element{idx}-event_width",
param="XSP3_EVENT_WIDTH",
datatype="DOUBLE",
addr=idx,
description=f"Chan {idx} Event Width",
),
NDAttributeParam(
name=f"{device_name}-element{idx}-clock_ticks",
param="XSP3_CHAN_SCA0",
datatype="DOUBLE",
addr=idx,
description=f"Chan {idx} ClockTicks",
),
NDAttributeParam(
name=f"{device_name}-element{idx}-reset_ticks",
param="XSP3_CHAN_SCA1",
datatype="DOUBLE",
addr=idx,
description=f"Chan {idx} ResetTicks",
),
NDAttributeParam(
name=f"{device_name}-element{idx}-reset_counts",
param="XSP3_CHAN_SCA2",
datatype="DOUBLE",
addr=idx,
description=f"Chan {idx} ResetCounts",
),
NDAttributeParam(
name=f"{device_name}-element{idx}-all_event",
param="XSP3_CHAN_SCA3",
datatype="DOUBLE",
addr=idx,
description=f"Chan {idx} AllEvent",
),
NDAttributeParam(
name=f"{device_name}-element{idx}-all_good",
param="XSP3_CHAN_SCA4",
datatype="DOUBLE",
addr=idx,
description=f"Chan {idx} AllGood",
),
NDAttributeParam(
name=f"{device_name}-element{idx}-pileup",
param="XSP3_CHAN_SCA7",
datatype="DOUBLE",
addr=idx,
description=f"Chan {idx} Pileup",
),
]
params.extend(new_params)
return params
9 changes: 8 additions & 1 deletion src/haven/tests/test_xspress.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from ophyd_async.core import TriggerInfo
from ophyd_async.testing import get_mock_put, set_mock_value

from haven.devices.detectors.xspress import Xspress3Detector
from haven.devices.detectors.xspress import Xspress3Detector, ndattribute_params

this_dir = Path(__file__).parent

Expand Down Expand Up @@ -73,6 +73,13 @@ async def test_deadtime_correction(detector):
assert not await detector.drv.deadtime_correction.get_value()


async def test_ndattribute_params():
n_elem = 8
n_params = 9
params = ndattribute_params(device_name="xsp3", elements=range(n_elem))
assert len(params) == n_elem * n_params


# -----------------------------------------------------------------------------
# :author: Mark Wolfman
# :email: [email protected]
Expand Down

0 comments on commit 83a87d5

Please sign in to comment.