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.

from datetime import datetime
import logging

import bluesky.plan_stubs as bps  # noqa F401
import bluesky.plans as bp  # noqa F401
import databroker  # type: ignore[import-untyped]
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 databroker import Broker
from ophyd.utils import make_dir_tree  # type: ignore[import-untyped]
from tiled.client import from_uri  # type: ignore[import-untyped]
from tiled.client.container import Container
from tiled.server import SimpleTiledServer

from blop.sim import HDF5Handler
from blop.sim.beamline import DatabrokerBeamline, TiledBeamline

# Suppress noisy logs from httpx 
logging.getLogger("httpx").setLevel(logging.WARNING)

DETECTOR_STORAGE = "/tmp/blop/sim"
tiled_server = SimpleTiledServer(readable_storage=[DETECTOR_STORAGE])
tiled_client = from_uri(tiled_server.uri)
tiled_writer = TiledWriter(tiled_client)


def setup_re_env(db_type="default", root_dir="/default/path", method="tiled"):
    RE = RunEngine({})
    bec = best_effort.BestEffortCallback()
    RE.subscribe(bec)
    _ = make_dir_tree(datetime.now().year, base_path=root_dir)
    if method.lower() == "tiled":
        RE.subscribe(tiled_writer)
        return {"RE": RE, "db": tiled_client, "bec": bec}
    elif method.lower() == "databroker":
        db = Broker.named(db_type)
        db.reg.register_handler("HDF5", HDF5Handler, overwrite=True)
        try:
            databroker.assets.utils.install_sentinels(db.reg.config, version=1)
        except Exception:
            pass
        RE.subscribe(db.insert)
        return {"RE": RE, "db": db, "bec": bec, }
    else:
        raise ValueError("The method for data storage used is not supported")


def register_handlers(db, handlers):
    for handler_spec, handler_class in handlers.items():
        db.reg.register_handler(handler_spec, handler_class, overwrite=True)


env = setup_re_env(db_type="temp", root_dir="/tmp/blop/sim", method="tiled")
globals().update(env)
bec.disable_plots()
2025-10-13 20:39:36.088 INFO: Subprocess stdout:
2025-10-13 20:39:36.090 INFO: Subprocess stderr: Database sqlite+aiosqlite:////tmp/tmpj_regtqn/catalog.db is new. Creating tables.
Database initialized.
Tiled version 0.1.6
2025-10-13 20:39:36.407 INFO: Tiled version 0.1.6
2025-10-13 20:39:36.413 INFO: Context impl SQLiteImpl.
2025-10-13 20:39:36.413 INFO: Will assume non-transactional DDL.

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.

if isinstance(db, Container):
    beamline = TiledBeamline(name="bl")
