{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Good Morning Bluesky: Starting your experiment\n", "\n", "In this notebook you will:\n", "\n", "* Start your virtual bluesky session \n", " * akin to `bsui` in a beamline computer terminal session\n", "* Configure custom metadata for your experiment\n", "* Use three common experimental procedures (\"plans\") that are built into bluesky\n", "* Learn about the bluesky RunEngine states\n", "\n", "\n", "Recommend Prerequisites:\n", "\n", "* [Hello Python and Jupyter](./Hello%20Python%20and%20Jupyter.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true, "tags": [] }, "outputs": [], "source": [ "#pip install -U --pre databroker[all]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hosted by Andi " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Disclaimer: This tutorial uses bluesky in its \"out-of-the-box\" installation, which should work at any bluesky beamline. \n", "
\n", "\n", "\n", "However, bluesky offers lots of flexiblity and often beamline staff want to further customize bluesky for the majority of their users.\n", "\n", "\n", "Other beamlines like the flexibility and choose to largely rely on lower level aquistion plans." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Start Bluesky\n", "Below, setup the \"beamline\" configuration or profile.\n", "* the beamlines, being more complex, are automaticaly configured using the beamline profile\n", "* [examples of NSLS-II beamline profiles](https://github.com/NSLS-II/profile-collection-ci)\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "%run -i gm_user/user_profile.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Is bluesky alive and waiting on you? \n", "\n", "```python\n", "RE.state\n", "```\n", "\n", "The cell should return:\n", "```\n", "'idle'\n", "```\n", "\n", "\n", "
If you see an error \n", "\n", " \n", "and it is\n", "```\n", "NotImplementedError: databroker 2.0.0 does not yet support 'temp' Broker\n", "\n", "```\n", "\n", "Then scroll up, uncomment, and run\n", "```python\n", "pip install -U --pre databroker[all]\n", "\n", "```\n", " \n", "Then restart your kernel as suggested (Select Kernel, Restart Kernel)." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "RE.state" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There are other states and manual ways to control the state of the **R**un**E**ngine. We will learn about those in this notebook." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Customize\n", "Now lets add customized RE metadata by editing [gm_user/user_startup.py](./gm_user/user_startup.py).\n", "\n", "
\n", "Caution: Some beamlines have their own custom functions for this task and so this this python file is not needed. Or sometimes beamlines use reserved key names that are not \"protected\". Always ask first.\n", "
\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%run -i gm_user/user_startup.py" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Confirm that your persistent metadata is as you like it.\n", "\n", "```python\n", "RE.md\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "RE.md" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ok, but that is hard to read. \n", "\n", "\n", "\n", "- What things do you know about python dictionaries that you can apply here?\n", "- Did you notice the convience function in [gm_user/user_startup.py](./gm_user/user_startup.py)?\n", "\n", "\n", "
Copy Paste Code\n", "\n", "```python\n", "list(RE.md)\n", "\n", "RE.md.keys()\n", "\n", "RE.md[\"instrument\"]\n", "\n", "md_info()\n", "\n", "```\n", "
\n", "\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since the start of most experiments are setup and alignment, lets label all the data as such. \n", "```python\n", "RE.md[\"purpose\"] = \"setup\"\n", "\n", "```\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "RE.md[\"purpose\"] = \"setup\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "md_info()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data Acquisition\n", "\n", "### Executing a `count` plan with various parameters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In the example below, the Bluesky RE consmumes the plan `count()`. `count()` is an experiment plan used here to acquire one reading from a detector.\n", "\n", "In this case, `det` or `noisy_det` is are point detectors. We will start with `noisy_det`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "RE(count([noisy_det]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The returned value above is a list of the run IDs that uniquely identify this data set (`uid`'s). The \"scan number\" (`scan_id`) is easier to remember but is not good for long-term reference because it may not be unique.\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "What else can `count` do to make your experiment better?\n", "\n", "**Hint:** `count` is like any other python function. You can view it's documentation in this notebook.\n", "\n", "
Copy Paste Code\n", "\n", "```python\n", "help(count)\n", "\n", "count?\n", "\n", "count??\n", "\n", "```\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true, "tags": [] }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's just get 5 readings for count" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "nbsphinx": "hidden" }, "outputs": [], "source": [ "# five consecutive readings\n", "RE(count([noisy_det], num=5))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Scan\n", "\n", "Scan `motor` from -10 to 10, stopping at 15 equally-spaced points and reading `noisy_det` at each point." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "RE(scan([noisy_det], motor, -10, 10, 15))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "How do we know where `motor` is now?\n", "\n", "[Bluesky magics](https://blueskyproject.io/bluesky/magics.html) (specific magics just for bluesky) can help us find the motor position" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "%wa " ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hosted by Josh" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Or interrogating the ophyd object's read attributes or `read_attrs`." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "motor" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "motor.readback" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "motor.readback.get()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "motor.readback.read()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**QUESTION:** What is the difference between `.read()` and `.get()`?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": { "jp-MarkdownHeadingCollapsed": true, "tags": [] }, "source": [ "Hosted by Andi " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Move\n", "\n", "Bluesky has lower level plans (stub plans aka `bluesky.plan_stubs`). This module contains smaller plans that can be used alone or as buildling blocks for larger plans.\n", "\n", "Moving a motor (any other \"set-able\" object) can be accomplished with `mv`. \n", "\n", "Try to move `motor` to the maximum detector value for the previous scan.\n", "
Copy Paste Solution\n", " \n", "```python\n", "\n", "RE(mv(motor,0))\n", "```\n", "
" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true, "tags": [] }, "outputs": [], "source": [ "### Complete the line below\n", "RE(mv(motor,))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Improving the measurement \n", "\n", "The `motor` scan was noisy. We can think of two ways to improve this:\n", "- more points\n", "- longer measurement time (less noise)\n", "\n", "Let's try less noise. \n", "\n", "\n", "Let's inspect the device to see the options:" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "noisy_det" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Since this isn't a real detector, we cannot increase the `acquire_time`. What other configuration attributes (`config_attrs`) can we adjust?" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "noisy_det.noise_multiplier.get()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's move `noisy_det.noise_multiplier` to 0.001 and count again.\n", "\n", "\n", "```python\n", "\n", "RE(mv(noisy_det.noise_multiplier, 0.001))\n", "\n", "RE(scan([noisy_det], motor, -10, 10, 15))\n", "```\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's now try the following:\n", "1. move `noisy_det.noise_multiplier` back to 0.1\n", "2. do a finer scan ( +/- 10 degrees with 1 degree step size)\n", "3. move `motor` to 0\n", "\n", "\n", "\n", "
Copy Paste Solution\n", "\n", "```python\n", "\n", "RE(mv(noisy_det.noise_multiplier, 0.1))\n", "\n", "RE(scan([noisy_det], motor, -10, 10, 21))\n", "\n", "RE(mv(motor, 0))\n", "```\n", "
\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Watch Out for a DAQ Trap #1: \n", "
\n", "\n", "Try:\n", "```python\n", "scan?\n", "```\n", "\n", "The last argument of `scan()` is num \n", "\n", "```\n", "num : integer\n", " number of points\n", "```\n", "\n", "Bluesky functions works always on the concept of number of points, not number of steps.\n", "```python\n", "int(20/1+1)\n", "```\n", "```\n", "21\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Watch Out for a DAQ Trap #2: \n", "
\n", "\n", "It is natural to do the following for experienced researchers that visit many facilities:\n", "```python\n", "RE(mv(noisy_det.noise_multiplier, 0.1)); RE(scan([noisy_det], motor, -10, 10, 21)); RE(mv(motor, 0))\n", "```\n", "\n", "It will work. **However**, if you have long count times or fast moving motors you may not be able to stop in time. \n", "\n", "For predictable performance of bluesky, the above is not recommended.\n", "\n", "In our next notebook, we will learn the recommended methods for assembling larger plans.\n", "\n", "But first, lets see what happens when we stop the RE." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hosted by Josh" ] }, { "cell_type": "markdown", "metadata": { "tags": [] }, "source": [ "## Interupt the RE\n", "\n", "At the beamline using a terminal window, there are two ways to interupt the RunEngine.\n", "\n", "- Interupt **immediately**: `Cntl C` `Cntl C`\n", "\n", "- Interupt at the next convient time for the RE: `Cntl C`\n", "\n", "\n", "But in a jupyter notebook, you must press the stop button (1 or 2 times). \n", "\n", "Start the scan, interupt the RE and instruct it what to do next." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "Bluesky Feature: count() is highly configurable.\n", "
\n", "\n", "collect data every 3 seconds\n", "```python\n", "delay = 3\n", "```\n", "\n", "infite timescan\n", "```python\n", "num = None\n", "```" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true, "tags": [] }, "outputs": [], "source": [ "RE(count([noisy_det], num = None, delay=3))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "tags": [] }, "outputs": [], "source": [ "RE.state" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true, "tags": [] }, "outputs": [], "source": [ "RE.stop()\n", "#RE.abort()\n", "#RE.halt()\n", "#RE.resume()" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "db[-1].stop[\"exit_status\"]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Questions about the above?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## What's next\n", "\n", "\n", "\n", "* [Good Afternoon Bluesky](./Good%20Afternoon%20Bluesky.ipynb)" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "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.9.13" } }, "nbformat": 4, "nbformat_minor": 4 }