Skip to content

Commit

Permalink
DOC #301 (#302)
Browse files Browse the repository at this point in the history
  • Loading branch information
prjemian committed Apr 29, 2024
1 parent 800519c commit 8277b81
Showing 1 changed file with 351 additions and 0 deletions.
351 changes: 351 additions & 0 deletions docs/source/howto/_epics_proc_field.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,351 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Trigger a Device with the EPICS record .PROC field\n",
"\n",
"The EPICS `.PROC` field is one of the fields\n",
"[common](https://epics-base.github.io/epics-base/dbCommonRecord.html) to all\n",
"EPICS records. It tells the IOC's database to execute the standard actions for\n",
"that record's data. When the record is in `Passive` [scan\n",
"mode](https://docs.epics-controls.org/en/latest/process-database/EPICS_Process_Database_Concepts.html#scanning-specification),\n",
"sending a `1` value to the `.PROC` field *processes* the record.\n",
"\n",
"EPICS record processing is similar to the ophyd `trigger()`\n",
"[method](https://github.com/bluesky/ophyd/blob/5c03c3fff974dc6390836fc83dae4c247a35e662/ophyd/device.py#L1438-L1439)\n",
"which tells the [Device](https://github.com/bluesky/ophyd/blob/5c03c3fff974dc6390836fc83dae4c247a35e662/ophyd/device.py#L780-L784) to run its data acquisition method."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from ophyd import Component, Device, EpicsSignal"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's make a custom ophyd `Device`, limiting our attention only to the fields of interest for this howto guide.\n",
"\n",
"field | description\n",
"---- | ----\n",
"`.A` | The *a* value.\n",
"`.CLCA` | The calculation to produce a new *A* value when the record is processed.\n",
"`.PROC` | Send a `1` to this field to process the record.\n",
"`.SCAN` | The record's scan mode selection.\n",
"\n",
"Here, we add the `trigger_value` [keyword argument](https://github.com/bluesky/ophyd/blob/master/ophyd/device.py#L139-L141). **This** is how we send a `1` to the `.PROC` field when the Device is triggered.\n",
"\n",
"It is worth commenting about the `kind` keyword value. The [kind](https://blueskyproject.io/ophyd/user/reference/signals.html#kind) attribute is the means to identify a signal that is relevant for handling by a callback.\n",
"\n",
"kind | usage\n",
"---- | ----\n",
"hinted | attribute should be reported by `.read()`\n",
"config | value is metadata, should be reported by `.read_configuration()`\n",
"omitted | value is not reportable"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"class Transform(Device):\n",
" a = Component(EpicsSignal, \".A\", kind=\"hinted\")\n",
" calc_a = Component(EpicsSignal, \".CLCA\", kind=\"config\", string=True)\n",
" process_record = Component(EpicsSignal, \".PROC\", kind=\"omitted\", trigger_value=1)\n",
" scan_mode = Component(EpicsSignal, \".SCAN\", kind=\"config\", string=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Create an ophyd object and connect it with EPICS."
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"xform = Transform(\"gp:userTran11\", name=\"xform\")\n",
"xform.wait_for_connection()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Print the summary ophyd of the Device."
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"data keys (* hints)\n",
"-------------------\n",
"*xform_a\n",
"\n",
"read attrs\n",
"----------\n",
"a EpicsSignal ('xform_a')\n",
"\n",
"config keys\n",
"-----------\n",
"xform_calc_a\n",
"xform_scan_mode\n",
"\n",
"configuration attrs\n",
"-------------------\n",
"calc_a EpicsSignal ('xform_calc_a')\n",
"scan_mode EpicsSignal ('xform_scan_mode')\n",
"\n",
"unused attrs\n",
"------------\n",
"process_record EpicsSignal ('xform_process_record')\n",
"\n"
]
}
],
"source": [
"xform.summary()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Show the values as they exist now using the `.read()` method."
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"xform.read()=OrderedDict([('xform_a', {'value': 2.0, 'timestamp': 1714336346.373808})])\n"
]
}
],
"source": [
"print(f\"{xform.read()=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Tell ophyd to trigger the Device (which tells the transform record to process) using the `.trigger()` method.\n",
"\n",
"Note that only the *a* value is reported. All other attributes are either\n",
"configuration or not reportable (such as `process_record`)."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"xform.read()=OrderedDict([('xform_a', {'value': 3.0, 'timestamp': 1714337169.963434})])\n"
]
}
],
"source": [
"xform.trigger()\n",
"print(f\"{xform.read()=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Reset the Device before we demonstrate."
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"xform.read()=OrderedDict([('xform_a', {'value': 0.0, 'timestamp': 1714337169.970021})])\n"
]
}
],
"source": [
"xform.calc_a.put(\"\")\n",
"xform.a.put(0)\n",
"xform.scan_mode.put(\"Passive\")\n",
"print(f\"{xform.read()=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define the calculation to run (increment *a*) each time the record is processed."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"xform.calc_a.put(\"A+1\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Print the value before triggering (processing), trigger the, then print the\n",
"value afterwards. We expect the value will increment by `1`."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"xform.read()=OrderedDict([('xform_a', {'value': 0.0, 'timestamp': 1714337169.970021})])\n",
"xform.read()=OrderedDict([('xform_a', {'value': 1.0, 'timestamp': 1714337169.982637})])\n"
]
}
],
"source": [
"print(f\"{xform.read()=}\")\n",
"xform.trigger()\n",
"print(f\"{xform.read()=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's do the same thing in a bluesky plan. First, we need some parts from the bluesky package. These are the most basic parts:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [],
"source": [
"from bluesky import RunEngine\n",
"from bluesky import plan_stubs as bps\n",
"\n",
"RE = RunEngine()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Define the bluesky plan. Instead of calling the Device's `.trigger()` method\n",
"directly, we let the RunEngine\n",
"[handle](https://github.com/bluesky/bluesky/blob/main/src/bluesky/plan_stubs.py#L447-L449)\n",
"that task (with `bps.trigger()`), in case the device takes some time to\n",
"complete its trigger action(s)."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [],
"source": [
"def plan():\n",
" print(f\"{xform.read()=}\")\n",
" yield from bps.trigger(xform)\n",
" print(f\"{xform.read()=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Run the plan."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"xform.read()=OrderedDict([('xform_a', {'value': 1.0, 'timestamp': 1714337169.982637})])\n",
"xform.read()=OrderedDict([('xform_a', {'value': 2.0, 'timestamp': 1714337170.147542})])\n"
]
},
{
"data": {
"text/plain": [
"()"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"RE(plan())"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "bluesky_2024_2",
"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.11.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}

0 comments on commit 8277b81

Please sign in to comment.