In EPICS, array detectors are typically integrated using Area Detector, which joins hardware integration to a live processing pipeline. Area Detector devices are the most complex devices built into Ophyd.
Configuring one in Ophyd currently requires some assembly, listing all the plugins that you want to expose to Ophyd. A more out-of-the-box solution is planned for a future relase of Ophyd.
!mkdir -p $HOME/images
# This is just a shortcut related to preparing this cloud-based
# deployment the day before the tutorial.
# It is not AT ALL necessary to loosen permissions like this
# in production deployments.
!chmod 777 $HOME/images
from ophyd.areadetector import SimDetector, SimDetectorCam, SingleTrigger
from ophyd.areadetector.plugins import (
StatsPlugin,
ImagePlugin,
ROIPlugin,
HDF5Plugin,
ProcessPlugin,
)
from ophyd.areadetector.filestore_mixins import FileStoreHDF5IterativeWrite
from ophyd import Component
class HDF5PluginWithFileStore(HDF5Plugin, FileStoreHDF5IterativeWrite):
pass
class Detector(SingleTrigger, SimDetector):
image = Component(ImagePlugin, 'image1:')
cam = Component(SimDetectorCam, 'cam1:')
transform_type = 0
hdf5 = Component(HDF5PluginWithFileStore, 'HDF1:',
write_path_template='/data/images/',
read_path_template='/home/jovyan/images',
read_attrs=[],
root='/')
stats1 = Component(StatsPlugin, 'Stats1:')
stats2 = Component(StatsPlugin, 'Stats2:')
stats3 = Component(StatsPlugin, 'Stats3:')
stats4 = Component(StatsPlugin, 'Stats4:')
stats5 = Component(StatsPlugin, 'Stats5:')
roi1 = Component(ROIPlugin, 'ROI1:')
roi2 = Component(ROIPlugin, 'ROI2:')
roi3 = Component(ROIPlugin, 'ROI3:')
roi4 = Component(ROIPlugin, 'ROI4:')
proc1 = Component(ProcessPlugin, 'Proc1:')
camera = Detector(name="camera", prefix="ADSIM:", read_attrs=["hdf5", "stats1", "stats5"])
The HDF5 plugin in particular requires a special "warmup" step before the first use after the IOC boots. This pushes an array through the plugin pipeline to make the HDF5 plugin aware of the array dimensions. It needs to know this before it can open a file for writing.
camera.hdf5.warmup()
camera.stage()
status = camera.trigger()
status.wait()
camera.describe()
camera.read()
documents = list(camera.collect_asset_docs())
camera.unstage()
from area_detector_handlers.handlers import AreaDetectorHDF5Handler
from pathlib import Path
_, resource_document = documents[0]
_, datum_document = documents[1]
handler = AreaDetectorHDF5Handler(
Path(resource_document["root"], resource_document["resource_path"]),
**resource_document["resource_kwargs"]
)
handler(**datum_document["datum_kwargs"])
from bluesky import RunEngine
from bluesky_tutorial_utils import setup_data_saving
RE = RunEngine()
db = setup_data_saving(RE)
from bluesky.plans import count
RE(count([camera], num=3))
dataset = db[-1].primary.read()
dataset
dataset["camera_image"]
%matplotlib widget
import matplotlib.pyplot as plt
plt.imshow(dataset["camera_image"][0][0])