{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Custom Callbacks\n", "\n", "## Configuration" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%matplotlib widget\n", "import matplotlib.pyplot as plt\n", "\n", "# Make plots live-update while scans run.\n", "from bluesky.utils import install_nb_kicker\n", "install_nb_kicker()\n", "\n", "import numpy as np\n", "from bluesky import RunEngine\n", "from bluesky.plans import scan\n", "from bluesky.examples import motor, noisy_det\n", "\n", "RE = RunEngine({})" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data Acquisition\n", "\n", "### Simple Custom Callbacks" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# No callbacks\n", "RE(scan([noisy_det], motor, 1, 5, 5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Print the type of document as each one is emitted.\n", "\n", "def cb(name, doc):\n", " print(name)\n", "\n", "RE(scan([noisy_det], motor, 1, 5, 5), cb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Print the event documents as they are emitted.\n", "\n", "def cb(name, doc):\n", " if name == 'event':\n", " print(doc)\n", "\n", "RE(scan([noisy_det], motor, 1, 5, 5), cb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Make a simple table with sequence number, motor setpoint, and detector reading.\n", "\n", "def cb(name, doc):\n", " if name == 'event':\n", " print(doc['seq_num'], doc['data']['motor_setpoint'], doc['data']['noisy_det'])\n", "\n", "RE(scan([noisy_det], motor, 1, 5, 5), cb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Compute the duration between the 'start' document and the 'stop' document.\n", "# Version 1 -- using a global variable (simple, but not recommended)\n", "\n", "start_time = None\n", "\n", "def cb(name, doc):\n", " global start_time\n", " if name == 'start':\n", " start_time = doc['time']\n", " if name == 'stop':\n", " stop_time = doc['time']\n", " duration = stop_time - start_time\n", " print('Duration:', duration, 'seconds')\n", "\n", "RE(scan([noisy_det], motor, 1, 5, 5), cb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# Compute the duration between the 'start' document and the 'stop' document.\n", "# Version 2 -- using a class variable (recommended)\n", "\n", "from bluesky.callbacks import CallbackBase\n", "\n", "\n", "class Timer(CallbackBase):\n", " def start(self, doc):\n", " self.start_time = doc['time']\n", " def stop(self, doc):\n", " stop_time = doc['time']\n", " duration = stop_time - self.start_time\n", " print('Duration:', duration, 'seconds')\n", "\n", "RE(scan([noisy_det], motor, 1, 5, 5), Timer())" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Binding Callbacks to Plans" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "from bluesky.preprocessors import subs_decorator\n", "\n", "\n", "@subs_decorator(cb)\n", "def my_scan(detectors, motor, start, stop, num):\n", " yield from scan(detectors, motor, start, stop, num)\n", "\n", "RE(my_scan([noisy_det], motor, 1, 5, 5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "# A useful pattern: Pass positional and keyword arguments through, blindly.\n", "\n", "@subs_decorator(cb)\n", "def my_scan(*args, **kwargs):\n", " yield from scan(*args, **kwargs)\n", "\n", "RE(my_scan([noisy_det], motor, 1, 5, 5))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Exercises\n", "\n", "1. Write a custom callback that prints the detector reading divided by the motor position.\n", "2. Use `subs_decorator` to bind it to a custom variant of the `scan` plan.\n", "3. Write a custom callback that prints the contents of the start document. Then, if you can, make the output more readable by put each key/value pair on its own line." ] }, { "cell_type": "code", "execution_count": null, "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.6.6" } }, "nbformat": 4, "nbformat_minor": 2 }