{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# Lesson 6: EPICS area detector\n", "\n", "In this lesson, we'll show how to use the tools provided \n", "with Bluesky to acquire an image from an EPICS Area Detector \n", "and show the image in the notebook.\n", "\n", "The EPICS Area Detector supports many different kinds of \n", "detector and provides many configuration possibilities \n", "for each detector in addition to configuration for handling \n", "of the acquired image or image stream via area detector \n", "components referred to as *plugins*. Configuration of \n", "bluesky to use an EPICS Area Detector usually requires \n", "several steps that are particular to the installation \n", "of the detector, specifically the type of camera and \n", "the use of the plugin chain.\n", "\n", "The amount of data that comes from imaging \n", "devices such as area detectors is much larger than the \n", "data involved with other data acquisition devices such as \n", "motors, scalers, temperature sensors, etc. Often, the imaging\n", "cameras will save the image data direct to a file system \n", "such as local storage. EPICS Area Detector has plugins to\n", "store the image stream to a file system accessible from the \n", "IOC (the camera's EPICS server computer). The Bluesky \n", "framework is designed with these considerations. The image\n", "data is stored external to the *databroker* component in \n", "bluesky. The *databroker* stores references to the file \n", "and address and provides access routines for the image data that\n", "manage ease of use along with efficient use of computing resources\n", "(memory, networking, etc.). \n", "\n", "So, instead of reading the image data directly from the \n", "area detector, we'll configure the area detector plugin chain\n", "to handle the image data and then, if we choose, use the \n", "databroker to process the image further such as visualize.\n", "\n", "**note**: This tutorial expects to find an EPICS IOC \n", "on the local network configured as an EPICS AreaDetector \n", "[ADSimDetector](https://github.com/areaDetector/ADSimDetector) \n", "IOC with prefix `adsky:`. A docker container is available \n", "to provide this IOC. See this URL for instructions: \n", "https://github.com/prjemian/epics-docker/blob/master/n4_areaDetector/README.md\n", "\n", "----" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Define the IOC prefix we'll use." ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "_ad_prefix = \"adsky:\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Import the instrument package as our routine initialization." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "I Sat-13:59:03 - ############################################################ startup\n", "I Sat-13:59:03 - logging started\n", "I Sat-13:59:03 - logging level = 10\n", "I Sat-13:59:03 - /home/prjemian/Documents/projects/bluesky_training/lessons/instrument/collection.py\n", "I Sat-13:59:03 - /home/prjemian/Documents/projects/bluesky_training/lessons/instrument/mpl/notebook.py\n", "Activating auto-logging. Current session state plus future input saved.\n", "Filename : /home/prjemian/Documents/projects/bluesky_training/lessons/.logs/ipython_console.log\n", "Mode : rotate\n", "Output logging : True\n", "Raw input log : False\n", "Timestamping : True\n", "State : active\n", "I Sat-13:59:03 - bluesky framework\n", "I Sat-13:59:03 - /home/prjemian/Documents/projects/bluesky_training/lessons/instrument/framework/check_python.py\n", "I Sat-13:59:03 - /home/prjemian/Documents/projects/bluesky_training/lessons/instrument/framework/check_bluesky.py\n", "I Sat-13:59:04 - /home/prjemian/Documents/projects/bluesky_training/lessons/instrument/framework/initialize.py\n", "I Sat-13:59:05 - /home/prjemian/Documents/projects/bluesky_training/lessons/instrument/framework/metadata.py\n", "I Sat-13:59:05 - /home/prjemian/Documents/projects/bluesky_training/lessons/instrument/framework/callbacks.py\n", "I Sat-13:59:05 - writing to SPEC file: /home/prjemian/Documents/projects/bluesky_training/lessons/20200516-135905.dat\n", "I Sat-13:59:05 - >>>> Using default SPEC file name <<<<\n", "I Sat-13:59:05 - file will be created when bluesky ends its next scan\n", "I Sat-13:59:05 - to change SPEC file, use command: newSpecFile('title')\n" ] } ], "source": [ "from instrument.collection import *" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For this tutorial, we'll configure the plotting as *inline* so we can view the graphics if we run the notebook from sessions in JupyterLab. For details, https://stackoverflow.com/a/51932652\n", "\n", "We always do this step *after* the instrument package has been imported." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The EPICS area detector support in ophyd has many features, some of them specific to the detector make and model. Let's start with just a few features using the ADSimDetector. We'll need to import support from ophyd by parts as they are needed.\n", "\n", "As we add features from the area detector plugins or other capabilities, the configuration complexity will increase. So, it is good to start with a simple case where we can control the camera and generate images." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "from ophyd import Component\n", "from ophyd.areadetector import ImagePlugin\n", "from ophyd.areadetector import SimDetector\n", "from ophyd.areadetector import SingleTrigger" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We need the ophyd `SimDetector` device. That support is flexible, so we must describe *how* we'll trigger it for data acquisition. We do that by adding the `SingleTrigger` mixin. Here's how to do it. This procedure is typical of what we'll have to do to support almost any EPICS area detector." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "class MySingleTriggerSimDetector(SingleTrigger, SimDetector):\n", " pass" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make an instance of this class and connect it with EPICS." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "adsimdet = MySingleTriggerSimDetector(_ad_prefix, name='adsimdet')\n", "adsimdet.wait_for_connection()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Staging** is fundamental to data acquisition in the Bluesky framework. Before a device is *triggered* to acquire data, it is *staged* to configure it for that specific acquisition. After acquisition is complete, the device is *unstaged* so that its previous configuration is restored. The *RunEngine* (`RE`) takes care of staging and unstaging so this all takes place behind the scenes. The `RE` also handles this when acquisition is interrupted.\n", "\n", "Here, we configure `adsimdet` for acquisition. These settings will be applied as part of data acquisition, then the previous settings will be restored. Here:\n", "\n", "* take one image per acquisition\n", "* acquire for exactly 0.1 seconds\n", "* Each acquisition will return after 0.25 s \n", "\n", "Note: if multiple acquisitions, acquire at interval of `adsimdet.cam.acquire_period`." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [], "source": [ "adsimdet.stage_sigs[\"cam.num_images\"] = 1\n", "adsimdet.stage_sigs[\"cam.acquire_time\"] = 0.1\n", "adsimdet.stage_sigs[\"cam.acquire_period\"] = 0.25" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Show all the settings to be used for data acquisition with this detector." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "OrderedDict([('cam.acquire', 0),\n", " ('cam.image_mode', 1),\n", " ('cam.num_images', 1),\n", " ('cam.acquire_time', 0.1),\n", " ('cam.acquire_period', 0.25)])" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "adsimdet.stage_sigs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is a python dictionary. We have just added to this. The settings will be applied in the order they have been added, then removed in reverse order after acquisition. Here's what the first two setting mean. The others were described above.\n", "\n", ":value | :meaning\n", "---- | ----\n", "`cam.acquire` | turn off any acquisition in progress\n", "`cam.image_mode` | use single image mode" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Use the *RunEngine* to acquire one image." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "\n", "Transient Scan ID: 1 Time: 2020-05-16 13:59:07\n", "Persistent Unique Scan ID: '931f2b22-4f9c-42f2-9921-122caef4d700'\n", "New stream: 'primary'\n", "+-----------+------------+\n", "| seq_num | time |\n", "+-----------+------------+\n", "| 1 | 13:59:07.9 |\n", "+-----------+------------+\n", "generator count ['931f2b22'] (scan num: 1)\n" ] }, { "data": { "text/plain": [ "('931f2b22-4f9c-42f2-9921-122caef4d700',)" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "RE(bp.count([adsimdet]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Display image from EPICS PV data**\n", "\n", "As noted above, we do not load the image data directly from EPICS PVs at this point for visualization. Recommended practice with Bluesky is to handle this large data as an \n", "external resource using the *databroker*. The file name and address within the file are \n", "stored with data acquisition, then *databroker* is used to access the image data.\n", "\n", "These next cells show how one might get the image data directly from EPICS. There\n", "are several additional aspects to consider to visualize an image in this way:\n", "\n", "* For large image data, it may be necessary to have defined \n", " `EPICS_CA_ARRAY_BYTES` before starting the notebook session \n", " *and* having that value set in the IOC.\n", "* Large images may stretch available resources on the computer that visualizes the data.\n", "* For multi-frame data, the image data may be 3-dimensional.\n", "* For a color camera, the image values should consider all colors and data value size.\n", "* The byte order or bit order may be different.\n", "\n", "Use of the plugin chain to handle the image data is recommended to handle all these aspects,\n", "simplify client-side software, and avoid writing software that is already written.\n", "\n", "First, we would need to add the *image* plugin to our area detector configuration,\n", "then make an instance with this new definition and repeat the configuration steps:\n", "\n", "```\n", "class MySingleTriggerSimDetector(SingleTrigger, SimDetector): \n", " \n", " image = Component(ImagePlugin, suffix=\"image1:\")\n", "\n", "adsimdet = MySingleTriggerSimDetector(_ad_prefix, name='adsimdet')\n", "adsimdet.wait_for_connection()\n", "adsimdet.stage_sigs[\"cam.num_images\"] = 1\n", "adsimdet.stage_sigs[\"cam.acquire_time\"] = 0.1\n", "adsimdet.stage_sigs[\"cam.acquire_period\"] = 0.25\n", "```\n", "\n", "The image comes from EPICS AD as a 1-D array, row by row.\n", "Here, we know it is a 2-D array (in the general case, \n", "we'd to learn that from EPICS).\n", "To make it into a 2-D array, we first need to\n", "get the number of rows and columns from the image plugin.\n", "\n", "```\n", "array_size = adsimdet.image.array_size.get()\n", "shape = (array_size.height, array_size.width)\n", "```\n", "\n", "Now, get the image and make it a 2-D array.\n", "\n", "```\n", "im = adsimdet.image.array_data.get().reshape(shape)\n", "```\n", "\n", "Tell MatPlotLib to show the image.\n", "\n", "```\n", "# show the image\n", "plt.imshow(im)\n", "```\n", "\n", "You could make these steps into a Python function:\n", "\n", "```\n", "def show_ad_image(det):\n", " array_size = det.image.array_size.get()\n", " shape = (array_size.height, array_size.width)\n", " im = det.image.array_data.get().reshape(shape)\n", " plt.imshow(im)\n", "```\n", "\n", "and then call that function:\n", "\n", "```\n", "show_ad_image(adsimdet)\n", "```\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Use HDF file saving plugin\n", "\n", "Use the EPICS Area Detector HDF (HDF5) File saving plugin to \n", "save image(s) to HDF5 file. We'll need more tools from the \n", "ophyd package to configure the plugin." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "from ophyd.areadetector import ADComponent\n", "from ophyd.areadetector import EpicsSignalWithRBV\n", "from ophyd.areadetector import HDF5Plugin\n", "from ophyd.areadetector.filestore_mixins import FileStoreHDF5IterativeWrite" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The first thing we need to do is to modify the existing support\n", "since we had a few problems when developing this tutorial.\n", "These steps could be removed when the problems are fixed.\n", "\n", "* `create_directory_depth` : Allow access to create subdirectories on demand.\n", "* `array_callbacks` : Reveal in ophyd interface.\n", "* `pool_max_buffers` : remove this attribute (set it to `None` instead of using `del`).\n", "* `get_frames_per_point()` : needed by databroker, \n", " returns the number of frames that were received with a \n", " single acquisition." ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [], "source": [ "class MyHDF5Plugin(HDF5Plugin, FileStoreHDF5IterativeWrite):\n", " create_directory_depth = Component(EpicsSignalWithRBV, suffix=\"CreateDirectory\")\n", " array_callbacks = Component(EpicsSignalWithRBV, suffix=\"ArrayCallbacks\")\n", "\n", " pool_max_buffers = None\n", " \n", " def get_frames_per_point(self):\n", " return self.num_capture.get()\n", "\n", " def stage(self):\n", " super().stage()\n", " res_kwargs = {'frame_per_point': self.get_frames_per_point()}\n", " # res_kwargs = {'frame_per_point': self.num_capture.get()}\n", " self._generate_resource(res_kwargs)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We're using an IOC that writes to a different file system than our notebook.\n", "Our IOC is running from a docker container. We tell the HDF5 plugin to write\n", "files to `/tmp/simdet/YEAR/MONTH/DAY/FILENAME.h5` in the IOC's filesystem.\n", "Our docker container mounts that filesystem in directory `/tmp/iocadsky/tmp` to this notebook can access the same files as `/tmp/iocadsky/tmp/simdet/YEAR/MONTH/DAY/FILENAME.h5`.\n", "\n", "Databroker is designed to reference the file locations based on a \n", "directory path relative to some directory. This allows the collected \n", "filesystem to be moved to other directories (such as a copy to take home), \n", "yet still be found by databroker. To enable this, the ophyd support \n", "must be able to separate the directory path into base and relocatable parts.\n", "\n", "In the setup below, we use three variables to define these parts:\n", "\n", "variable | meaning\n", ":---- | :----\n", "`WRITE_HDF5_FILE_PATH` | directory path seen by EPICS area detector IOC\n", "`READ_HDF5_FILE_PATH` | directory path seen by bluesky during data acquisition\n", "`DATABROKER_ROOT_PATH` | base (common part) directory path\n" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [], "source": [ "DATABROKER_ROOT_PATH = \"/tmp/\"\n", "\n", "# note: AD path MUST, must, MUST have trailing \"/\"!!!\n", "# ...and... start with the same path defined in root (above)\n", "\n", "# path as seen by detector IOC\n", "WRITE_HDF5_FILE_PATH = \"/tmp/simdet/%Y/%m/%d/\"\n", "#!!! NOTE !!! This filesystem is on the IOC\n", "\n", "# path as seen by bluesky data acquistion\n", "READ_HDF5_FILE_PATH = \"/tmp/docker_ioc/iocadsky/tmp/simdet/%Y/%m/%d/\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Re-write our custom detector class to include the HDF File Writing plugin. Use our custom plugin support since we modified the support.\n", "\n", "Also, we have added support for the Image plugin so we can, as is common practice, observe the acquired image with a GUI tool such as ImageJ or caQtDM. However, those GUI tools are not part of this tutorial." ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [], "source": [ "class MySingleTriggerSimDetector(SingleTrigger, SimDetector): \n", " \n", " image = Component(ImagePlugin, suffix=\"image1:\")\n", " hdf1 = ADComponent(\n", " MyHDF5Plugin,\n", " suffix='HDF1:', \n", " root=DATABROKER_ROOT_PATH,\n", " write_path_template = WRITE_HDF5_FILE_PATH,\n", " read_path_template = READ_HDF5_FILE_PATH,\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Make an instance of this class. It may not be necessary to add the `wait_for_connection()` command but it is good practice.\n", "\n", "We'll need to configure the HDF plugin for image per capture (it does not get this automatically from the `cam` module)." ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "adsimdet = MySingleTriggerSimDetector(_ad_prefix, name='adsimdet')\n", "adsimdet.wait_for_connection()\n", "adsimdet.stage_sigs[\"cam.num_images\"] = 1\n", "adsimdet.stage_sigs[\"cam.acquire_time\"] = 0.1\n", "adsimdet.stage_sigs[\"cam.acquire_period\"] = 0.25\n", "adsimdet.hdf1.stage_sigs[\"num_capture\"] = 1" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Show the items that will be staged." ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "OrderedDict([('cam.acquire', 0),\n", " ('cam.image_mode', 1),\n", " ('cam.num_images', 1),\n", " ('cam.acquire_time', 0.1),\n", " ('cam.acquire_period', 0.25)])" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "adsimdet.stage_sigs" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "OrderedDict([('enable', 1),\n", " ('auto_increment', 'Yes'),\n", " ('array_counter', 0),\n", " ('auto_save', 'Yes'),\n", " ('num_capture', 1),\n", " ('file_template', '%s%s_%6.6d.h5'),\n", " ('file_write_mode', 'Stream'),\n", " ('capture', 1),\n", " ('blocking_callbacks', 'Yes'),\n", " ('parent.cam.array_callbacks', 1)])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "adsimdet.hdf1.stage_sigs" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just a bit more configuration of the HDF plugin. \n", "\n", "We add it to the `adsimdet.read_attrs` list so that the HDF plugin returns some useful data when `adsimdet` is read during acquistion (by `adsimdet.read()`).\n", "\n", "We allow the HDF plugin to create up to 5 subdirectories when writing the image to an HDF5 file. We need that since we have built the year, month, and date into the file path." ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [], "source": [ "adsimdet.read_attrs.append(\"hdf1\")\n", "if adsimdet.hdf1.create_directory_depth.get() == 0:\n", " # probably not set, so let's set it now to some default\n", " adsimdet.hdf1.create_directory_depth.put(-5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Prime the area detector file writing plugin**\n", "\n", "EPICS AreaDetector file-saving plugins (such as \n", "the HDF plugin) must be primed before they can be \n", "used. Priming must be done in these situations:\n", "\n", "* the IOC has just started\n", "* the image size has changed\n", "\n", "If you do not prime the detector and its plugin chain, *ophyd* will report an *UnprimedPlugin* error like this if you try to trigger (acquire data from) the detector:\n", "\n", "```\n", "UnprimedPlugin: The plugin hdf1 on the area detector with name DETECTOR_NAME has not been primed.\n", "```\n", "\n", "To prime the HDF plugin, call its `warmup()` method." ] }, { "cell_type": "code", "execution_count": 18, "metadata": {}, "outputs": [], "source": [ "enabled = adsimdet.hdf1.enable.get()\n", "adsimdet.hdf1.warmup()\n", "adsimdet.hdf1.enable.put(enabled)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Acquire an image and save it to an HDF5 file. Print out \n", "the name of the file (on the IOC filesystem)." ] }, { "cell_type": "code", "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "frames/point: 1\n", "\n", "\n", "Transient Scan ID: 2 Time: 2020-05-16 13:59:12\n", "Persistent Unique Scan ID: 'b761689f-ec6f-44b5-a862-c9b2ceb3d820'\n", "New stream: 'primary'\n", "+-----------+------------+\n", "| seq_num | time |\n", "+-----------+------------+\n", "| 1 | 13:59:12.9 |\n", "+-----------+------------+\n", "generator count ['b761689f'] (scan num: 2)\n", "/tmp/simdet/2020/05/16/ec0e1c0a-6d32-4f06-8606_000000.h5\n" ] } ], "source": [ "print(f\"frames/point: {adsimdet.hdf1.get_frames_per_point()}\")\n", "RE(bp.count([adsimdet]))\n", "print(adsimdet.hdf1.full_file_name.get())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Show the image\n", "\n", "Now, use *databroker* to retrieve that data and show the image. We imported the `db` symbol (instance of the *databroker*) with the instrument package. The most recent data is accessed using a list-style reference. The symbol `h` is customary to use as a run *header* in reference to the most recent data." ] }, { "cell_type": "code", "execution_count": 20, "metadata": {}, "outputs": [], "source": [ "h = db[-1]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Just to be informative, show all the documents from the most recent data. Look for the *resource* document that describes the details of the image file." ] }, { "cell_type": "code", "execution_count": 21, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "start \n", "Run Start\n", "=========\n", "beamline_id : APS lesson \n", "detectors : ['adsimdet'] \n", "hints :\n", " dimensions : [[['time'], 'primary']] \n", "login_id : prjemian@poof \n", "num_intervals : 0 \n", "num_points : 1 \n", "pid : 31285 \n", "plan_args :\n", " detectors : [\"MySingleTriggerSimDetector(prefix='adsky:', name='adsimdet', read_attrs=['hdf1'], configuration_attrs=['cam', 'cam.acquire_period', 'cam.acquire_time', 'cam.image_mode', 'cam.manufacturer', 'cam.model', 'cam.num_exposures', 'cam.trigger_mode', 'hdf1'])\"]\n", " num : 1 \n", "plan_name : count \n", "plan_type : generator \n", "proposal_id : testing \n", "scan_id : 2 \n", "time : 1589655552.753227 \n", "uid : b761689f-ec6f-44b5-a862-c9b2ceb3d820 \n", "versions :\n", " apstools : 1.2.3 \n", " bluesky : 1.6.0 \n", " databroker : 1.0.2 \n", " epics : 3.4.1 \n", " matplotlib : 3.1.3 \n", " numpy : 1.18.1 \n", " ophyd : 1.5.0 \n", " pyRestTable : 2020.0.2 \n", " spec2nexus : 2021.1.7 \n", "----------------------------------------\n", "descriptor \n", "Event Descriptor\n", "================\n", "configuration :\n", " adsimdet_cam_acq: 0.25 \n", " adsimdet_cam_acq: 0.1 \n", " adsimdet_cam_ima: 1 \n", " adsimdet_cam_man: Simulated detector \n", " adsimdet_cam_mod: Basic simulator \n", " adsimdet_cam_num: 1 \n", " adsimdet_cam_tri: 0 \n", " adsimdet_cam_acq: 1589655552.194608 \n", " adsimdet_cam_acq: 1589655552.194 \n", " adsimdet_cam_ima: 1589655552.193175 \n", " adsimdet_cam_man: 1589655512.975452 \n", " adsimdet_cam_mod: 1589655512.975456 \n", " adsimdet_cam_num: 1589655512.975577 \n", " adsimdet_cam_tri: 1589655512.975629 \n", " source : PV:adsky:cam1:AcquirePeriod_RBV \n", " dtype : number \n", " shape : [] \n", " units : \n", " lower_ctrl_limit: 0.0 \n", " upper_ctrl_limit: 0.0 \n", " precision : 3 \n", " source : PV:adsky:cam1:AcquireTime_RBV \n", " dtype : number \n", " shape : [] \n", " units : \n", " lower_ctrl_limit: 0.0 \n", " upper_ctrl_limit: 0.0 \n", " precision : 3 \n", " source : PV:adsky:cam1:ImageMode_RBV \n", " dtype : integer \n", " shape : [] \n", " units : None \n", " lower_ctrl_limit: None \n", " upper_ctrl_limit: None \n", " enum_strs : ['Single', 'Multiple', 'Continuous'] \n", " source : PV:adsky:cam1:Manufacturer_RBV \n", " dtype : string \n", " shape : [] \n", " units : None \n", " lower_ctrl_limit: None \n", " upper_ctrl_limit: None \n", " source : PV:adsky:cam1:Model_RBV \n", " dtype : string \n", " shape : [] \n", " units : None \n", " lower_ctrl_limit: None \n", " upper_ctrl_limit: None \n", " source : PV:adsky:cam1:NumExposures_RBV \n", " dtype : integer \n", " shape : [] \n", " units : \n", " lower_ctrl_limit: 0 \n", " upper_ctrl_limit: 0 \n", " source : PV:adsky:cam1:TriggerMode_RBV \n", " dtype : integer \n", " shape : [] \n", " units : None \n", " lower_ctrl_limit: None \n", " upper_ctrl_limit: None \n", " enum_strs : ['Internal', 'External'] \n", "+----------------+-------+------------+-------------+-----------------+-----------+\n", "| data keys | dtype | external | object_name | shape | source |\n", "+----------------+-------+------------+-------------+-----------------+-----------+\n", "| adsimdet_image | array | FILESTORE: | adsimdet | [1024, 1024, 0] | PV:adsky: |\n", "+----------------+-------+------------+-------------+-----------------+-----------+\n", "hints :\n", " fields : [] \n", "name : primary \n", "object_keys :\n", " adsimdet : ['adsimdet_image'] \n", "run_start : b761689f-ec6f-44b5-a862-c9b2ceb3d820 \n", "time : 1589655552.9516096 \n", "uid : 835db081-889b-4b4e-b21e-98950d018b54 \n", "----------------------------------------\n", "resource \n", "Resource\n", "========\n", "path_semantics : posix \n", "resource_kwargs :\n", " frame_per_point : 1 \n", "resource_path : docker_ioc/iocadsky/tmp/simdet/2020/05/16/ec0e1c0a-6d32-4f06-8606_000000.h5\n", "root : /tmp \n", "run_start : b761689f-ec6f-44b5-a862-c9b2ceb3d820 \n", "spec : AD_HDF5 \n", "uid : 43f0b39c-3f34-44c0-b815-ff2cc4c7d167 \n", "----------------------------------------\n", "resource \n", "Resource\n", "========\n", "path_semantics : posix \n", "resource_kwargs :\n", " frame_per_point : 1 \n", "resource_path : docker_ioc/iocadsky/tmp/simdet/2020/05/16/ec0e1c0a-6d32-4f06-8606_000000.h5\n", "root : /tmp \n", "run_start : b761689f-ec6f-44b5-a862-c9b2ceb3d820 \n", "spec : AD_HDF5 \n", "uid : a33d7a48-b751-4a4d-82fd-76bf9f544011 \n", "----------------------------------------\n", "datum \n", "Datum\n", "=====\n", "datum_id : a33d7a48-b751-4a4d-82fd-76bf9f544011/0 \n", "datum_kwargs :\n", " point_number : 0 \n", "resource : a33d7a48-b751-4a4d-82fd-76bf9f544011 \n", "----------------------------------------\n", "event \n", "Event\n", "=====\n", "data :\n", " adsimdet_image : a33d7a48-b751-4a4d-82fd-76bf9f544011/0 \n", "descriptor : 835db081-889b-4b4e-b21e-98950d018b54 \n", "filled :\n", " adsimdet_image : False \n", "seq_num : 1 \n", "time : 1589655552.9566658 \n", "timestamps :\n", " adsimdet_image : 1589655552.7591739 \n", "uid : e1570df6-c114-48f8-9491-587b541939d8 \n", "----------------------------------------\n", "stop \n", "Run Stop\n", "========\n", "exit_status : success \n", "num_events :\n", " primary : 1 \n", "reason : \n", "run_start : b761689f-ec6f-44b5-a862-c9b2ceb3d820 \n", "time : 1589655552.9572377 \n", "uid : 3a76df5b-502d-48c1-a934-28cd38a02807 \n", "----------------------------------------\n" ] } ], "source": [ "for entry in h.documents():\n", " key, doc = entry\n", " print(key, doc)\n", " print(\"-\"*40)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Show the image the last data with matplotlib." ] }, { "cell_type": "code", "execution_count": 22, "metadata": { "scrolled": true }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 22, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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", "image/svg+xml": [ "\n", "\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "\n" ], "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "# get the MatPlotLib tool\n", "from instrument.mpl import plt\n", "\n", "plt.imshow(h.xarray().adsimdet_image[0][0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The structure of the HDF5 file as reported by the \n", "punx program (https://punx.readthedocs.io):\n", "\n", "```\n", " entry:NXentry\n", " data:NXdata\n", " data:NX_UINT8[1,1024,1024] = [ ... ]\n", " instrument:NXinstrument\n", " NDAttributes:NXcollection\n", " NDArrayEpicsTSSec:NX_UINT32 = 958492486\n", " NDArrayEpicsTSnSec:NX_UINT32 = 334947107\n", " NDArrayTimeStamp:NX_FLOAT64 = 958492486.2348573\n", " NDArrayUniqueId:NX_INT32 = 3\n", " detector:NXdetector\n", " data:NX_UINT8[1,1024,1024] = [ ... ]\n", " NDAttributes:NXcollection\n", " ColorMode:NX_INT32 = 0\n", " performance\n", " timestamp:NX_FLOAT64[1,5] = [ ... ]\n", "```\n", "\n", "With attributes shown:\n", "\n", "```\n", " entry:NXentry\n", " @NX_class = NXentry\n", " data:NXdata\n", " @NX_class = NXdata\n", " data:NX_UINT8[1,1024,1024] = [ ... ]\n", " @NDArrayDimBinning = 1\n", " @NDArrayDimOffset = 0\n", " @NDArrayDimReverse = 0\n", " @NDArrayNumDims = 2\n", " @signal = 1\n", " instrument:NXinstrument\n", " @NX_class = NXinstrument\n", " NDAttributes:NXcollection\n", " @NX_class = NXcollection\n", " @hostname = poof\n", " NDArrayEpicsTSSec:NX_UINT32 = 958492486\n", " @NDAttrDescription = The NDArray EPICS timestamp seconds past epoch\n", " @NDAttrName = NDArrayEpicsTSSec\n", " @NDAttrSource = Driver\n", " @NDAttrSourceType = NDAttrSourceDriver\n", " NDArrayEpicsTSnSec:NX_UINT32 = 334947107\n", " @NDAttrDescription = The NDArray EPICS timestamp nanoseconds\n", " @NDAttrName = NDArrayEpicsTSnSec\n", " @NDAttrSource = Driver\n", " @NDAttrSourceType = NDAttrSourceDriver\n", " NDArrayTimeStamp:NX_FLOAT64 = 958492486.2348573\n", " @NDAttrDescription = The timestamp of the NDArray as float64\n", " @NDAttrName = NDArrayTimeStamp\n", " @NDAttrSource = Driver\n", " @NDAttrSourceType = NDAttrSourceDriver\n", " NDArrayUniqueId:NX_INT32 = 3\n", " @NDAttrDescription = The unique ID of the NDArray\n", " @NDAttrName = NDArrayUniqueId\n", " @NDAttrSource = Driver\n", " @NDAttrSourceType = NDAttrSourceDriver\n", " detector:NXdetector\n", " @NX_class = NXdetector\n", " data:NX_UINT8[1,1024,1024] = [ ... ]\n", " @NDArrayDimBinning = 1\n", " @NDArrayDimOffset = 0\n", " @NDArrayDimReverse = 0\n", " @NDArrayNumDims = 2\n", " @signal = 1\n", " NDAttributes:NXcollection\n", " @NX_class = NXcollection\n", " ColorMode:NX_INT32 = 0\n", " @NDAttrDescription = Color mode\n", " @NDAttrName = ColorMode\n", " @NDAttrSource = Driver\n", " @NDAttrSourceType = NDAttrSourceDriver\n", " performance\n", " timestamp:NX_FLOAT64[1,5] = [ ... ]\n", "```\n" ] } ], "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.7-final" } }, "nbformat": 4, "nbformat_minor": 4 }