General Plans
ibex_bluesky_core
provides a number of plans that can be run by the RunEngine directly. These are mostly thin wrappers around the generic bluesky plans
All of these plans can be used directly by the RunEngine (RE()
) or within a wrapper of your own that yields from them (yield from
)
So you can do this:
result = RE(refl_scan("S1VG", 1, 10, 21, model=Gaussian().fit() frames=500, det=100, mon=3, pixel_range=6, periods=True, save_run=False))
or this:
from ibex_bluesky_core.plans.reflectometry import refl_scan
def my_plan():
... # Some stuff before scan
icc = (yield from refl_scan("S1VG", 1, 10, 21, model=Gaussian().fit() frames=500, det=100, mon=3, pixel_range=6, periods=True, save_run=False))
... # Some stuff after scan
Return values
The scanning plans documented on this page will return an ISISCallbacks
instance, which gives results of fits, centre of masses etc. - for example in your own plan if you wanted to print the fit result and the centre of mass:
from ibex_bluesky_core.plans import motor_scan
def my_plan():
icc = (yield from motor_scan("MyBlock1", 1, 10, 21, model=Gaussian().fit() frames=500, det=100, mon=3, pixel_range=6, periods=True, save_run=False))
print(icc.live_fit.result.fit_report())
print(f"COM: {icc.peak_stats['com']}")
Lower-level plans
These take “devices” so you can pass your own DAE object and a movable/readable but use a standard set of callbacks for plotting, fitting and log file writing. These are designed to allow flexibility such as more in-depth DAE customisation, block configuration ie write tolerances, settle times.
scan
- this is for a absolute/relative scan.
adaptive_scan
- this is for an adaptive/relative-adaptive scan.
polling_plan
- this is used for moving a motor and dropping updates from a “readable” if no motor updates are provided. An example of this is a laser reading which updates much more quickly than a motor might register it’s moved, so the laser readings are not really useful information.
An example of using one of these could be:
from ibex_bluesky_core.devices.simpledae import SimpleDae
from ibex_bluesky_core.devices.block import BlockRw, BlockWriteConfig
from ibex_bluesky_core.plans import scan
from ibex_bluesky_core.callbacks.fitting.fitting_utils import Linear
def my_plan():
dae = SimpleDae(...) # Give your DAE options here
block = BlockRw("my_block", write_config=BlockWriteConfig(settle_time_s=5)) # This block needs a settle time of 5 seconds
icc = (yield from scan(dae, block, 1, 10, 21, model=Linear().fit()))
print(icc.peak_stats['com']) # print the centre of mass
which would be used on the console like so: RE(my_plan)
Higher-level wrapper plans
Alternatively, we provide some very thin wrappers which construct the devices for you - these are:
which wrap the above respectively. These take names of blocks, rather than devices themselves, and construct a DAE and block device for you. This might be useful if you have a fairly standard DAE setup and just want to scan a block pointing at a motor such as a Sample Changer axis.
for example if you just wanted to scan over a motor, wait for 400 frames, and perform a linear fit, you can just write this in the console:
>>> from ibex_bluesky_core.plans import motor_scan
>>> from ibex_bluesky_core.callbacks.fitting.fitting_utils import Linear
>>> result = RE(motor_scan("motor_block", 1, 10, 11, model=Linear().fit(), frames=400, det=1, mon=3))
>>> result.plan_result.live_fit