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
motorto position 12. - Executes a relative scan
dscanofmotorfrom -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.