Skip to content

Commit f1589cb

Browse files
committed
Autoalign
1 parent 98d5f30 commit f1589cb

File tree

1 file changed

+18
-8
lines changed

1 file changed

+18
-8
lines changed

doc/plans/reflectometry/autoalign.md

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@
22

33
For reflectometers, we provide a few generic plans which can be used as helpers for automated beamline alignment.
44

5-
The {py:obj}`~ibex_bluesky_core.plans.reflectometry.optimise_axis_against_intensity` plan is designed to scan over a movable against beam intensity, and given which fitting parameter is chosen to be optimised and the fitting method, it will aim to find an optimum value. See [standard fits](/callbacks/fitting/standard_fits.md) for the fitting parameters for each fitting model you can use. At this stage it will check if the value is 'sensible' - there are some default checks, but the user is encouraged to provide their own checks. If found to be sensible, the motor will be moved to this value, otherwise it will optionally run a callback that can be provided, and then ask the user if they want to rescan or continue to move the movable.
5+
The {py:obj}`~ibex_bluesky_core.plans.reflectometry.optimise_axis_against_intensity` plan is designed to scan a {py:obj}`~bluesky.protocols.Movable` against beam intensity, and given a fitting routine, will aim to find an optimum value. Many [standard fits](/callbacks/fitting/standard_fits.md) have been implemented and can be used easily.
66

7-
The idea for how we expect the main auto-alignment plan to be used is that at the top / instrument level, you will move all other movables to some position ready to align, yield from this plan and then re-zero the motor.
8-
The following is how you would do this for a reflectometry parameter as your movable:
7+
Once a fit has been performed, {py:obj}`~ibex_bluesky_core.plans.reflectometry.optimise_axis_against_intensity` will check that the fit parameters are 'sensible' - there are some default checks, but the user is encouraged to provide their own checks. If the checks pass, the motor will be moved to the fit value, otherwise it will run a user-provided callback, and then ask the user if they want to rescan or move anyway.
98

10-
```python
9+
Reflectometer auto-alignment routines will generally be structured as a series of calls which:
10+
- Put the beamline into a suitable state for the alignment
11+
- Call {py:obj}`~ibex_bluesky_core.plans.reflectometry.optimise_axis_against_intensity` to optimise the axis. This will leave the axis parked at its optimal position.
12+
- Redefine that position as zero (note: this is fully optional, but common on reflectometers)
13+
- Repeat the above steps for subsequent axes
14+
15+
For example, using a reflectometry parameter as your {py:obj}`~bluesky.protocols.Movable`:
1116

17+
```python
1218
def full_autoalign_plan() -> Generator[Msg, None, None]:
1319

1420
det_pixels = centred_pixel(DEFAULT_DET, PIXEL_RANGE)
@@ -20,8 +26,8 @@ def full_autoalign_plan() -> Generator[Msg, None, None]:
2026
monitor=DEFAULT_MON,
2127
)
2228

23-
s1vg = ReflParameter(prefix=PREFIX, name="S1VG", changing_timeout_s=60)
2429
# Interfaces with the reflectometry server
30+
s1vg = ReflParameter(prefix=PREFIX, name="S1VG", changing_timeout_s=60)
2531

2632
yield from ensure_connected(s1vg, dae)
2733

@@ -44,12 +50,16 @@ def full_autoalign_plan() -> Generator[Msg, None, None]:
4450
# ....
4551

4652
print("Auto alignment complete.")
47-
4853
```
4954

50-
As mentioned prior, it is recommended that for each movable you want to align, you should provide a checking function, to make sure that for the value you receive for the chosen fitting paramater e.g centre of a gaussian, is sensible. If the optimised value is not found to be sensible then you will have the option to either type 1 and restart the alignment for this movable, or press 2 and continue with moving the movable to the found value. The following is how you would make a check function with the right signature and pass it to {py:obj}`ibex_bluesky_core.plans.reflectometry.optimise_axis_against_intensity`:
55+
As mentioned prior, it is recommended that for each {py:obj}`~bluesky.protocols.Movable` to be aligned, you should provide a checking function, to make sure that for the value you receive for the chosen fitting paramater e.g centre of a gaussian, is physically reasonable. If the optimised value fails the check, then you will have the option to either restart the alignment for this axis, or continue moving this axis to the located value despite the failing check.
56+
57+
The following is how you would define a check function with the right signature and pass it to {py:obj}`~ibex_bluesky_core.plans.reflectometry.optimise_axis_against_intensity`:
5158

5259
```python
60+
from lmfit.model import ModelResult
61+
from math import isclose
62+
5363

5464
def s1vg_checks(result: ModelResult, alignment_param_value: float) -> str | None: # Must take a ModelResult and a float
5565
"""Check for optimised S1VG value. Returns True if sensible."""
@@ -72,7 +82,7 @@ def s1vg_checks(result: ModelResult, alignment_param_value: float) -> str | None
7282
if result.values["background"] / result.model.func(alignment_param_value) <= max_peak_factor:
7383
return "Peak was not above the background by factor."
7484

75-
# Everything is fine so return None
85+
# Everything is fine, so return None
7686
return None
7787

7888
# ...

0 commit comments

Comments
 (0)