Skip to content

How to Write a Script

To begin writing scripts for Bluesky, create a personal folder within the ~/bluesky/user_scripts/your_name directory. You can store your scripts here. For reference, check out examples in ~/bluesky/user_scripts/examples.

Commands - supported syntax

You can write commands as you were on the IPython shell, for example

# Change Energy
mov pgm.en 400
# Perform scan
dscan motor -1 1 10
# Read detector
count det 5
# Check motor positions
wa

are all valid instructions. They will be executed sequentially.
You can also wrap commands in for loops and use the iterator index inline:

# Perform 5 dscan moving the motor from 0 to 20
# with the number of steps increasing by 1 at every cycle
# starting from 10 up to 14
for i in range(10,14):
    dscan motor 0 20 i

# Nested loops are also supported
for j in range(4):
    scan motor j 20 10
    for k in range(10,13):
        count [det1 det2] k
        wa motor

Commands - unsupported syntax

Using custom variables as commands' argument is not supported. For example:

my_var = 5
dscan motor -10 my_var 20 # unsupported

steps = [5, 6, 4]
for step in steps:
    scan motor -10 10 step # supported - step is the loop index

for i in range(1,5):
    scan motor -10 10 my_var # unsupported

To address these cases you must use the Bluesky standard syntax (next section).

Bluesky Standard Syntax

If you want to implement complex logic that is not supported by the commands syntax, you should use the standard Bluesky syntax:

# Scan over a motor from -10 to 10 in 20 steps 
# and read from det1, det2 at every step
RE(scan_plan([det1 det2], motor, -10, 10, 20))

note that if you are using standard commands (scan, mov, ... ) you have to attach the suffix _plan.

With this notation you can perform more complex operations, for examples:

# Define variables
starting_point = -10
end_point = 10
number_of_steps = 20
# Use variables in plan
RE(scan_plan([det1 det2], motor, starting_point, end_point, number_of_steps))

Types of Scripts

You can create either procedural scripts, which execute a sequence of instructions immediately upon loading, or scripts that define functions to be called interactively.

Procedural Scripts

For a procedural script, see the example at ~/bluesky/user_scripts/examples/example_script.py. This script performs the following actions:

  • Prints the current position of a simulated motor called motor.
  • Moves motor to position 12.
  • Executes a relative scan dscan of motor from -1 to +1 in 10 steps.
# Print the current position of the motor
print(f"Current position of the motor: {motor.readback.get()}")

# Move the motor to a specified position
mov motor 12

# Run a scan
dscan motor -1 1 10

To execute this script, use:

load_user_scripts('examples/example_script.py')

Scripts with Functions

This type of script defines a function, such as test_plan(), that encapsulates a series of operations:

def test_plan():
    """Execute this test plan."""
    # Print the current position of the motor
    print(f"Current position of motor: {motor.readback.get()}")

    # Move the motor to position 0
    mov motor 0

    # Run a scan
    dscan [noisy_det] motor -1 1 10

Load this script as follows:

load_user_script('examples/example_with_functions.py')

Once loaded, the function test_plan() is available in the IPython session. To execute it, simply enter:

test_plan()

You do not need to reload the script to execute the function multiple times unless you make modifications to it. If changes are made, reloading is necessary.