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"
[WARNING 11-06 21:27:19] 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)


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-11-06 21:27:24.251 INFO: Subprocess stdout:
2025-11-06 21:27:24.252 INFO: Subprocess stderr: Database sqlite+aiosqlite:////tmp/tmpbpy35l2z/catalog.db is new. Creating tables.
Database initialized.
Tiled version 0.2.0
2025-11-06 21:27:24.596 INFO: Tiled version 0.2.0
2025-11-06 21:27:24.601 INFO: Context impl SQLiteImpl.
2025-11-06 21:27:24.602 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")
2025-11-06 21:27:24.990 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-11-06 21:27:25
Persistent Unique Scan ID: '175429a3-c49c-4c31-8cd5-e85458996a9f'
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 | 21:27:25.3 |      0.000 |      0.000 |      0.000 |      0.000 |    543.549 |      199.039 |      149.000 |       31.155 |       39.897 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['175429a3'] (scan num: 1)


Transient Scan ID: 2     Time: 2025-11-06 21:27:26
Persistent Unique Scan ID: 'daabd171-da91-4792-96a8-4ac7c439eeb0'
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 | 21:27:26.5 |      3.775 |     -4.687 |      0.380 |     -4.527 |     -1.330 |      120.142 |      125.732 |      229.478 |      166.579 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['daabd171'] (scan num: 2)


Transient Scan ID: 3     Time: 2025-11-06 21:27:27
Persistent Unique Scan ID: '512463aa-a385-4f01-964a-bf8fcca98c4c'
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 | 21:27:27.1 |     -0.881 |      3.115 |     -1.663 |      1.420 |    542.727 |      260.389 |      208.742 |       36.411 |       10.022 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['512463aa'] (scan num: 3)


Transient Scan ID: 4     Time: 2025-11-06 21:27:27
Persistent Unique Scan ID: 'e80c4d0b-eef1-448c-9d5e-d114558a28b1'
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 | 21:27:27.7 |     -3.564 |     -0.883 |      2.990 |     -2.077 |    156.237 |      103.445 |      172.049 |        7.917 |       92.847 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['e80c4d0b'] (scan num: 4)


Transient Scan ID: 5     Time: 2025-11-06 21:27:28
Persistent Unique Scan ID: '83ba133d-61f4-421a-88b6-a80ceabc8a18'
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 | 21:27:28.4 |      1.761 |      1.821 |     -4.361 |      3.851 |      1.623 |      213.160 |      111.550 |      356.299 |      200.216 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['83ba133d'] (scan num: 5)


Transient Scan ID: 6     Time: 2025-11-06 21:27:32
Persistent Unique Scan ID: 'cb84a02a-1f04-4a6c-966b-77a4bf77875b'
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 | 21:27:32.4 |     -1.255 |      1.878 |      0.326 |     -0.147 |    552.674 |      189.500 |      195.663 |       26.996 |       28.522 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['cb84a02a'] (scan num: 6)


Transient Scan ID: 7     Time: 2025-11-06 21:27:38
Persistent Unique Scan ID: '9ac9f08f-7706-46f7-a60f-39530fccab5e'
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 | 21:27:38.1 |     -3.067 |      4.437 |     -2.341 |      0.525 |     -4.719 |      203.684 |      151.022 |      333.541 |      261.239 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['9ac9f08f'] (scan num: 7)


Transient Scan ID: 8     Time: 2025-11-06 21:27:43
Persistent Unique Scan ID: 'a5345b6e-9b57-41af-a3ac-2bb507cfde74'
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 | 21:27:43.7 |     -0.602 |      2.045 |      0.326 |      1.421 |    540.829 |      220.885 |      188.583 |       25.638 |       14.346 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['a5345b6e'] (scan num: 8)


Transient Scan ID: 9     Time: 2025-11-06 21:27:50
Persistent Unique Scan ID: 'bfcab12a-9cd5-4758-802b-e411de92aa8e'
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 | 21:27:50.7 |     -0.631 |      1.282 |     -0.758 |     -2.495 |    484.668 |      164.686 |      177.620 |      110.728 |       27.746 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['bfcab12a'] (scan num: 9)


Transient Scan ID: 10     Time: 2025-11-06 21:27:58
Persistent Unique Scan ID: 'fb5a9aa9-24da-4aaf-b6e4-7e3bd0a667f4'
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 | 21:27:58.2 |     -0.775 |     -1.108 |     -0.642 |      0.855 |    507.126 |      228.931 |      144.345 |       26.276 |       76.841 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['fb5a9aa9'] (scan num: 10)


