Simulated KB Mirror Demo#
This notebook introduces the use of Blop to tune a KB mirror pair to optimize the quality of a simulated beam read by a detector.
Blop uses Ax as its optimization and experiment tracking backend.
Ax provides:
Experiment tracking
Analysis & visualization
Bayesian optimization (through BoTorch)
Blop provides:
Native integration with Bluesky & its ecosystem
Specialized kernels and methods common to beamline optimization problems
These features make it simple to optimize your beamline using both Bluesky & Ax.
Preparing a test environment#
Here we prepare the RunEngine, setup a local Tiled server, and connect to it with a Tiled client.
import logging
import bluesky.plan_stubs as bps # noqa F401
import bluesky.plans as bp # noqa F401
import matplotlib.pyplot as plt
from bluesky.callbacks import best_effort
from bluesky.callbacks.tiled_writer import TiledWriter
from bluesky.run_engine import RunEngine
from tiled.client import from_uri # type: ignore[import-untyped]
from tiled.client.container import Container
from tiled.server import SimpleTiledServer
from blop.sim.beamline import TiledBeamline
# Suppress noisy logs from httpx
logging.getLogger("httpx").setLevel(logging.WARNING)
DETECTOR_STORAGE = "/tmp/blop/sim"
[WARNING 12-08 20:30:56] ax.service.utils.with_db_settings_base: Ax currently requires a sqlalchemy version below 2.0. This will be addressed in a future release. Disabling SQL storage in Ax for now, if you would like to use SQL storage please install Ax with mysql extras via `pip install ax-platform[mysql]`.
tiled_server = SimpleTiledServer(readable_storage=[DETECTOR_STORAGE])
tiled_client = from_uri(tiled_server.uri)
tiled_writer = TiledWriter(tiled_client)
bec = best_effort.BestEffortCallback()
bec.disable_plots()
RE = RunEngine({})
RE.subscribe(bec)
RE.subscribe(tiled_writer)
2025-12-08 20:31:00.604 INFO: Subprocess stdout:
2025-12-08 20:31:00.605 INFO: Subprocess stderr: Database sqlite+aiosqlite:////tmp/tmppc7lyyk9/catalog.db is new. Creating tables.
Database initialized.
Tiled version 0.2.2
2025-12-08 20:31:01.315 INFO: Tiled version 0.2.2
2025-12-08 20:31:01.321 INFO: Context impl SQLiteImpl.
2025-12-08 20:31:01.322 INFO: Will assume non-transactional DDL.
1
Simulated beamline with KB mirror pair#
Here we describe an analytical simulated beamline with a KB mirror pair. This is implemented as an Ophyd device for ease-of-use with Bluesky.
beamline = TiledBeamline(name="bl")
Create a Blop-Ax experiment#
Now we can define the experiment we plan to run.
This involves setting 4 parameters that simulate motor positions controlling two KB mirrors. The objectives of the experiment are to maximize the beam intensity while minimizing the area of the beam.
We transform the Agent into an optimization problem that can be used with standard Bluesky plans.
from blop.ax import Agent, RangeDOF, Objective
from blop.protocols import EvaluationFunction
dofs = [
RangeDOF(movable=beamline.kbv_dsv, parameter_type="float", bounds=(-5.0, 5.0)),
RangeDOF(movable=beamline.kbv_usv, parameter_type="float", bounds=(-5.0, 5.0)),
RangeDOF(movable=beamline.kbh_dsh, parameter_type="float", bounds=(-5.0, 5.0)),
RangeDOF(movable=beamline.kbh_ush, parameter_type="float", bounds=(-5.0, 5.0)),
]
objectives = [
Objective(name="bl_det_sum", minimize=False),
Objective(name="bl_det_wid_x", minimize=True),
Objective(name="bl_det_wid_y", minimize=True),
]
class DetectorEvaluation(EvaluationFunction):
def __init__(self, tiled_client: Container):
self.tiled_client = tiled_client
def __call__(self, uid: str, suggestions: list[dict]) -> list[dict]:
outcomes = []
run = self.tiled_client[uid]
bl_det_sum = run["primary/bl_det_sum"].read()
bl_det_wid_x = run["primary/bl_det_wid_x"].read()
bl_det_wid_y = run["primary/bl_det_wid_y"].read()
# These ids are stored in the start document's metadata when
# using the `blop.plans.default_acquire` plan.
# You may want to store them differently in your experiment when writing
# your a custom acquisiton plan.
suggestion_ids = run.metadata["start"]["blop_suggestion_ids"]
for idx, sid in enumerate(suggestion_ids):
outcome = {
"_id": sid,
"bl_det_sum": bl_det_sum[idx],
"bl_det_wid_x": bl_det_wid_x[idx],
"bl_det_wid_y": bl_det_wid_y[idx],
}
outcomes.append(outcome)
return outcomes
evaluation_function = DetectorEvaluation(tiled_client)
agent = Agent(
readables=[beamline.det],
dofs=dofs,
objectives=objectives,
evaluation=evaluation_function,
name="sim_kb_mirror",
description="Simulated KB Mirror Experiment",
)
Optimization#
With all of our experimental setup done, we can optimize the DOFs to satisfy our objectives.
For this example, Ax will optimize the 4 motor positions to produce the greatest intensity beam with the smallest beam width and height (smallest area). It does this by first running a couple of trials which are random samples, then the remainder using Bayesian optimization through BoTorch.
RE(agent.optimize(iterations=25, n_points=1))
Transient Scan ID: 1 Time: 2025-12-08 20:31:01
Persistent Unique Scan ID: 'bb078c2e-0ba8-4853-9ea6-64b97d1997eb'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:01.9 | 0.000 | 0.000 | 0.000 | 0.000 | 531.529 | 198.987 | 148.768 | 31.145 | 40.553 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['bb078c2e'] (scan num: 1)
Transient Scan ID: 2 Time: 2025-12-08 20:31:02
Persistent Unique Scan ID: '984303dc-1cd2-4140-8538-384b52179d35'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:03.0 | -3.817 | -0.634 | -1.280 | -3.084 | 182.732 | 169.944 | 174.331 | 118.132 | 87.573 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['984303dc'] (scan num: 2)
Transient Scan ID: 3 Time: 2025-12-08 20:31:03
Persistent Unique Scan ID: '87ab352c-2cb9-4857-b441-c91c0bc1ea0d'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:03.6 | 2.263 | 2.735 | 2.902 | 1.880 | 442.187 | 179.164 | 155.885 | 99.678 | 58.213 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['87ab352c'] (scan num: 3)
Transient Scan ID: 4 Time: 2025-12-08 20:31:04
Persistent Unique Scan ID: '51e9625f-746f-47f8-bf6d-988d702ffc20'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:04.2 | 2.889 | -3.364 | -3.853 | -1.025 | 46.939 | 235.915 | 79.849 | 112.245 | 10.415 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['51e9625f'] (scan num: 4)
Transient Scan ID: 5 Time: 2025-12-08 20:31:04
Persistent Unique Scan ID: 'db573131-af59-430a-9a54-76358eaddc42'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:04.8 | -0.689 | 0.005 | 0.320 | 3.929 | 379.391 | 261.469 | 159.652 | 66.921 | 54.058 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['db573131'] (scan num: 5)
Transient Scan ID: 6 Time: 2025-12-08 20:31:08
Persistent Unique Scan ID: '9127477b-b792-4d15-b69d-02140033abcb'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:08.5 | 0.778 | -1.231 | -1.093 | -1.047 | 493.228 | 199.942 | 119.012 | 83.533 | 48.179 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['9127477b'] (scan num: 6)
Transient Scan ID: 7 Time: 2025-12-08 20:31:11
Persistent Unique Scan ID: 'c84988cf-1712-489f-b56f-08eec9a2fc2a'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:12.0 | 0.515 | -0.726 | -3.007 | 0.292 | 391.158 | 254.486 | 130.555 | 79.289 | 44.752 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['c84988cf'] (scan num: 7)
Transient Scan ID: 8 Time: 2025-12-08 20:31:16
Persistent Unique Scan ID: '091aaea0-dba8-4737-a304-79ec91fce872'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:17.0 | 0.049 | 2.191 | 0.440 | -1.948 | 545.641 | 151.400 | 181.016 | 67.360 | 10.338 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['091aaea0'] (scan num: 8)
Transient Scan ID: 9 Time: 2025-12-08 20:31:21
Persistent Unique Scan ID: 'f69e5ef2-2528-44b7-8bde-1427e435386c'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:21.8 | 0.288 | 1.816 | -0.049 | -0.033 | 544.387 | 199.312 | 171.980 | 32.887 | 8.802 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['f69e5ef2'] (scan num: 9)
Transient Scan ID: 10 Time: 2025-12-08 20:31:28
Persistent Unique Scan ID: 'ca389db3-0cbd-4a74-b001-23b5986af513'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:28.3 | 0.550 | 2.109 | 0.457 | -0.013 | 551.371 | 189.633 | 172.100 | 22.013 | 15.591 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['ca389db3'] (scan num: 10)
Transient Scan ID: 11 Time: 2025-12-08 20:31:34
Persistent Unique Scan ID: '6ea5bcd9-273f-4be4-bcdd-ec2821d8baa1'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:34.5 | 0.391 | 1.574 | 1.001 | -0.604 | 553.422 | 167.000 | 166.938 | 22.450 | 8.768 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['6ea5bcd9'] (scan num: 11)
Transient Scan ID: 12 Time: 2025-12-08 20:31:40
Persistent Unique Scan ID: '686e3855-18ce-4ba9-a1ed-3c2290a34130'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:40.5 | 0.722 | -4.378 | 1.200 | -0.157 | 257.355 | 171.874 | 104.833 | 16.687 | 55.112 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['686e3855'] (scan num: 12)
Transient Scan ID: 13 Time: 2025-12-08 20:31:47
Persistent Unique Scan ID: '183db838-367c-40cb-a503-6240495b2a3a'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:47.7 | 0.826 | 1.226 | 1.119 | -0.086 | 553.137 | 175.000 | 155.000 | 16.750 | 8.714 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['183db838'] (scan num: 13)
Transient Scan ID: 14 Time: 2025-12-08 20:31:54
Persistent Unique Scan ID: 'c269bb81-7fba-4203-88db-10da39582a29'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:31:54.8 | -0.667 | 1.949 | 1.220 | 0.005 | 545.392 | 174.906 | 188.125 | 17.394 | 16.956 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['c269bb81'] (scan num: 14)
Transient Scan ID: 15 Time: 2025-12-08 20:32:04
Persistent Unique Scan ID: 'af695872-c602-4bc9-9e35-b5c587b68b9e'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:32:04.1 | 0.436 | 1.538 | 2.739 | -1.275 | 543.365 | 119.000 | 165.432 | 20.143 | 9.220 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['af695872'] (scan num: 15)
Transient Scan ID: 16 Time: 2025-12-08 20:32:13
Persistent Unique Scan ID: '00264669-854d-4643-bac7-6649fab4e3ea'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:32:13.1 | 0.449 | 1.476 | 1.936 | -0.497 | 546.259 | 150.438 | 164.315 | 19.825 | 9.138 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['00264669'] (scan num: 16)
Transient Scan ID: 17 Time: 2025-12-08 20:32:22
Persistent Unique Scan ID: 'fccc30cc-dd4b-4154-8982-a241b77a828a'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:32:22.4 | 0.383 | 1.544 | 4.200 | -2.951 | 1.192 | 209.198 | 162.184 | 365.819 | 260.622 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['fccc30cc'] (scan num: 17)
Transient Scan ID: 18 Time: 2025-12-08 20:32:30
Persistent Unique Scan ID: '79ad580b-9723-4015-ab9b-f5a684cdce9e'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:32:30.5 | -0.167 | 4.149 | 2.026 | -1.101 | 396.445 | 136.517 | 207.364 | 16.600 | 29.355 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['79ad580b'] (scan num: 18)
Transient Scan ID: 19 Time: 2025-12-08 20:32:41
Persistent Unique Scan ID: '3e402b1f-c3c3-4aa7-a858-c86052da42f9'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:32:41.9 | -0.172 | 0.049 | 2.392 | -1.024 | 546.770 | 130.951 | 152.306 | 19.120 | 42.828 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['3e402b1f'] (scan num: 19)
Transient Scan ID: 20 Time: 2025-12-08 20:32:53
Persistent Unique Scan ID: 'd737a79e-35e5-45db-9b5b-ad0faa207987'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:32:53.2 | 0.797 | 1.037 | 0.653 | 0.854 | 547.601 | 203.000 | 152.543 | 20.822 | 9.548 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['d737a79e'] (scan num: 20)
Transient Scan ID: 21 Time: 2025-12-08 20:33:03
Persistent Unique Scan ID: 'aad43dcd-31fb-4b93-a838-574bc78744f5'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:33:03.4 | 2.190 | 1.092 | 1.040 | 0.433 | 545.505 | 186.960 | 132.500 | 20.824 | 26.730 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['aad43dcd'] (scan num: 21)
Transient Scan ID: 22 Time: 2025-12-08 20:33:15
Persistent Unique Scan ID: '89660117-cc14-41f4-892b-8dac4fd0636a'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:33:15.7 | 0.931 | 1.941 | 2.422 | -1.685 | 549.787 | 117.193 | 164.025 | 17.833 | 19.144 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['89660117'] (scan num: 22)
Transient Scan ID: 23 Time: 2025-12-08 20:33:28
Persistent Unique Scan ID: '74eb894a-dcd1-40da-88f3-1788ed88a369'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:33:28.7 | 0.185 | 1.177 | 2.417 | -1.347 | 549.445 | 123.929 | 163.906 | 16.964 | 15.406 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['74eb894a'] (scan num: 23)
Transient Scan ID: 24 Time: 2025-12-08 20:33:43
Persistent Unique Scan ID: 'fbb87ac1-263a-49d4-b256-bb78f7e98d1f'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:33:43.3 | 4.496 | 1.947 | 2.452 | -1.406 | 446.311 | 122.034 | 117.060 | 17.077 | 76.048 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['fbb87ac1'] (scan num: 24)
Transient Scan ID: 25 Time: 2025-12-08 20:33:52
Persistent Unique Scan ID: 'f80b638f-0582-4875-9069-49ec38e75de2'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:33:52.3 | 1.846 | -1.009 | 1.655 | -1.859 | 549.916 | 128.868 | 106.382 | 35.877 | 24.798 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['f80b638f'] (scan num: 25)
2025-12-08 20:31:01.810 INFO: Executing plan <generator object Agent.optimize at 0x7f4239f73060>
2025-12-08 20:31:01.812 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f4238ec8d40> from 'idle' -> 'running'
2025-12-08 20:33:52.839 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f4238ec8d40> from 'running' -> 'idle'
2025-12-08 20:33:52.840 INFO: Cleaned up from plan <generator object Agent.optimize at 0x7f4239f73060>
('bb078c2e-0ba8-4853-9ea6-64b97d1997eb',
'984303dc-1cd2-4140-8538-384b52179d35',
'87ab352c-2cb9-4857-b441-c91c0bc1ea0d',
'51e9625f-746f-47f8-bf6d-988d702ffc20',
'db573131-af59-430a-9a54-76358eaddc42',
'9127477b-b792-4d15-b69d-02140033abcb',
'c84988cf-1712-489f-b56f-08eec9a2fc2a',
'091aaea0-dba8-4737-a304-79ec91fce872',
'f69e5ef2-2528-44b7-8bde-1427e435386c',
'ca389db3-0cbd-4a74-b001-23b5986af513',
'6ea5bcd9-273f-4be4-bcdd-ec2821d8baa1',
'686e3855-18ce-4ba9-a1ed-3c2290a34130',
'183db838-367c-40cb-a503-6240495b2a3a',
'c269bb81-7fba-4203-88db-10da39582a29',
'af695872-c602-4bc9-9e35-b5c587b68b9e',
'00264669-854d-4643-bac7-6649fab4e3ea',
'fccc30cc-dd4b-4154-8982-a241b77a828a',
'79ad580b-9723-4015-ab9b-f5a684cdce9e',
'3e402b1f-c3c3-4aa7-a858-c86052da42f9',
'd737a79e-35e5-45db-9b5b-ad0faa207987',
'aad43dcd-31fb-4b93-a838-574bc78744f5',
'89660117-cc14-41f4-892b-8dac4fd0636a',
'74eb894a-dcd1-40da-88f3-1788ed88a369',
'fbb87ac1-263a-49d4-b256-bb78f7e98d1f',
'f80b638f-0582-4875-9069-49ec38e75de2')
Analyze Results#
We can start by summarizing each step of the optimization procedure and whether trials were successful or not. This can be done by accessing the Ax client directly.
agent.ax_client.summarize()
| trial_index | arm_name | trial_status | generation_node | bl_det_sum | bl_det_wid_x | bl_det_wid_y | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | |
|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 0 | 0_0 | COMPLETED | CenterOfSearchSpace | 531.529317 | 31.144737 | 40.552976 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
| 1 | 1 | 1_0 | COMPLETED | Sobol | 182.731662 | 118.132292 | 87.573266 | -3.817377 | -0.634485 | -1.280143 | -3.084386 |
| 2 | 2 | 2_0 | COMPLETED | Sobol | 442.187150 | 99.678285 | 58.212574 | 2.262620 | 2.734593 | 2.902145 | 1.880185 |
| 3 | 3 | 3_0 | COMPLETED | Sobol | 46.939259 | 112.244643 | 10.415194 | 2.888802 | -3.364296 | -3.852560 | -1.025447 |
| 4 | 4 | 4_0 | COMPLETED | Sobol | 379.390696 | 66.920869 | 54.057721 | -0.688752 | 0.004802 | 0.319647 | 3.928900 |
| 5 | 5 | 5_0 | COMPLETED | MBM | 493.227995 | 83.532802 | 48.178914 | 0.778327 | -1.231264 | -1.093167 | -1.047361 |
| 6 | 6 | 6_0 | COMPLETED | MBM | 391.158229 | 79.288537 | 44.752238 | 0.514859 | -0.725977 | -3.006525 | 0.292367 |
| 7 | 7 | 7_0 | COMPLETED | MBM | 545.641067 | 67.360000 | 10.337847 | 0.049002 | 2.191129 | 0.440202 | -1.948350 |
| 8 | 8 | 8_0 | COMPLETED | MBM | 544.387227 | 32.887500 | 8.802002 | 0.287579 | 1.815779 | -0.049201 | -0.032869 |
| 9 | 9 | 9_0 | COMPLETED | MBM | 551.371449 | 22.013333 | 15.590890 | 0.549521 | 2.109481 | 0.457132 | -0.012521 |
| 10 | 10 | 10_0 | COMPLETED | MBM | 553.421677 | 22.450000 | 8.767677 | 0.391057 | 1.574256 | 1.000621 | -0.604057 |
| 11 | 11 | 11_0 | COMPLETED | MBM | 257.355204 | 16.686708 | 55.111786 | 0.721923 | -4.377903 | 1.200329 | -0.156880 |
| 12 | 12 | 12_0 | COMPLETED | MBM | 553.137054 | 16.750000 | 8.714286 | 0.826153 | 1.226178 | 1.119364 | -0.086491 |
| 13 | 13 | 13_0 | COMPLETED | MBM | 545.391625 | 17.393750 | 16.956250 | -0.667330 | 1.948688 | 1.219797 | 0.004877 |
| 14 | 14 | 14_0 | COMPLETED | MBM | 543.364559 | 20.142857 | 9.220238 | 0.436425 | 1.537574 | 2.738531 | -1.275484 |
| 15 | 15 | 15_0 | COMPLETED | MBM | 546.258730 | 19.825000 | 9.137544 | 0.449137 | 1.475610 | 1.935501 | -0.497295 |
| 16 | 16 | 16_0 | COMPLETED | MBM | 1.191811 | 365.818803 | 260.622010 | 0.382622 | 1.544140 | 4.199744 | -2.950996 |
| 17 | 17 | 17_0 | COMPLETED | MBM | 396.444544 | 16.600000 | 29.354510 | -0.167487 | 4.148820 | 2.025940 | -1.101104 |
| 18 | 18 | 18_0 | COMPLETED | MBM | 546.770315 | 19.119512 | 42.827778 | -0.172095 | 0.049247 | 2.392451 | -1.024342 |
| 19 | 19 | 19_0 | COMPLETED | MBM | 547.601077 | 20.822222 | 9.547917 | 0.797381 | 1.037305 | 0.652703 | 0.854311 |
| 20 | 20 | 20_0 | COMPLETED | MBM | 545.504995 | 20.824000 | 26.730000 | 2.190017 | 1.091841 | 1.039912 | 0.432931 |
| 21 | 21 | 21_0 | COMPLETED | MBM | 549.786681 | 17.833059 | 19.144097 | 0.931070 | 1.940924 | 2.422034 | -1.685184 |
| 22 | 22 | 22_0 | COMPLETED | MBM | 549.444627 | 16.964286 | 15.406250 | 0.184751 | 1.177347 | 2.417220 | -1.346690 |
| 23 | 23 | 23_0 | COMPLETED | MBM | 446.310866 | 17.077027 | 76.048264 | 4.495507 | 1.947486 | 2.452246 | -1.406385 |
| 24 | 24 | 24_0 | COMPLETED | MBM | 549.916382 | 35.876976 | 24.798070 | 1.845792 | -1.008954 | 1.655245 | -1.858946 |
Plotting#
We also can plot slices of the parameter space with respect to our objectives.
from ax.analysis import SlicePlot
_ = agent.ax_client.compute_analyses(analyses=[SlicePlot("bl_kbv_dsv", "bl_det_sum")])
The slice plot provides a one-dimensional view of predicted outcomes for bl_det_sum as a function of a single parameter, while keeping all other parameters fixed at their status_quo value (or mean value if status_quo is unavailable). This visualization helps in understanding the sensitivity and impact of changes in the selected parameter on the predicted metric outcomes.
_ = agent.ax_client.compute_analyses(analyses=[SlicePlot("bl_kbv_dsv", "bl_det_wid_x")])
The slice plot provides a one-dimensional view of predicted outcomes for bl_det_wid_x as a function of a single parameter, while keeping all other parameters fixed at their status_quo value (or mean value if status_quo is unavailable). This visualization helps in understanding the sensitivity and impact of changes in the selected parameter on the predicted metric outcomes.
More comprehensive analyses#
Ax provides many analysis tools that can help understand optimization results.
from ax.analysis import TopSurfacesAnalysis
_ = agent.ax_client.compute_analyses(analyses=[TopSurfacesAnalysis("bl_det_sum")])
Understand how each parameter affects bl_det_sum according to a second-order sensitivity analysis.
The slice plot provides a one-dimensional view of predicted outcomes for bl_det_sum as a function of a single parameter, while keeping all other parameters fixed at their status_quo value (or mean value if status_quo is unavailable). This visualization helps in understanding the sensitivity and impact of changes in the selected parameter on the predicted metric outcomes.
The contour plot visualizes the predicted outcomes for bl_det_sum across a two-dimensional parameter space, with other parameters held fixed at their status_quo value (or mean value if status_quo is unavailable). This plot helps in identifying regions of optimal performance and understanding how changes in the selected parameters influence the predicted outcomes. Contour lines represent levels of constant predicted values, providing insights into the gradient and potential optima within the parameter space.
The contour plot visualizes the predicted outcomes for bl_det_sum across a two-dimensional parameter space, with other parameters held fixed at their status_quo value (or mean value if status_quo is unavailable). This plot helps in identifying regions of optimal performance and understanding how changes in the selected parameters influence the predicted outcomes. Contour lines represent levels of constant predicted values, providing insights into the gradient and potential optima within the parameter space.
The slice plot provides a one-dimensional view of predicted outcomes for bl_det_sum as a function of a single parameter, while keeping all other parameters fixed at their status_quo value (or mean value if status_quo is unavailable). This visualization helps in understanding the sensitivity and impact of changes in the selected parameter on the predicted metric outcomes.
The contour plot visualizes the predicted outcomes for bl_det_sum across a two-dimensional parameter space, with other parameters held fixed at their status_quo value (or mean value if status_quo is unavailable). This plot helps in identifying regions of optimal performance and understanding how changes in the selected parameters influence the predicted outcomes. Contour lines represent levels of constant predicted values, providing insights into the gradient and potential optima within the parameter space.
Visualizing the optimal beam#
Below we get the optimal parameters, move the motors to their optimal positions, and observe the resulting beam.
optimal_parameters = next(iter(agent.ax_client.get_pareto_frontier()))[0]
optimal_parameters
[INFO 12-08 20:34:00] ax.service.utils.best_point: Using inferred objective thresholds: [ObjectiveThreshold(bl_det_sum >= 555.7823535929614), ObjectiveThreshold(bl_det_wid_x <= 22.9498967658003), ObjectiveThreshold(bl_det_wid_y <= 16.510023453499397)], as objective thresholds were not specified as part of the optimization configuration on the experiment.
{'bl_kbv_dsv': 0.3910567152768806,
'bl_kbv_usv': 1.574255867157634,
'bl_kbh_dsh': 1.000620951658333,
'bl_kbh_ush': -0.6040570392437791}
from bluesky.plans import list_scan
scan_motor_params = []
for motor in [beamline.kbv_dsv, beamline.kbv_usv, beamline.kbh_dsh, beamline.kbh_ush]:
scan_motor_params.append(motor)
scan_motor_params.append([optimal_parameters[motor.name]])
uid = RE(list_scan([beamline.det], *scan_motor_params))
Transient Scan ID: 26 Time: 2025-12-08 20:34:00
Persistent Unique Scan ID: 'efcd5793-7696-4c2e-b741-7e13b03417f3'
New stream: 'primary'
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| seq_num | time | bl_kbv_dsv | bl_kbv_usv | bl_kbh_dsh | bl_kbh_ush | bl_det_sum | bl_det_cen_x | bl_det_cen_y | bl_det_wid_x | bl_det_wid_y |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
| 1 | 20:34:01.0 | 0.391 | 1.574 | 1.001 | -0.604 | 553.594 | 167.000 | 166.938 | 22.450 | 8.768 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['efcd5793'] (scan num: 26)
2025-12-08 20:34:00.938 INFO: Executing plan <generator object list_scan at 0x7f4214000f40>
2025-12-08 20:34:00.939 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f4238ec8d40> from 'idle' -> 'running'
2025-12-08 20:34:01.315 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f4238ec8d40> from 'running' -> 'idle'
2025-12-08 20:34:01.316 INFO: Cleaned up from plan <generator object list_scan at 0x7f4214000f40>