(Optional) SPEC-like Interface

Warning

The SPEC-like interface was changed in bluesky v0.5.0, and this documentation has not yet been updated. It will be updated before the start of the Summer 2016 cycle. Until then, consult the DAMA group with any questions.

Conceptual Differences Between Bluesky and SPEC

Some scientists are familiar with SPEC, a domain-specific language for hardware control. It is possible to imitate the SPEC workflow on top of bluesky. Of course, we still adhere to the Python syntax so that we can employ the full power of the general-purpose Python language.

It is useful to understand a key conceptual difference between bluesky and SPEC. SPEC treats the specification of an experiment (“move a motor from 1 to 5 in 5 strides”) and its execution in one step. For example, in SPEC, typing

ascan th, 1, 5, 5

both specifies and executes the scan. Fundamentally, bluesky separates these steps: first we generate a “plan” (a set of granular instructions)

plan = AbsScanPlan(detectors, th, 1, 5, 4)

and then we pass the plan to a RunEninge for execution.

RE(plan)

To imitate the SPEC workflow, these two steps are lumped together.

ascan(th, 1, 5, 5)  # this is bluesky's imitation of SPEC

For simple tasks, the condensed syntax is clearly convenient; for others, maintaining that logical separation can be empowering. (See the section on Plans for why.)

Addiontally, SPEC maintains a global list of detectors that apply to all scans. Bluesky specifies detectors on a per-plan basis: for example, a “count” might involve different detectors than an “ascan”. But, to imitate SPEC, bluesky provides a global “stash” of settings, gs, including a customizable list of “standard” detectors, as illustrated below.

Specify Detectors

Note

If you are using a IPython profile, a list of detectors might be automatically specified at startup. In that case, you may not need to do anything unless you need to inspect or customize that list.

The setting gs.DETS is a list of a detector objects. It controls which detectors are triggered and read by all the simple scans. (Incidentally, gs stands for “global state” or “global settings.” Why can’t it just be plain DETS? Global variables are best avoided in Python, and the gs. part provides useful input validation.)

In [1]: gs.DETS = [det1, det2]

Like any Python list, you can append and remove elements.

In [2]: gs.DETS.append(det3)

In [3]: gs.DETS.remove(det1)

In [4]: gs.DETS
Out[4]: [reader: det2, reader: det3]

There are other settings which control the output of the scans – gs.TABLE_COLS and gs.PLOT_Y for example. Explore the contents of gs by typing gs.<TAB>.

Count

A ct (“count”) scan reads all the detectors in the list DETS for a given acquisition time. If no time is specified, 1 second is the default.

ct(time=1)

Motor Scans

Like ct, the motor scans read from all the detectors in the list DETS.

Absolute Scans

An ascan (“absolute scan”) scans one motor in equal-sized steps.

ascan(motor, start, finish, intervals, time)

Note that intervals counts the number of steps which is one less than the number of data points. This follows the convention in SPEC. Outside of the simple API, we revert to the Python convention of counting data points, not steps.

An a2scan scans two motors together along different trajectories, again in equal-sized steps. (We think of this as the “inner product” of two trajectories.)

a2scan(motor1, start1, finish1, motor2, start2, finish2, intervals, time)
a3scan(motor1, start1, finish1, motor2, start2, finish2, motor3,
       start3, finish3, intervals, time)

We provide a2scan and a3scan for convenience, but in fact both of them support any number of motors. This is valid:

a2scan(motor1, start1, finish1, motor2, start2, finish2, motor3, start3,
       finish3, motor4, start4, finish4, intervals, time)

Delta Scans

A dscan (“delta scan”) scans one motor in equal-size steps, specified relative to the motor’s current position.

dscan(motor, start, finish, intervals, time)

lup is an alias for dscan. And as with ascan above, there is a d2scan and a d3scan, each of which accept an unlimited number of motors.

Mesh Scan

A mesh scan scans any number of motors in a mesh. (We think of this as the “other product” of the trajectories.)

mesh(motor1, start1, finish1, intervals1, motor2, start2, finish2,
     intervals2, time)

As with a2scan and a3scan, mesh accepts any number of motors. Notice that the number of intervals is specified sepraately for each motor.

Scans Tied to Particular Motors / Controllers

Theta Two Theta

This scan requires the settings gs.TH_MOTOR (“theta motor”) and gs.TTH_MOTOR (“two theta motor”).

A th2th (“theta two theta”) scans steps the two theta motor through a given range while stepping the theta motor through half that range.

th2th(start, finish, intervals, time)

Temperature Scans

Temperature scans require the setting gs.TEMP_CONTROLLER.

A tscan steps the temperature controller through equally-spaced temperature set points. An optional sleep argument specifies a thermalization time. As in SPEC, it is zero by default.

tscan(start, finish, intervals, time, sleep=0)

There is also dtscan, a relative temperature scan.

Tweak

Tweak is an interactive scan that reads a field from one detector, displays the result, and prompts the user to specify where to step the motor next. It requires the setting gs.MASTER_DET (which detector to use, such as sclr) and MASTER_DET_FIELD (the name of the field in that detector to read out, such as 'sclr_chan4'). Note that the former is a readable object and the latter is a string of text.

tw(motor, step)