Transient Scan ID: 11     Time: 2025-11-06 21:28:05
Persistent Unique Scan ID: '71fb98b9-0486-4437-8318-913dc00056d0'
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 | 21:28:05.4 |     -0.973 |      3.203 |      2.972 |     -0.888 |    538.007 |      122.000 |      211.500 |       32.933 |        9.680 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['71fb98b9'] (scan num: 11)


Transient Scan ID: 12     Time: 2025-11-06 21:28:14
Persistent Unique Scan ID: '4837a10f-33ff-43f8-b359-b4d913a303d4'
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 | 21:28:14.9 |     -0.584 |      2.943 |      0.936 |      0.270 |    545.874 |      185.886 |      201.562 |       17.218 |       11.270 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['4837a10f'] (scan num: 12)


Transient Scan ID: 13     Time: 2025-11-06 21:28:24
Persistent Unique Scan ID: '6f051eee-7f49-4dee-b3ab-daed7ef5dc51'
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 | 21:28:24.1 |     -0.774 |      1.580 |      5.000 |      0.223 |    281.622 |      132.572 |      184.243 |       60.055 |       24.994 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['6f051eee'] (scan num: 13)


Transient Scan ID: 14     Time: 2025-11-06 21:28:32
Persistent Unique Scan ID: '645fe0d9-1b2f-4f8a-a0d8-e56feebffd19'
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 | 21:28:32.5 |     -0.549 |      4.858 |     -0.712 |      0.388 |    213.253 |      220.938 |      213.616 |       37.450 |       18.368 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['645fe0d9'] (scan num: 14)


Transient Scan ID: 15     Time: 2025-11-06 21:28:41
Persistent Unique Scan ID: '6597e9a0-cbc2-4484-9e8a-926cf5be2eda'
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 | 21:28:41.8 |     -3.581 |     -4.346 |      5.000 |     -2.919 |      1.827 |      181.534 |      147.038 |      333.038 |      284.669 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['6597e9a0'] (scan num: 15)


Transient Scan ID: 16     Time: 2025-11-06 21:28:50
Persistent Unique Scan ID: '2f7dc1ee-f9c3-43fd-9e34-3b49fec76f89'
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 | 21:28:50.4 |     -0.681 |      0.697 |     -2.486 |      0.867 |    449.722 |      262.089 |      169.569 |       63.927 |       40.623 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['2f7dc1ee'] (scan num: 16)


Transient Scan ID: 17     Time: 2025-11-06 21:28:59
Persistent Unique Scan ID: '587e745c-2709-40b0-a951-93cd546ffa66'
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 | 21:28:59.4 |     -0.941 |      3.327 |      1.855 |      1.583 |    543.100 |      193.591 |      212.835 |       65.836 |       11.809 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['587e745c'] (scan num: 17)


Transient Scan ID: 18     Time: 2025-11-06 21:29:04
Persistent Unique Scan ID: 'af747859-7930-4045-9bac-ca6f7272eb4b'
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 | 21:29:05.0 |      0.276 |      2.156 |      1.907 |      1.596 |    537.005 |      192.667 |      177.032 |       67.600 |       12.194 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['af747859'] (scan num: 18)


Transient Scan ID: 19     Time: 2025-11-06 21:29:14
Persistent Unique Scan ID: '7618017d-9a6d-42eb-a68a-4a2013252af8'
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 | 21:29:14.3 |     -0.368 |     -0.170 |      1.796 |      0.542 |    527.586 |      173.997 |      152.000 |       38.619 |       50.317 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['7618017d'] (scan num: 19)


Transient Scan ID: 20     Time: 2025-11-06 21:29:27
Persistent Unique Scan ID: '64e420e6-0e18-4891-bc32-147fa3d1c8c3'
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 | 21:29:27.6 |      0.113 |     -0.879 |      1.154 |      1.790 |    507.802 |      211.295 |      134.270 |       53.142 |       54.582 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['64e420e6'] (scan num: 20)


Transient Scan ID: 21     Time: 2025-11-06 21:29:37
Persistent Unique Scan ID: 'c73e0817-c5f4-46cf-bd19-c3750e8e372c'
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 | 21:29:37.6 |     -1.644 |      1.642 |      3.207 |     -1.464 |    385.757 |      109.785 |      198.000 |       19.045 |       40.161 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['c73e0817'] (scan num: 21)