elif isinstance(db, databroker.v1.Broker):
    beamline = DatabrokerBeamline(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.

from blop.ax import Agent
from blop.dofs import DOF
from blop.objectives import Objective

dofs = [
    DOF(movable=beamline.kbv_dsv, type="continuous", search_domain=(-5.0, 5.0)),
    DOF(movable=beamline.kbv_usv, type="continuous", search_domain=(-5.0, 5.0)),
    DOF(movable=beamline.kbh_dsh, type="continuous", search_domain=(-5.0, 5.0)),
    DOF(movable=beamline.kbh_ush, type="continuous", search_domain=(-5.0, 5.0)),
]

objectives = [
    Objective(name="bl_det_sum", target="max"),
    Objective(name="bl_det_wid_x", target="min"),
    Objective(name="bl_det_wid_y", target="min"),
]

agent = Agent(
    readables=[beamline.det],
    dofs=dofs,
    objectives=objectives,
    db=db,
)
agent.configure_experiment(name="test_ax_agent", description="Test the AxAgent")
[WARNING 10-13 20:39:37] 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]`.
2025-10-13 20:39:37.686 INFO: Configuring optimization with objective: bl_det_sum, -bl_det_wid_x, -bl_det_wid_y and outcome constraints: []

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.learn(iterations=25, n=1))
Transient Scan ID: 1     Time: 2025-10-13 20:39:37
Persistent Unique Scan ID: 'af22a361-5e19-4c6b-8c65-dd2ae87cae11'
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:39:37.9 |      0.000 |      0.000 |      0.000 |      0.000 |    542.712 |      198.987 |      149.000 |       31.155 |       39.897 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['af22a361'] (scan num: 1)
Found duckdb shared library at /home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.12/site-packages/_duckdb.cpython-312-x86_64-linux-gnu.so


Transient Scan ID: 2     Time: 2025-10-13 20:39:39
Persistent Unique Scan ID: 'a2573a0f-9535-49eb-96bd-144968cdba87'
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:39:39.1 |      0.388 |      2.833 |     -1.689 |     -1.154 |    504.803 |      210.594 |      185.515 |      101.792 |       25.291 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['a2573a0f'] (scan num: 2)


Transient Scan ID: 3     Time: 2025-10-13 20:39:39
Persistent Unique Scan ID: '2414bb42-d148-4b3b-be66-e4f381b6487d'
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:39:39.7 |     -3.457 |     -3.937 |      4.304 |      4.034 |      0.914 |      197.811 |      167.230 |      231.813 |      165.560 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['2414bb42'] (scan num: 3)


Transient Scan ID: 4     Time: 2025-10-13 20:39:40
Persistent Unique Scan ID: 'c6c411fd-11a0-4f43-b4a0-84ccff0fad56'
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:39:40.4 |     -0.792 |      1.089 |     -4.330 |     -4.621 |     54.650 |      197.411 |      176.977 |      174.096 |       32.375 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['c6c411fd'] (scan num: 4)


Transient Scan ID: 5     Time: 2025-10-13 20:39:41
Persistent Unique Scan ID: '2b270a12-4a64-42c3-8a89-e843ea0fa818'
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:39:41.1 |      2.702 |     -2.172 |      1.712 |      0.489 |    304.754 |      174.500 |       83.798 |       35.307 |       17.252 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['2b270a12'] (scan num: 5)


Transient Scan ID: 6     Time: 2025-10-13 20:39:45
Persistent Unique Scan ID: 'cde20903-f3ce-468b-a613-5825d02d65d1'
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:39:45.1 |      2.259 |     -0.084 |     -0.808 |      0.166 |    543.465 |      218.500 |      113.778 |       45.875 |        9.267 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['cde20903'] (scan num: 6)


Transient Scan ID: 7     Time: 2025-10-13 20:39:50
Persistent Unique Scan ID: 'abcde7c8-20bb-452c-bbc5-23e7569a105f'
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:39:50.5 |      1.995 |     -3.585 |     -0.495 |     -0.164 |    204.108 |      205.460 |       90.390 |       45.080 |       29.220 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['abcde7c8'] (scan num: 7)


Transient Scan ID: 8     Time: 2025-10-13 20:39:56
Persistent Unique Scan ID: '27e36073-7ee8-4d6f-8ec2-d2ab9430dfbe'
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:39:56.8 |      2.330 |      1.482 |      3.476 |      0.111 |    460.098 |      135.266 |      136.323 |       62.884 |       37.293 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['27e36073'] (scan num: 8)


Transient Scan ID: 9     Time: 2025-10-13 20:40:02
Persistent Unique Scan ID: '45ad787e-9627-4617-8b16-95b4ce4dad2d'
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:40:02.7 |      2.486 |      0.643 |      0.540 |      0.296 |    544.872 |      194.043 |      121.500 |       17.348 |       23.562 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['45ad787e'] (scan num: 9)


Transient Scan ID: 10     Time: 2025-10-13 20:40:08
Persistent Unique Scan ID: 'dcef7eb2-7c07-4742-8554-f77f4a40ccf2'
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:40:08.2 |      2.699 |     -0.650 |      0.246 |      0.091 |    548.939 |      195.938 |       98.986 |       24.100 |        8.781 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['dcef7eb2'] (scan num: 10)


Transient Scan ID: 11     Time: 2025-10-13 20:40:13
Persistent Unique Scan ID: 'f93560eb-7460-468e-aa02-aad6883bba99'
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:40:14.0 |      2.943 |      0.158 |      0.777 |     -0.545 |    547.403 |      172.640 |      107.440 |       26.420 |       23.342 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['f93560eb'] (scan num: 11)


Transient Scan ID: 12     Time: 2025-10-13 20:40:20
Persistent Unique Scan ID: '73ed172c-4068-479b-9190-48a401b689d0'
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:40:20.8 |      2.088 |      0.146 |      0.085 |     -0.116 |    550.309 |      194.900 |      119.963 |       31.040 |       10.275 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['73ed172c'] (scan num: 12)


Transient Scan ID: 13     Time: 2025-10-13 20:40:26
Persistent Unique Scan ID: 'a86458b0-a054-4627-906a-9fae1336e514'
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:40:26.8 |      2.543 |     -1.236 |     -5.000 |      5.000 |      0.294 |      167.680 |      150.424 |      297.451 |      285.852 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['a86458b0'] (scan num: 13)


Transient Scan ID: 14     Time: 2025-10-13 20:40:36
Persistent Unique Scan ID: 'a17ecfec-cb53-4d6b-9848-2aec409e15c4'
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:40:37.0 |      5.000 |      0.475 |      0.109 |      0.189 |    327.826 |      200.527 |       97.350 |       25.078 |       41.628 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['a17ecfec'] (scan num: 14)


Transient Scan ID: 15     Time: 2025-10-13 20:40:49
Persistent Unique Scan ID: '61d963e2-dc5b-4337-ad1c-1fb72ab88710'
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:40:49.8 |      1.789 |      0.303 |      0.617 |     -0.243 |    552.263 |      181.750 |      126.971 |       23.100 |        8.797 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['61d963e2'] (scan num: 15)


Transient Scan ID: 16     Time: 2025-10-13 20:40:59
Persistent Unique Scan ID: '0fddb6df-f24a-4262-af7d-b06a14acaa2d'
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:40:59.9 |      1.519 |      0.158 |      0.300 |     -0.549 |    548.204 |      182.000 |      128.625 |       36.200 |       11.083 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['0fddb6df'] (scan num: 16)


Transient Scan ID: 17     Time: 2025-10-13 20:41:09
Persistent Unique Scan ID: '1dbdbfba-ac72-4ad8-94c3-8a2364923ea9'
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:41:09.4 |      1.965 |     -0.271 |      1.075 |     -0.077 |    552.602 |      176.000 |      115.570 |       16.600 |       10.977 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['1dbdbfba'] (scan num: 17)


Transient Scan ID: 18     Time: 2025-10-13 20:41:20
Persistent Unique Scan ID: 'a83a1053-2101-41be-af4b-7bf4c8fade2c'
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:41:20.3 |     -1.410 |      1.841 |      1.939 |     -1.119 |    548.360 |      138.000 |      197.500 |       17.381 |       31.925 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['a83a1053'] (scan num: 18)


Transient Scan ID: 19     Time: 2025-10-13 20:41:33
Persistent Unique Scan ID: '14260c3d-2d12-44b9-8d62-91ec31d7c256'
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:41:33.1 |     -0.651 |     -0.520 |      3.933 |     -1.947 |     30.412 |      101.128 |      151.750 |        5.082 |       60.400 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['14260c3d'] (scan num: 19)


Transient Scan ID: 20     Time: 2025-10-13 20:41:47
Persistent Unique Scan ID: '3a1ec5ac-4608-4053-bc49-f6d91d8ae38f'
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:41:47.7 |     -1.037 |      3.027 |      3.408 |     -1.682 |    239.744 |      105.430 |      209.874 |       11.174 |        8.567 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['3a1ec5ac'] (scan num: 20)


Transient Scan ID: 21     Time: 2025-10-13 20:42:00
Persistent Unique Scan ID: '706e387c-3e58-4415-bb36-3af86e03d484'
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:42:00.5 |     -1.757 |      2.294 |      3.770 |     -2.558 |      2.308 |      169.714 |      149.200 |      308.153 |      281.992 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['706e387c'] (scan num: 21)


Transient Scan ID: 22     Time: 2025-10-13 20:42:16
Persistent Unique Scan ID: '117d5443-fb13-40da-ae83-d3c584e81e89'
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:42:16.8 |     -0.851 |      0.645 |      3.222 |     -1.481 |    378.249 |      109.373 |      171.412 |       18.269 |       44.212 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['117d5443'] (scan num: 22)


Transient Scan ID: 23     Time: 2025-10-13 20:42:36
Persistent Unique Scan ID: '2e7197dd-1bcf-4a6e-9c0c-022969ab32a3'
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:42:36.6 |      0.126 |      2.205 |      3.241 |     -0.766 |    483.691 |      121.323 |      180.009 |       38.113 |       10.656 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['2e7197dd'] (scan num: 23)


Transient Scan ID: 24     Time: 2025-10-13 20:42:58
Persistent Unique Scan ID: '1571883a-a0aa-4970-999d-01f1e3e82f31'
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:42:58.8 |      0.344 |      2.858 |      5.000 |     -1.716 |     44.841 |      103.713 |      186.664 |        8.434 |       24.071 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['1571883a'] (scan num: 24)


Transient Scan ID: 25     Time: 2025-10-13 20:43:22
Persistent Unique Scan ID: 'a89f3d52-095c-4e3f-98d1-03ac4aad50b0'
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:43:23.0 |     -2.156 |      1.602 |      4.175 |     -1.769 |     44.300 |      102.947 |      200.861 |        7.086 |       39.940 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['a89f3d52'] (scan num: 25)
2025-10-13 20:39:37.785 INFO: Executing plan <generator object Agent.learn at 0x7f5c134d4440>
2025-10-13 20:39:37.787 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f5c24d282c0> from 'idle' -> 'running'
2025-10-13 20:43:23.626 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f5c24d282c0> from 'running' -> 'idle'
2025-10-13 20:43:23.627 INFO: Cleaned up from plan <generator object Agent.learn at 0x7f5c134d4440>
('af22a361-5e19-4c6b-8c65-dd2ae87cae11',
 'a2573a0f-9535-49eb-96bd-144968cdba87',
 '2414bb42-d148-4b3b-be66-e4f381b6487d',
 'c6c411fd-11a0-4f43-b4a0-84ccff0fad56',
 '2b270a12-4a64-42c3-8a89-e843ea0fa818',
 'cde20903-f3ce-468b-a613-5825d02d65d1',
 'abcde7c8-20bb-452c-bbc5-23e7569a105f',
 '27e36073-7ee8-4d6f-8ec2-d2ab9430dfbe',
 '45ad787e-9627-4617-8b16-95b4ce4dad2d',
 'dcef7eb2-7c07-4742-8554-f77f4a40ccf2',
 'f93560eb-7460-468e-aa02-aad6883bba99',
 '73ed172c-4068-479b-9190-48a401b689d0',
 'a86458b0-a054-4627-906a-9fae1336e514',
 'a17ecfec-cb53-4d6b-9848-2aec409e15c4',
 '61d963e2-dc5b-4337-ad1c-1fb72ab88710',
 '0fddb6df-f24a-4262-af7d-b06a14acaa2d',
 '1dbdbfba-ac72-4ad8-94c3-8a2364923ea9',
 'a83a1053-2101-41be-af4b-7bf4c8fade2c',
 '14260c3d-2d12-44b9-8d62-91ec31d7c256',
 '3a1ec5ac-4608-4053-bc49-f6d91d8ae38f',
 '706e387c-3e58-4415-bb36-3af86e03d484',
 '117d5443-fb13-40da-ae83-d3c584e81e89',
 '2e7197dd-1bcf-4a6e-9c0c-022969ab32a3',
 '1571883a-a0aa-4970-999d-01f1e3e82f31',
 'a89f3d52-095c-4e3f-98d1-03ac4aad50b0')

Analyze Results

We can start by summarizing each step of the optimization procedure and whether trials were successful or not.

agent.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 542.712122 31.155263 39.896667 0.000000 0.000000 0.000000 0.000000
1 1 1_0 COMPLETED Sobol 504.802752 101.792083 25.290845 0.388068 2.832910 -1.688840 -1.154414
2 2 2_0 COMPLETED Sobol 0.913969 231.813312 165.560000 -3.457393 -3.936744 4.304256 4.033780
3 3 3_0 COMPLETED Sobol 54.649728 174.095764 32.374964 -0.792014 1.088601 -4.330241 -4.621093
4 4 4_0 COMPLETED Sobol 304.753981 35.306667 17.252343 2.702014 -2.172295 1.711588 0.488674
5 5 5_0 COMPLETED MBM 543.465048 45.875000 9.266667 2.259250 -0.084356 -0.807512 0.165584
6 6 6_0 COMPLETED MBM 204.107678 45.080000 29.220000 1.995411 -3.585023 -0.495463 -0.163657
7 7 7_0 COMPLETED MBM 460.098285 62.883603 37.292918 2.329860 1.481609 3.476035 0.111130
8 8 8_0 COMPLETED MBM 544.871822 17.347826 23.562500 2.486284 0.643419 0.540389 0.296320
9 9 9_0 COMPLETED MBM 548.938586 24.100000 8.780736 2.699220 -0.650062 0.246055 0.090791
10 10 10_0 COMPLETED MBM 547.402721 26.420455 23.342120 2.942696 0.158414 0.776900 -0.545334
11 11 11_0 COMPLETED MBM 550.308800 31.040000 10.275000 2.087681 0.146121 0.085052 -0.116252
12 12 12_0 COMPLETED MBM 0.293539 297.451357 285.852000 2.543189 -1.235738 -5.000000 5.000000
13 13 13_0 COMPLETED MBM 327.825930 25.078378 41.628079 5.000000 0.475322 0.109249 0.188853
14 14 14_0 COMPLETED MBM 552.262807 23.100000 8.797273 1.788778 0.302634 0.616639 -0.243461
15 15 15_0 COMPLETED MBM 548.203657 36.200000 11.083333 1.518592 0.158256 0.299756 -0.549303
16 16 16_0 COMPLETED MBM 552.602047 16.600000 10.977083 1.965290 -0.270726 1.074727 -0.076958
17 17 17_0 COMPLETED MBM 548.359956 17.380645 31.925000 -1.410045 1.840920 1.939233 -1.118664
18 18 18_0 COMPLETED MBM 30.412337 5.081994 60.400000 -0.651036 -0.520203 3.933421 -1.947015
19 19 19_0 COMPLETED MBM 239.743787 11.173810 8.567143 -1.036562 3.027000 3.407781 -1.682057
20 20 20_0 COMPLETED MBM 2.308160 308.152500 281.992000 -1.757053 2.293543 3.770426 -2.557876
21 21 21_0 COMPLETED MBM 378.248846 18.269394 44.211765 -0.851234 0.645122 3.221665 -1.480581
22 22 22_0 COMPLETED MBM 483.690947 38.113333 10.655761 0.125681 2.205469 3.241256 -0.766060
23 23 23_0 COMPLETED MBM 44.840899 8.434000 24.071429 0.343580 2.857935 5.000000 -1.715955
24 24 24_0 COMPLETED MBM 44.299519 7.086218 39.939583 -2.155716 1.602125 4.175039 -1.769257

Plotting

We also can plot slices of the parameter space with respect to our objectives.

from ax.analysis import SlicePlot

_ = agent.compute_analyses(analyses=[SlicePlot("bl_kbv_dsv", "bl_det_sum")])
bl_kbv_dsv vs. 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.compute_analyses(analyses=[SlicePlot("bl_kbv_dsv", "bl_det_wid_x")])
bl_kbv_dsv vs. 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.compute_analyses(analyses=[TopSurfacesAnalysis("bl_det_sum")])
Sensitivity Analysis for bl_det_sum

Understand how each parameter affects bl_det_sum according to a second-order sensitivity analysis.

bl_kbh_ush vs. 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.

bl_kbv_usv, bl_kbh_ush vs. bl_det_sum

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.

bl_kbv_usv vs. 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.

bl_kbv_dsv, bl_kbh_ush vs. bl_det_sum

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.

bl_kbh_dsh, bl_kbh_ush vs. bl_det_sum

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.client.get_pareto_frontier()))[0]
optimal_parameters
[INFO 10-13 20:43:30] ax.service.utils.best_point: Using inferred objective thresholds: [ObjectiveThreshold(bl_det_sum >= -8.552646286745016), ObjectiveThreshold(bl_det_wid_x <= 25.747033186890405), ObjectiveThreshold(bl_det_wid_y <= 41.975180427658756)], as objective thresholds were not specified as part of the optimization configuration on the experiment.
{'bl_kbv_dsv': 1.9652896444564145,
 'bl_kbv_usv': -0.27072600397546304,
 'bl_kbh_dsh': 1.074727342610785,
 'bl_kbh_ush': -0.07695790969598545}
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-10-13 20:43:30
Persistent Unique Scan ID: '1088a572-27a2-4bb3-b685-fc0c1fdb29ae'
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:43:30.2 |      1.965 |     -0.271 |      1.075 |     -0.077 |    549.689 |      176.000 |      115.570 |       16.600 |       10.977 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['1088a572'] (scan num: 26)
2025-10-13 20:43:30.167 INFO: Executing plan <generator object list_scan at 0x7f5bdb302d40>
2025-10-13 20:43:30.168 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f5c24d282c0> from 'idle' -> 'running'
2025-10-13 20:43:30.540 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7f5c24d282c0> from 'running' -> 'idle'
2025-10-13 20:43:30.541 INFO: Cleaned up from plan <generator object list_scan at 0x7f5bdb302d40>
image = db[uid[0]]["primary"]["bl_det_image"].read().squeeze()
plt.imshow(image)
plt.colorbar()
plt.show()