Skip to content

Commit

Permalink
Modify jupyter notebook to import from main script
Browse files Browse the repository at this point in the history
  • Loading branch information
8ryn committed Aug 23, 2023
1 parent c3f2060 commit 4498e84
Showing 1 changed file with 6 additions and 270 deletions.
276 changes: 6 additions & 270 deletions src/tomoscan/setup.ipynb
Original file line number Diff line number Diff line change
@@ -1,225 +1,12 @@
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import time as ttime\n",
"\n",
"from bluesky.plans import count, scan\n",
"from ophyd import EpicsSignal"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here the ophyd areadetector classes are setup:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ophyd.areadetector.filestore_mixins import FileStoreHDF5IterativeWrite\n",
"from ophyd.areadetector.plugins import HDF5Plugin_V34\n",
"from ophyd import SingleTrigger, AreaDetector, ADComponent\n",
"from ophyd.areadetector import cam\n",
"\n",
"class MyHDF5Plugin(FileStoreHDF5IterativeWrite, HDF5Plugin_V34):\n",
" ...\n",
"\n",
"\n",
"class MyDetector(SingleTrigger, AreaDetector):\n",
" cam = ADComponent(cam.AreaDetectorCam, \"CAM:\")\n",
" hdf1 = ADComponent(\n",
" MyHDF5Plugin,\n",
" \"HDF1:\",\n",
" write_path_template=\"/out/%Y/%m/%d/\",\n",
" #read_path_template=\"/home/bar/Projects/tomoscan/data/%Y/%m/%d/\",\n",
" read_path_template=\"/home/jovyan/data/%Y/%m/%d/\"\n",
" \n",
" )"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from ophyd import Device, Component, EpicsSignalRO\n",
"\n",
"class MyLaser(Device):\n",
" power = Component(EpicsSignalRO, \"laser:power\")\n",
" pulse_id = Component(EpicsSignalRO, \"EPAC-DEV:PULSE:PULSE_ID\", name=\"pulse_id\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The next code block defines a function used to poll PVs until they take a particular value.\n",
"This function should be a temporary measure and a more streamlined approach monitoring the PV integrated proerly with Bluesky/Ophyd is hoped to be used in the future."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def wait_for_value(signal: EpicsSignal, value, poll_time=0.01, timeout=10):\n",
" expiration_time = ttime.time() + timeout\n",
" current_value = signal.get()\n",
" while current_value != value:\n",
" # ttime.sleep(poll_time)\n",
" yield from bps.sleep(poll_time)\n",
" if ttime.time() > expiration_time:\n",
" raise TimeoutError(\n",
" \"Timed out waiting for %r to take value %r after %r seconds\"\n",
" % (signal, value, timeout)\n",
" )\n",
" current_value = signal.get()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This custom plan moves the motor and then waits for the laser pulse before taking the next reading."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from bluesky.plan_stubs import mv\n",
"import bluesky.plan_stubs as bps\n",
"\n",
"def pulse_sync(detectors, motor, laser, start, stop, steps):\n",
" step_size = (stop - start) / (steps - 1)\n",
"\n",
" for det in detectors:\n",
" yield from bps.stage(det)\n",
"\n",
" yield from bps.open_run()\n",
" for i in range(steps):\n",
" yield from bps.checkpoint() # allows pausing/rewinding\n",
" yield from mv(motor, start + i * step_size)\n",
" yield from wait_for_value(\n",
" laser.power, 0, poll_time=0.01, timeout=10\n",
" ) # Want to be at 0 initially such that image taken on pulse\n",
" yield from wait_for_value(laser.power, 1, poll_time=0.001, timeout=10)\n",
" yield from bps.trigger_and_read(list(detectors) + [motor] + [laser])\n",
" yield from bps.close_run()\n",
"\n",
" for det in detectors:\n",
" yield from bps.unstage(det)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This custom plan moves the motor based on the detector status. It is designed to be used when the detector is being directly triggered outside of bluesky."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def passive_scan(detectors, motor, start, stop, steps, adStatus, pulse_ID):\n",
" step_size = (stop - start) / (steps - 1)\n",
"\n",
" yield from mv(motor, start) # Move motor to starting position since may take time\n",
"\n",
" yield from bps.open_run()\n",
"\n",
" for det in detectors:\n",
" yield from bps.stage(det)\n",
"\n",
" for i in range(steps):\n",
" yield from mv(motor, start + i * step_size)\n",
" yield from bps.checkpoint()\n",
" yield from wait_for_value(adStatus, 2, poll_time=0.001, timeout=10)\n",
" yield from bps.trigger_and_read([motor] + [pulse_ID])\n",
" yield from wait_for_value(adStatus, 0, poll_time=0.001, timeout=10)\n",
"\n",
" for det in detectors:\n",
" yield from bps.unstage(det)\n",
"\n",
" yield from bps.close_run()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Here we initialise the detector object. \n",
"This will give an error saying that caRepeater couldn't be located, this is not an issue. A second related error message may later appear which can also be ignored."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"prefix = \"ADT:USER1:\"\n",
"det = MyDetector(prefix, name=\"det\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The detector's HDF plugin is then set to create the necessary output directory if it does not exist and the detector is primed.\n",
"The plugin's \"kind\" is required to be set to 3 such that the resulting HDF files are accessible via the databroker."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"det.hdf1.create_directory.put(-5)\n",
"det.hdf1.warmup()\n",
"det.hdf1.kind = 3 # config | normal, required to include images in run documents"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The camera's stage signatures are area detector configurations which are set whenever the detector is staged within Bluesky."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"det.cam.stage_sigs[\"image_mode\"] = \"Multiple\"\n",
"det.cam.stage_sigs[\"acquire_time\"] = 0.05\n",
"det.cam.stage_sigs[\"num_images\"] = 1"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The motor and laser objects are created. In the case of the laser we wait for the PVs to connect succesfully."
"First the detector, laser and motor are setup along with the bluesky environment from the ophyd_inter_setup file.\n",
"Due to the different file structure of the Jupyter notebook the read path must be updated.\n",
"An error related to caRepeater will likely appear, this is not a concern."
]
},
{
Expand All @@ -228,59 +15,15 @@
"metadata": {},
"outputs": [],
"source": [
"from ophyd import EpicsMotor\n",
"\n",
"motor1 = EpicsMotor(\"motorS:axis1\", name=\"motor1\")\n",
"laser1 = MyLaser(\"\", name=\"laser1\")\n",
"laser1.wait_for_connection()"
"from ophyd_inter_setup import *\n",
"det.hdf1.read_path_template = \"/home/jovyan/data/%Y/%m/%d/\" "
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We load the Bluesky run engine and subscribe the best effort callback. The best effort callback aims to print and plot useful information as scans are performed."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from bluesky import RunEngine\n",
"from bluesky.callbacks.best_effort import BestEffortCallback\n",
"\n",
"RE = RunEngine()\n",
"bec = BestEffortCallback()\n",
"RE.subscribe(bec)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The databroker is linked to the running mongoDB database and the run engine is set to insert all data captured to the databroker."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import databroker\n",
"\n",
"catalog = databroker.catalog[\"mongo\"]\n",
"RE.subscribe(catalog.v1.insert)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As a first example run this synced scan which takes 11 readings at intervals between motor positions of -10 and +10\n",
"This will also generate a table and a plot of the motor position. In this case the plot does not show much information."
"The synced scan can then be run. This example scans in 11 steps between -10 and +10."
]
},
{
Expand Down Expand Up @@ -327,13 +70,6 @@
"frame = image[0][0] # Index 1 refers to the time of the image and the second index refers to the frame number\n",
"frame.plot.pcolormesh()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down

0 comments on commit 4498e84

Please sign in to comment.