Transient Scan ID: 22     Time: 2025-11-06 21:29:45
Persistent Unique Scan ID: 'd0d2c88c-ec2d-48e9-bdeb-b53c7004ea20'
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 | 21:29:45.4 |     -1.480 |      2.848 |      1.843 |     -2.354 |    439.016 |      119.280 |      213.514 |       35.701 |       14.957 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['d0d2c88c'] (scan num: 22)


Transient Scan ID: 23     Time: 2025-11-06 21:29:51
Persistent Unique Scan ID: 'af2a7a79-8d82-4d07-a44a-21bfc1f76cd3'
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 | 21:29:51.3 |     -1.150 |      3.493 |      5.000 |     -4.327 |      1.433 |      217.526 |      147.501 |      315.185 |      286.647 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['af2a7a79'] (scan num: 23)


Transient Scan ID: 24     Time: 2025-11-06 21:29:56
Persistent Unique Scan ID: 'b917a00f-7837-417e-8256-681d1bd0d3b0'
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 | 21:29:56.7 |     -2.116 |      2.737 |      2.147 |     -1.012 |    314.544 |      135.967 |      214.598 |       17.087 |       16.432 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['b917a00f'] (scan num: 24)


Transient Scan ID: 25     Time: 2025-11-06 21:30:04
Persistent Unique Scan ID: '3d27555a-2620-4a0a-a4a6-8b513a656cf7'
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 | 21:30:04.6 |     -0.346 |      2.620 |     -1.574 |      2.446 |    547.788 |      279.111 |      193.165 |       16.944 |       10.236 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['3d27555a'] (scan num: 25)
2025-11-06 21:27:25.087 INFO: Executing plan <generator object Agent.learn at 0x7fc3907ba540>
2025-11-06 21:27:25.088 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7fc390a1bf20> from 'idle' -> 'running'
2025-11-06 21:30:05.182 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7fc390a1bf20> from 'running' -> 'idle'
2025-11-06 21:30:05.183 INFO: Cleaned up from plan <generator object Agent.learn at 0x7fc3907ba540>
('175429a3-c49c-4c31-8cd5-e85458996a9f',
 'daabd171-da91-4792-96a8-4ac7c439eeb0',
 '512463aa-a385-4f01-964a-bf8fcca98c4c',
 'e80c4d0b-eef1-448c-9d5e-d114558a28b1',
 '83ba133d-61f4-421a-88b6-a80ceabc8a18',
 'cb84a02a-1f04-4a6c-966b-77a4bf77875b',
 '9ac9f08f-7706-46f7-a60f-39530fccab5e',
 'a5345b6e-9b57-41af-a3ac-2bb507cfde74',
 'bfcab12a-9cd5-4758-802b-e411de92aa8e',
 'fb5a9aa9-24da-4aaf-b6e4-7e3bd0a667f4',
 '71fb98b9-0486-4437-8318-913dc00056d0',
 '4837a10f-33ff-43f8-b359-b4d913a303d4',
 '6f051eee-7f49-4dee-b3ab-daed7ef5dc51',
 '645fe0d9-1b2f-4f8a-a0d8-e56feebffd19',
 '6597e9a0-cbc2-4484-9e8a-926cf5be2eda',
 '2f7dc1ee-f9c3-43fd-9e34-3b49fec76f89',
 '587e745c-2709-40b0-a951-93cd546ffa66',
 'af747859-7930-4045-9bac-ca6f7272eb4b',
 '7618017d-9a6d-42eb-a68a-4a2013252af8',
 '64e420e6-0e18-4891-bc32-147fa3d1c8c3',
 'c73e0817-c5f4-46cf-bd19-c3750e8e372c',
 'd0d2c88c-ec2d-48e9-bdeb-b53c7004ea20',
 'af2a7a79-8d82-4d07-a44a-21bfc1f76cd3',
 'b917a00f-7837-417e-8256-681d1bd0d3b0',
 '3d27555a-2620-4a0a-a4a6-8b513a656cf7')

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 543.549143 31.155263 39.896667 0.000000 0.000000 0.000000 0.000000
1 1 1_0 COMPLETED Sobol -1.329838 229.478309 166.578929 3.774975 -4.687191 0.380294 -4.526971
2 2 2_0 COMPLETED Sobol 542.727228 36.411111 10.022212 -0.881318 3.115303 -1.662784 1.419990
3 3 3_0 COMPLETED Sobol 156.236875 7.916920 92.847222 -3.564300 -0.883405 2.989666 -2.077426
4 4 4_0 COMPLETED Sobol 1.622949 356.299375 200.216333 1.760652 1.821436 -4.361023 3.851227
5 5 5_0 COMPLETED MBM 552.674176 26.996429 28.522074 -1.255103 1.877739 0.326479 -0.147385
6 6 6_0 COMPLETED MBM -4.718911 333.540873 261.238542 -3.067489 4.436882 -2.341389 0.525311
7 7 7_0 COMPLETED MBM 540.829136 25.638462 14.345833 -0.602253 2.044941 0.325910 1.421244
8 8 8_0 COMPLETED MBM 484.668131 110.727778 27.746154 -0.630516 1.281676 -0.758181 -2.494583
9 9 9_0 COMPLETED MBM 507.126155 26.275959 76.841385 -0.775086 -1.107616 -0.642255 0.855155
10 10 10_0 COMPLETED MBM 538.006822 32.933333 9.680000 -0.972999 3.202615 2.971870 -0.888421
11 11 11_0 COMPLETED MBM 545.873571 17.217727 11.269744 -0.583877 2.942794 0.936007 0.270153
12 12 12_0 COMPLETED MBM 281.621856 60.055172 24.993922 -0.773628 1.579916 5.000000 0.223135
13 13 13_0 COMPLETED MBM 213.252812 37.450000 18.367742 -0.549290 4.858164 -0.711897 0.388085
14 14 14_0 COMPLETED MBM 1.826830 333.037949 284.669383 -3.580649 -4.345928 5.000000 -2.918626
15 15 15_0 COMPLETED MBM 449.721656 63.927326 40.623077 -0.681448 0.696891 -2.486489 0.867143
16 16 16_0 COMPLETED MBM 543.100414 65.836364 11.808913 -0.941341 3.326977 1.854913 1.583376
17 17 17_0 COMPLETED MBM 537.005080 67.600000 12.194268 0.276154 2.156423 1.906834 1.595618
18 18 18_0 COMPLETED MBM 527.585833 38.619016 50.316667 -0.368384 -0.169542 1.795749 0.542277
19 19 19_0 COMPLETED MBM 507.801696 53.141836 54.582429 0.113354 -0.879326 1.153878 1.789564
20 20 20_0 COMPLETED MBM 385.757346 19.044853 40.161111 -1.644104 1.641852 3.207266 -1.463896
21 21 21_0 COMPLETED MBM 439.015614 35.701357 14.956757 -1.480097 2.847604 1.842664 -2.354437
22 22 22_0 COMPLETED MBM 1.433320 315.184848 286.646642 -1.150091 3.492883 5.000000 -4.326694
23 23 23_0 COMPLETED MBM 314.543790 17.086667 16.431746 -2.115979 2.737320 2.147388 -1.011654
24 24 24_0 COMPLETED MBM 547.787863 16.944444 10.236458 -0.346012 2.619716 -1.574303 2.446125

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_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.

