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")])
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.ax_client.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.ax_client.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_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.

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.

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>
image = tiled_client[uid[0]]["primary/bl_det_image"].read().squeeze()
plt.imshow(image)
plt.colorbar()
plt.show()