{ "cells": [ { "cell_type": "markdown", "id": "welcome-clark", "metadata": {}, "source": [ "# Standard EPICS Area Detector\n", "\n", "In EPICS, array detectors are typically integrated using [Area Detector](https://areadetector.github.io/), which joins hardware integration to a live processing pipeline. Area Detector devices are the most complex devices built into Ophyd.\n", "\n", "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." ] }, { "cell_type": "code", "execution_count": null, "id": "juvenile-variation", "metadata": {}, "outputs": [], "source": [ "!mkdir -p $HOME/images\n", "\n", "# This is just a shortcut related to preparing this cloud-based\n", "# deployment the day before the tutorial.\n", "# It is not AT ALL necessary to loosen permissions like this\n", "# in production deployments.\n", "!chmod 777 $HOME/images" ] }, { "cell_type": "code", "execution_count": null, "id": "unauthorized-budget", "metadata": {}, "outputs": [], "source": [ "from ophyd.areadetector import SimDetector, SimDetectorCam, SingleTrigger\n", "from ophyd.areadetector.plugins import (\n", " StatsPlugin,\n", " ImagePlugin,\n", " ROIPlugin,\n", " HDF5Plugin,\n", " ProcessPlugin,\n", ")\n", "from ophyd.areadetector.filestore_mixins import FileStoreHDF5IterativeWrite\n", "from ophyd import Component" ] }, { "cell_type": "code", "execution_count": null, "id": "frequent-mattress", "metadata": {}, "outputs": [], "source": [ "class HDF5PluginWithFileStore(HDF5Plugin, FileStoreHDF5IterativeWrite):\n", " pass\n", "\n", "class Detector(SingleTrigger, SimDetector):\n", " image = Component(ImagePlugin, 'image1:')\n", " cam = Component(SimDetectorCam, 'cam1:')\n", " transform_type = 0\n", " hdf5 = Component(HDF5PluginWithFileStore, 'HDF1:',\n", " write_path_template='/data/images/',\n", " read_path_template='/home/jovyan/images',\n", " read_attrs=[],\n", " root='/')\n", " stats1 = Component(StatsPlugin, 'Stats1:')\n", " stats2 = Component(StatsPlugin, 'Stats2:')\n", " stats3 = Component(StatsPlugin, 'Stats3:')\n", " stats4 = Component(StatsPlugin, 'Stats4:')\n", " stats5 = Component(StatsPlugin, 'Stats5:')\n", " roi1 = Component(ROIPlugin, 'ROI1:')\n", " roi2 = Component(ROIPlugin, 'ROI2:')\n", " roi3 = Component(ROIPlugin, 'ROI3:')\n", " roi4 = Component(ROIPlugin, 'ROI4:')\n", " proc1 = Component(ProcessPlugin, 'Proc1:')" ] }, { "cell_type": "code", "execution_count": null, "id": "rural-russell", "metadata": {}, "outputs": [], "source": [ "camera = Detector(name=\"camera\", prefix=\"ADSIM:\", read_attrs=[\"hdf5\", \"stats1\", \"stats5\"])" ] }, { "cell_type": "markdown", "id": "conscious-bowling", "metadata": {}, "source": [ "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." ] }, { "cell_type": "code", "execution_count": null, "id": "industrial-evans", "metadata": {}, "outputs": [], "source": [ "camera.hdf5.warmup()" ] }, { "cell_type": "markdown", "id": "disabled-eagle", "metadata": {}, "source": [ "## Manually walk throough the cycle" ] }, { "cell_type": "code", "execution_count": null, "id": "disabled-contamination", "metadata": {}, "outputs": [], "source": [ "camera.stage()" ] }, { "cell_type": "code", "execution_count": null, "id": "concrete-likelihood", "metadata": {}, "outputs": [], "source": [ "status = camera.trigger()" ] }, { "cell_type": "code", "execution_count": null, "id": "egyptian-judges", "metadata": {}, "outputs": [], "source": [ "status.wait()" ] }, { "cell_type": "code", "execution_count": null, "id": "statutory-inspection", "metadata": {}, "outputs": [], "source": [ "camera.describe()" ] }, { "cell_type": "code", "execution_count": null, "id": "accomplished-calendar", "metadata": {}, "outputs": [], "source": [ "camera.read()" ] }, { "cell_type": "code", "execution_count": null, "id": "tracked-debate", "metadata": {}, "outputs": [], "source": [ "documents = list(camera.collect_asset_docs())" ] }, { "cell_type": "code", "execution_count": null, "id": "major-cheat", "metadata": {}, "outputs": [], "source": [ "camera.unstage()" ] }, { "cell_type": "code", "execution_count": null, "id": "designing-adult", "metadata": {}, "outputs": [], "source": [ "from area_detector_handlers.handlers import AreaDetectorHDF5Handler\n", "from pathlib import Path" ] }, { "cell_type": "code", "execution_count": null, "id": "hourly-trout", "metadata": {}, "outputs": [], "source": [ "_, resource_document = documents[0]\n", "_, datum_document = documents[1]\n", "handler = AreaDetectorHDF5Handler(\n", " Path(resource_document[\"root\"], resource_document[\"resource_path\"]),\n", " **resource_document[\"resource_kwargs\"]\n", ")\n", "handler(**datum_document[\"datum_kwargs\"])" ] }, { "cell_type": "markdown", "id": "corporate-animation", "metadata": {}, "source": [ "## Use it with the Bluesky RunEngine" ] }, { "cell_type": "code", "execution_count": null, "id": "complimentary-conservative", "metadata": {}, "outputs": [], "source": [ "from bluesky import RunEngine\n", "from bluesky_tutorial_utils import setup_data_saving\n", "\n", "RE = RunEngine()\n", "db = setup_data_saving(RE)" ] }, { "cell_type": "code", "execution_count": null, "id": "julian-imaging", "metadata": {}, "outputs": [], "source": [ "from bluesky.plans import count" ] }, { "cell_type": "code", "execution_count": null, "id": "official-maker", "metadata": {}, "outputs": [], "source": [ "RE(count([camera], num=3))" ] }, { "cell_type": "code", "execution_count": null, "id": "blocked-villa", "metadata": {}, "outputs": [], "source": [ "dataset = db[-1].primary.read()\n", "dataset" ] }, { "cell_type": "code", "execution_count": null, "id": "musical-marker", "metadata": {}, "outputs": [], "source": [ "dataset[\"camera_image\"]" ] }, { "cell_type": "code", "execution_count": null, "id": "educational-serbia", "metadata": {}, "outputs": [], "source": [ "%matplotlib widget\n", "\n", "import matplotlib.pyplot as plt\n", "\n", "plt.imshow(dataset[\"camera_image\"][0][0])" ] }, { "cell_type": "code", "execution_count": null, "id": "rapid-middle", "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.10" } }, "nbformat": 4, "nbformat_minor": 5 }