bl_kbv_dsv, bl_kbh_dsh 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 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_kbv_usv 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.

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 11-06 21:30:08] ax.service.utils.best_point: Using inferred objective thresholds: [ObjectiveThreshold(bl_det_sum >= 115.69903984441274), ObjectiveThreshold(bl_det_wid_x <= 22.64452458331587), ObjectiveThreshold(bl_det_wid_y <= 102.85992230176592)], as objective thresholds were not specified as part of the optimization configuration on the experiment.
{'bl_kbv_dsv': -0.3460118706654314,
 'bl_kbv_usv': 2.619716134717018,
 'bl_kbh_dsh': -1.5743033585319601,
 'bl_kbh_ush': 2.446125093034421}
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-11-06 21:30:08
Persistent Unique Scan ID: '7109f6f7-c237-4df9-b7f0-cc84b538fd87'
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 | 21:30:08.5 |     -0.346 |      2.620 |     -1.574 |      2.446 |    551.705 |      279.111 |      193.165 |       16.944 |       10.236 |
+-----------+------------+------------+------------+------------+------------+------------+--------------+--------------+--------------+--------------+
generator list_scan ['7109f6f7'] (scan num: 26)
2025-11-06 21:30:08.414 INFO: Executing plan <generator object list_scan at 0x7fc358c86d40>
2025-11-06 21:30:08.416 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7fc390a1bf20> from 'idle' -> 'running'
2025-11-06 21:30:08.768 INFO: Change state on <bluesky.run_engine.RunEngine object at 0x7fc390a1bf20> from 'running' -> 'idle'
2025-11-06 21:30:08.769 INFO: Cleaned up from plan <generator object list_scan at 0x7fc358c86d40>
image = db[uid[0]]["primary"]["bl_det_image"].read().squeeze()
plt.imshow(image)
plt.colorbar()
plt.show()