Coming to Bluesky from SPEC#
This page is for users with SPEC experience. We assume you know what
mv, umvr, ascan, dscan, and ct do; what wm shows; and how
SPEC stores data in numbered scan files.
Bluesky is a different beast. This page is the cross-walk between SPEC concepts and their Bluesky equivalents – close enough to bridge the gap, honest about where Bluesky is more trouble than SPEC.
The single most important difference#
In SPEC, you type a command and the hardware moves:
SPEC> mv samx 5
In Bluesky, you type the description of a motion and hand it to the RunEngine to execute:
RE(bps.mv(sample_stage.xprime, 5))
The bps.mv(...) part returns a Python generator – a description
of what should happen. The RE(...) part does it. If you forget
the RE(...) and type just bps.mv(...), the motor does not move.
This is the source of more new-user confusion than anything else. See The RunEngine for why Bluesky is built this way.
Command cross-walk#
SPEC |
Bluesky |
Notes |
|---|---|---|
|
|
Move one motor to absolute position. |
|
|
Multi-motor move (parallel). |
|
|
Bluesky always waits; no “update vs. non-update” distinction. |
|
|
Relative move. |
|
|
Returns a float; no |
|
|
“where all” for motors with the |
|
|
One count of named detector(s). |
|
|
Five counts; |
|
|
SPEC counts intervals; Bluesky counts points. 10 intervals = 11 points. |
|
|
Relative scan around current position. |
|
|
Multi-motor synchronized scan. |
|
|
2-D mesh; again, +1 on each “intervals” count. |
|
|
Set the current readback to a new value (changes the offset). |
|
(use motor record |
Bluesky has no built-in limit-setter shortcut; ophyd exposes them as |
|
|
(or |
|
|
Bluesky writes structured runs to a server; no per-scan file. |
|
(not applicable; runs are tagged with metadata) |
See |
|
( |
The |
|
|
load (and execute) code from a file |
Bluesky’s built-in scan plans live in bluesky.plans and are
imported as bp in the session. Plan stubs (one-shot operations
that compose into plans) live in bluesky.plan_stubs and are imported
as bps. See Plans and stubs
for the distinction.
When not to use RE(...)#
SPEC has no distinction: every command at the prompt is a command. Bluesky has two kinds of expressions:
# Plans -- use RE(...)
RE(bps.mv(motor, 5))
RE(bp.scan([detector], motor, 0, 10, 11))
RE(laser_optics.move_out())
# NOT plans -- call directly, no RE(...)
sample_stage.xprime.position # returns a float
sample_stage.xprime.user_readback.get() # returns a float
laser_optics.is_out # returns a bool
sample_stage.xprime.read() # returns a dict
shutter.open() # returns immediately; the bare device method
cat[-1].primary.read() # returns an xarray Dataset
The rule: if it returns a generator, wrap with RE; if it returns
data, call directly. See The
RunEngine for the full reasoning.
What Bluesky has that SPEC does not#
These are the upsides:
Structured metadata. Every run has a unique UID, a
scan_id, a start time, an end time, and a customizable metadata dict (md=). No more “what was scan 47 of yesterday?”.Pause / resume. Two Ctrl-C’s pause the RunEngine between steps. Inspect, fix, then
RE.resume().Suspenders. “Pause on beam dump, resume when it comes back” is a generic Bluesky mechanism, not bespoke per-beamline code.
Document streams. Every run emits a stream of structured documents (
start,descriptor,event,stop). Subscribers consume the stream live: BEC for plots, TiledWriter for storage, SPEC-format writer for SPEC-style files (if enabled).Live plotting. The
BestEffortCallback(bec) opens a plot for any 1-D scan automatically.
What SPEC has that Bluesky does not#
These are real downsides; pretending otherwise wastes everyone’s time:
Compactness.
ascan samx 0 10 10 1is much shorter thanRE(bp.scan([scaler], sample_stage.xprime, 0, 10, 11)). You can alias common scans to save typing, but the bare commands are longer.Inline command editing. SPEC lets you edit and re-run scans by recalling the command line. Bluesky has IPython history, which is close but not the same.
Macros. SPEC’s
overnight.macis sometimes faster to write than authoring a Python plan, especially for one-off ideas. Bluesky plans are more reusable but more verbose to write. Both can be nested, Bluesky plans are easier to understand side-effects when nesting.One command, one file. SPEC files are human-readable text with per-scan headers. Bluesky data lives in a Tiled catalog; reading it requires a client (Python, or a Tiled web browser).
Decades of stability. SPEC’s command set has not changed in ages. Bluesky is younger and the ecosystem is still moving.
Data files#
In SPEC, you set a data file with newfile, every scan appends to
it, and you read with pdshow / external tools.
In Bluesky at 3-ID-C:
Runs are sent to a Tiled server by the
TiledWritercallback. Runs land under the/rawtree on that server.Area-detector image files (Eiger HDF5) are written by the IOC into a beamline-specific directory and linked into the Bluesky master HDF5 file via HDF5 external links.
The catalog client (
catin your session) is the way to look at runs after the fact:run = cat[-1]; run.primary.read().
See How to inspect data and How to visualize HDF5 for the practical workflows.
See also#
EPICS user perspective – if you also know EPICS but not Python, that page may help more than this one.
The RunEngine – why Bluesky insists on the
RE(...)wrapping.Cheat sheet – print this and tape it to your monitor.