Demonstrating “Bring Your Own Beamline” simulation with XRT#
In this tutorial we’ll show a simulation optimization workflow by loading arbitrary XRT setups using xml/json. By the end, you should be able to go to XRT qook/glow and build your beamline from there to export and drop in to blop. Or if you are lucky enough for an XRT model to be already built for you, export to xml and load in blop.
Some Environment Setup#
note, like all other demos you need the blop_sim subpackage to run
import logging
import warnings
import matplotlib.pyplot as plt
import numpy as np
from bluesky.callbacks.best_effort import BestEffortCallback
# Import simulation devices (requires: pip install -e sim/)
from bluesky.run_engine import RunEngine
from bluesky.utils import ProgressBarManager
from bluesky_tiled_plugins import TiledWriter
from tiled.client import from_uri # type: ignore[import-untyped]
from tiled.client.container import Container
from tiled.server import SimpleTiledServer
from blop.ax import Agent, Objective, RangeDOF
from blop.protocols import EvaluationFunction
from blop_sim.backends import XRTBackend
from blop_sim.devices.xrt import infer_detectors, infer_variables
# Suppress noisy logs from httpx and dependency deprecation warnings
logging.getLogger("httpx").setLevel(logging.WARNING)
warnings.filterwarnings("ignore", category=FutureWarning)
# Enable interactive plotting
plt.ion()
DETECTOR_STORAGE = "/tmp/blop/sim"
[INFO 07-28 17:28:44] ax.storage.sqa_store.with_db_settings_base: Ax SQL storage initialized with SQLAlchemy 2.0.51
/home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.13/site-packages/xrt/backends/raycing/sources/sybase.py:78: SyntaxWarning: invalid escape sequence '\s'
:math:`\beta_i = \frac{\sigma_i^{2}}{\epsilon_i}`, with
fileName = r"toroid_focus.xml"
beam = XRTBackend(file=fileName)
dets = infer_detectors(beam)
motors = infer_variables(beam, filter_for=None)
created inferred variable toroid_focus:screen01:center:z of float type as value is None or auto.
Be careful when setting this variable as the type is guessed as float by default.
A small view of the inferred motors#
for name, element in motors.items():
print(name)
for nm, motor in element.items():
print(f"{nm} : {motor}")
bendingMagnet01
B0 : <InferredVariable::toroid_focus:bendingMagnet01:B0=<class 'float'>:1.0>
rho : <InferredVariable::toroid_focus:bendingMagnet01:rho=<class 'float'>:10.00692285594456>
toroidMirror01
R : <InferredVariable::toroid_focus:toroidMirror01:R=<class 'float'>:152982.84327559808>
r : <InferredVariable::toroid_focus:toroidMirror01:r=<class 'float'>:1162.0765699687756>
screen01
center:x : <InferredVariable::toroid_focus:screen01:center:x=<class 'int'>:0>
center:y : <InferredVariable::toroid_focus:screen01:center:y=<class 'int'>:30000>
center:z : <InferredVariable::toroid_focus:screen01:center:z=<class 'float'>:auto>
x:x : <InferredVariable::toroid_focus:screen01:x:x=<class 'float'>:1.0>
x:y : <InferredVariable::toroid_focus:screen01:x:y=<class 'float'>:-0.0>
x:z : <InferredVariable::toroid_focus:screen01:x:z=<class 'float'>:0.0>
z:x : <InferredVariable::toroid_focus:screen01:z:x=<class 'float'>:0.0>
z:y : <InferredVariable::toroid_focus:screen01:z:y=<class 'float'>:0.0>
z:z : <InferredVariable::toroid_focus:screen01:z:z=<class 'float'>:1.0>
Another glimpse into the inferred detectors#
for name, det in dets.items():
print(f"{name} : {det}")
bendingMagnet01 : <blop_sim.devices.xrt.auto_element.InferredDetector object at 0x7fa944c4dd30>
toroidMirror01 : <blop_sim.devices.xrt.auto_element.InferredDetector object at 0x7fa944bd39d0>
screen01 : <blop_sim.devices.xrt.auto_element.InferredDetector object at 0x7fa944bd3b10>
Setting up an optimization#
toro_R = motors["toroidMirror01"]["R"]
toro_R.alias = "big_r"
toro_r = motors["toroidMirror01"]["r"]
screen = dets["screen01"]
screen.set_primary()
VERTICAL_BOUNDS = (toro_R.val - 15000, toro_R.val + 15000)
HORIZONTAL_BOUNDS = (toro_r.val - 500, toro_r.val + 500)
# Define DOFs using mirror radius signals
dofs = [
RangeDOF(actuator=toro_R, bounds=VERTICAL_BOUNDS, parameter_type="float"),
RangeDOF(actuator=toro_r, bounds=HORIZONTAL_BOUNDS, parameter_type="float"),
]
tiled_server = SimpleTiledServer()
tiled_client = from_uri(tiled_server.uri)
tiled_writer = TiledWriter(tiled_client)
RE = RunEngine({})
bec = BestEffortCallback()
# Send all metadata/data captured to the BestEffortCallback.
# RE.subscribe(bec)
RE.waiting_hook = ProgressBarManager()
tiled_client = from_uri(tiled_server.uri)
tiled_writer = TiledWriter(tiled_client)
RE.subscribe(tiled_writer)
Tiled version 0.2.14
0
# Single objective: minimize the geometric-mean FWHM
objectives = [
Objective(name="fwhm", minimize=True),
]
class DetectorEvaluation(EvaluationFunction):
def __init__(self, tiled_client: Container):
self.tiled_client = tiled_client
def _fwhm_from_profile(self, profile: np.ndarray) -> float:
"""Compute FWHM from a 1D marginal profile.
Finds the half-maximum crossing points with sub-pixel interpolation.
Returns a large value if the beam is too dim or fills the entire detector.
"""
peak = profile.max()
if peak == 0:
return float(len(profile)) # No signal — return detector width as penalty
half_max = peak / 2.0
above = profile >= half_max
if not above.any():
return float(len(profile))
indices = np.where(above)[0]
left_idx = indices[0]
right_idx = indices[-1]
# Sub-pixel interpolation at left crossing
if left_idx > 0:
left = left_idx - 1 + (half_max - profile[left_idx - 1]) / (profile[left_idx] - profile[left_idx - 1])
else:
left = 0.0
# Sub-pixel interpolation at right crossing
if right_idx < len(profile) - 1:
right = right_idx + (half_max - profile[right_idx]) / (profile[right_idx + 1] - profile[right_idx])
else:
right = float(len(profile) - 1)
return right - left
def _compute_stats(self, image: np.ndarray) -> tuple[float, float]:
"""Compute FWHM and integrated intensity from a beam image.
Returns
-------
fwhm : float
Geometric mean of the horizontal and vertical FWHM (in pixels).
intensity : float
Total integrated intensity (sum of all pixel values).
"""
gray = image.squeeze().astype(np.float64)
if gray.ndim == 3:
gray = gray.mean(axis=-1)
# Integrated intensity (total flux on detector)
intensity = gray.sum()
if intensity == 0:
return 400.0, 0.0 # No beam — return max FWHM penalty
# Marginal profiles: project onto each axis
x_profile = gray.sum(axis=0) # sum along Y rows -> X profile
y_profile = gray.sum(axis=1) # sum along X cols -> Y profile
fwhm_x = self._fwhm_from_profile(x_profile)
fwhm_y = self._fwhm_from_profile(y_profile)
# Geometric mean FWHM — targets a small, round spot
fwhm = np.sqrt(fwhm_x * fwhm_y)
return float(fwhm), float(intensity)
def __call__(self, uid: str, suggestions: list[dict]) -> list[dict]:
outcomes = []
run = self.tiled_client[uid]
# Read beam images from detector
images = run[f"primary/{screen.name}"].read()
# Suggestion IDs stored in start document metadata
suggestion_ids = [suggestion["_id"] for suggestion in run.metadata["start"]["blop_suggestions"]]
# Compute statistics from each image
for idx, sid in enumerate(suggestion_ids):
image = images[idx]
fwhm, intensity = self._compute_stats(image)
outcome = {
"_id": sid,
"fwhm": fwhm,
# "intensity": intensity,
}
outcomes.append(outcome)
return outcomes
agent = Agent(
sensors=[screen],
dofs=dofs,
objectives=objectives,
evaluation_function=DetectorEvaluation(tiled_client),
name="xrt-blop-demo",
description="A demo of the Blop agent with XRT simulated beamline",
experiment_type="demo",
)
# Run 1 iteration with a batch of 10 points for initial exploration
RE(agent.optimize(1, n_points=10))
╭───────────────────────────────────────────────── Optimization ──────────────────────────────────────────────────╮ │ Optimizer AxOptimizer │ │ Actuators big_r, toroid_focus:toroidMirror01:r │ │ Sensors screen01 │ │ Iterations 1 Points/iter 10 │ │ Run UID 0c48bbc6-7c3d-45d2-9ede-ed2cb892fd70 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
125591 rays of 500000
250715 rays of 500000
375837 rays of 500000
501565 rays of 500000
screen01
center:
[0.0, 30000.0, 1763.2705775903494]
[INFO 07-28 17:28:50] ax.api.client: GenerationStrategy(name='Center+Sobol+MBM:fast', nodes=[CenterGenerationNode(next_node_name='Sobol', use_existing_trials_for_initialization=True), GenerationNode(name='Sobol', generator_specs=[GeneratorSpec(generator_enum=Sobol, generator_key_override=None)], transition_criteria=[MinTrials(transition_to='MBM'), MinTrials(transition_to='MBM')], suggested_experiment_status=ExperimentStatus.INITIALIZATION, pausing_criteria=[MaxTrialsAwaitingData(threshold=5)]), GenerationNode(name='MBM', generator_specs=[GeneratorSpec(generator_enum=BoTorch, generator_key_override=None)], transition_criteria=None, suggested_experiment_status=ExperimentStatus.OPTIMIZATION, pausing_criteria=None)]) chosen based on user input and problem structure.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 0 with parameters {'big_r': 152982.843276, 'toroid_focus:toroidMirror01:r': 1162.07657} using GenerationNode CenterOfSearchSpace.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 1 with parameters {'big_r': 145398.236121, 'toroid_focus:toroidMirror01:r': 1309.918679} using GenerationNode Sobol.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 2 with parameters {'big_r': 160157.286524, 'toroid_focus:toroidMirror01:r': 1041.052447} using GenerationNode Sobol.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 3 with parameters {'big_r': 165845.632869, 'toroid_focus:toroidMirror01:r': 1443.179306} using GenerationNode Sobol.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 4 with parameters {'big_r': 151077.091554, 'toroid_focus:toroidMirror01:r': 674.439288} using GenerationNode Sobol.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 5 with parameters {'big_r': 146024.532346, 'toroid_focus:toroidMirror01:r': 1581.85832} using GenerationNode Sobol.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 6 with parameters {'big_r': 161288.831494, 'toroid_focus:toroidMirror01:r': 848.275501} using GenerationNode Sobol.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 7 with parameters {'big_r': 155573.462676, 'toroid_focus:toroidMirror01:r': 1198.582433} using GenerationNode Sobol.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 8 with parameters {'big_r': 140372.670637, 'toroid_focus:toroidMirror01:r': 964.873435} using GenerationNode Sobol.
[INFO 07-28 17:28:50] ax.api.client: Generated new trial 9 with parameters {'big_r': 138226.612601, 'toroid_focus:toroidMirror01:r': 1474.784081} using GenerationNode Sobol.
[INFO 07-28 17:29:19] ax.api.client: Trial 9 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 8 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 1 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 5 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 4 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 0 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 2 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 6 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 3 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 7 marked COMPLETED.
[INFO 07-28 17:29:19] ax.api.client: Trial 0 marked COMPLETED.
────────────────────────────────────────── Iteration 1 / 1 (10 points) ───────────────────────────────────────────
Acquire UID a2d344d5-2f9f-47b4-b273-544f4f9b7439
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ big_r ┃ toroid_focus:toroidMirror01:r ┃ fwhm ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩ │ 0 │ 0 │ 152983 │ 1162.08 │ 38.3015 │ │ 1 │ 1 │ 145398 │ 1309.92 │ 16.2013 │ │ 2 │ 2 │ 160157 │ 1041.05 │ 17.4272 │ │ 3 │ 3 │ 165846 │ 1443.18 │ 60.7359 │ │ 4 │ 4 │ 151077 │ 674.439 │ 26.6438 │ │ 5 │ 5 │ 146025 │ 1581.86 │ 19.1713 │ │ 6 │ 6 │ 161289 │ 848.276 │ 15.8496 │ │ 7 │ 7 │ 155573 │ 1198.58 │ 77.0534 │ │ 8 │ 8 │ 140373 │ 964.873 │ 12.6198 │ │ 9 │ 9 │ 138227 │ 1474.78 │ 15.9499 │ └───────┴───────────────┴────────┴───────────────────────────────┴─────────┘
fwhm min: 12.6198 max: 77.0534 mean: 29.9954 (10 pts sampled)
Summary Statistics ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┓ ┃ Name ┃ Type ┃ Min ┃ Max ┃ Mean ┃ Std ┃ Count ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━┩ │ big_r │ param │ 138227 │ 165846 │ 151695 │ 9203.69 │ 10 │ │ toroid_focus:toroidMirror01:r │ param │ 674.439 │ 1581.86 │ 1169.9 │ 291.623 │ 10 │ │ fwhm │ outcome │ 12.6198 │ 77.0534 │ 29.9954 │ 22.1217 │ 10 │ └───────────────────────────────┴─────────┴─────────┴─────────┴─────────┴─────────┴───────┘
────────────────────────────────────────────── Optimization Complete ──────────────────────────────────────────────
('0c48bbc6-7c3d-45d2-9ede-ed2cb892fd70',
'a2d344d5-2f9f-47b4-b273-544f4f9b7439')
# Run more iterations
RE(agent.optimize(5, n_points=5))
╭───────────────────────────────────────────────── Optimization ──────────────────────────────────────────────────╮ │ Optimizer AxOptimizer │ │ Actuators big_r, toroid_focus:toroidMirror01:r │ │ Sensors screen01 │ │ Iterations 5 more (1 completed, 6 total) Points/iter 5 │ │ Run UID 0a07e5e9-57c6-4d40-8ee2-ba6f731f5228 │ ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
[INFO 07-28 17:29:21] ax.api.client: Generated new trial 10 with parameters {'big_r': 142552.529623, 'toroid_focus:toroidMirror01:r': 1662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:21] ax.api.client: Generated new trial 11 with parameters {'big_r': 138912.300526, 'toroid_focus:toroidMirror01:r': 662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:21] ax.api.client: Generated new trial 12 with parameters {'big_r': 142901.500396, 'toroid_focus:toroidMirror01:r': 662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:21] ax.api.client: Generated new trial 13 with parameters {'big_r': 140113.143129, 'toroid_focus:toroidMirror01:r': 1662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:21] ax.api.client: Generated new trial 14 with parameters {'big_r': 146846.087723, 'toroid_focus:toroidMirror01:r': 662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:33] ax.api.client: Trial 10 marked COMPLETED.
[INFO 07-28 17:29:33] ax.api.client: Trial 13 marked COMPLETED.
[INFO 07-28 17:29:33] ax.api.client: Trial 11 marked COMPLETED.
[INFO 07-28 17:29:33] ax.api.client: Trial 12 marked COMPLETED.
[INFO 07-28 17:29:33] ax.api.client: Trial 14 marked COMPLETED.
[INFO 07-28 17:29:38] ax.api.client: Generated new trial 15 with parameters {'big_r': 142176.329772, 'toroid_focus:toroidMirror01:r': 1308.949748} using GenerationNode MBM.
[INFO 07-28 17:29:38] ax.api.client: Generated new trial 16 with parameters {'big_r': 142559.88062, 'toroid_focus:toroidMirror01:r': 1311.335974} using GenerationNode MBM.
[INFO 07-28 17:29:38] ax.api.client: Generated new trial 17 with parameters {'big_r': 141775.81881, 'toroid_focus:toroidMirror01:r': 1331.37397} using GenerationNode MBM.
[INFO 07-28 17:29:38] ax.api.client: Generated new trial 18 with parameters {'big_r': 161162.570712, 'toroid_focus:toroidMirror01:r': 1662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:38] ax.api.client: Generated new trial 19 with parameters {'big_r': 142556.439659, 'toroid_focus:toroidMirror01:r': 1430.043773} using GenerationNode MBM.
[INFO 07-28 17:29:50] ax.api.client: Trial 18 marked COMPLETED.
[INFO 07-28 17:29:50] ax.api.client: Trial 19 marked COMPLETED.
[INFO 07-28 17:29:50] ax.api.client: Trial 17 marked COMPLETED.
[INFO 07-28 17:29:50] ax.api.client: Trial 15 marked COMPLETED.
[INFO 07-28 17:29:50] ax.api.client: Trial 16 marked COMPLETED.
[INFO 07-28 17:29:54] ax.api.client: Generated new trial 20 with parameters {'big_r': 159870.192969, 'toroid_focus:toroidMirror01:r': 662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:54] ax.api.client: Generated new trial 21 with parameters {'big_r': 159436.628663, 'toroid_focus:toroidMirror01:r': 662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:54] ax.api.client: Generated new trial 22 with parameters {'big_r': 150002.566849, 'toroid_focus:toroidMirror01:r': 1662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:54] ax.api.client: Generated new trial 23 with parameters {'big_r': 160262.239497, 'toroid_focus:toroidMirror01:r': 662.07657} using GenerationNode MBM.
[INFO 07-28 17:29:54] ax.api.client: Generated new trial 24 with parameters {'big_r': 167982.843276, 'toroid_focus:toroidMirror01:r': 662.07657} using GenerationNode MBM.
[INFO 07-28 17:30:07] ax.api.client: Trial 21 marked COMPLETED.
[INFO 07-28 17:30:07] ax.api.client: Trial 20 marked COMPLETED.
[INFO 07-28 17:30:07] ax.api.client: Trial 23 marked COMPLETED.
[INFO 07-28 17:30:07] ax.api.client: Trial 24 marked COMPLETED.
[INFO 07-28 17:30:07] ax.api.client: Trial 22 marked COMPLETED.
[INFO 07-28 17:30:12] ax.api.client: Generated new trial 25 with parameters {'big_r': 143287.336686, 'toroid_focus:toroidMirror01:r': 986.585398} using GenerationNode MBM.
[INFO 07-28 17:30:12] ax.api.client: Generated new trial 26 with parameters {'big_r': 137982.843276, 'toroid_focus:toroidMirror01:r': 1118.146096} using GenerationNode MBM.
[INFO 07-28 17:30:12] ax.api.client: Generated new trial 27 with parameters {'big_r': 148904.012598, 'toroid_focus:toroidMirror01:r': 1078.240649} using GenerationNode MBM.
[INFO 07-28 17:30:12] ax.api.client: Generated new trial 28 with parameters {'big_r': 140073.859933, 'toroid_focus:toroidMirror01:r': 1294.887357} using GenerationNode MBM.
[INFO 07-28 17:30:12] ax.api.client: Generated new trial 29 with parameters {'big_r': 140902.378246, 'toroid_focus:toroidMirror01:r': 1485.310689} using GenerationNode MBM.
[INFO 07-28 17:30:24] ax.api.client: Trial 29 marked COMPLETED.
[INFO 07-28 17:30:24] ax.api.client: Trial 28 marked COMPLETED.
[INFO 07-28 17:30:24] ax.api.client: Trial 26 marked COMPLETED.
[INFO 07-28 17:30:24] ax.api.client: Trial 25 marked COMPLETED.
[INFO 07-28 17:30:24] ax.api.client: Trial 27 marked COMPLETED.
[INFO 07-28 17:30:30] ax.api.client: Generated new trial 30 with parameters {'big_r': 143106.209136, 'toroid_focus:toroidMirror01:r': 1145.395445} using GenerationNode MBM.
[INFO 07-28 17:30:30] ax.api.client: Generated new trial 31 with parameters {'big_r': 137982.843276, 'toroid_focus:toroidMirror01:r': 1662.07657} using GenerationNode MBM.
[INFO 07-28 17:30:30] ax.api.client: Generated new trial 32 with parameters {'big_r': 141700.622181, 'toroid_focus:toroidMirror01:r': 1155.676177} using GenerationNode MBM.
[INFO 07-28 17:30:30] ax.api.client: Generated new trial 33 with parameters {'big_r': 143978.719797, 'toroid_focus:toroidMirror01:r': 1215.47124} using GenerationNode MBM.
[INFO 07-28 17:30:30] ax.api.client: Generated new trial 34 with parameters {'big_r': 144829.635065, 'toroid_focus:toroidMirror01:r': 1013.18701} using GenerationNode MBM.
[INFO 07-28 17:30:43] ax.api.client: Trial 33 marked COMPLETED.
[INFO 07-28 17:30:43] ax.api.client: Trial 31 marked COMPLETED.
[INFO 07-28 17:30:43] ax.api.client: Trial 32 marked COMPLETED.
[INFO 07-28 17:30:43] ax.api.client: Trial 30 marked COMPLETED.
[INFO 07-28 17:30:43] ax.api.client: Trial 34 marked COMPLETED.
─────────────────────────────────────────── Iteration 2 / 6 (5 points) ───────────────────────────────────────────
Acquire UID 1cf0057b-cab9-4c9c-be8e-85961a845d2f
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ big_r ┃ toroid_focus:toroidMirror01:r ┃ fwhm ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩ │ 0 │ 10 │ 142553 │ 1662.08 │ 10.5673 │ │ 1 │ 11 │ 138912 │ 662.077 │ 20.7404 │ │ 2 │ 12 │ 142902 │ 662.077 │ 15.6037 │ │ 3 │ 13 │ 140113 │ 1662.08 │ 13.4675 │ │ 4 │ 14 │ 146846 │ 662.077 │ 24.5438 │ └───────┴───────────────┴────────┴───────────────────────────────┴─────────┘
fwhm min: 10.5673 max: 77.0534 mean: 25.6584 (15 pts sampled)
─────────────────────────────────────────── Iteration 3 / 6 (5 points) ───────────────────────────────────────────
Acquire UID 32f78c2e-2850-4a2d-b911-544976f40bac
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ big_r ┃ toroid_focus:toroidMirror01:r ┃ fwhm ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩ │ 0 │ 15 │ 142176 │ 1308.95 │ 9.6592 │ │ 1 │ 16 │ 142560 │ 1311.34 │ 10.0167 │ │ 2 │ 17 │ 141776 │ 1331.37 │ 10.6624 │ │ 3 │ 18 │ 161163 │ 1662.08 │ 63.3133 │ │ 4 │ 19 │ 142556 │ 1430.04 │ 9.80408 │ └───────┴───────────────┴────────┴───────────────────────────────┴─────────┘
fwhm min: 9.6592 max: 77.0534 mean: 24.4166 (20 pts sampled)
─────────────────────────────────────────── Iteration 4 / 6 (5 points) ───────────────────────────────────────────
Acquire UID 835c82f3-2c9a-43f6-80eb-6c493693f001
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ big_r ┃ toroid_focus:toroidMirror01:r ┃ fwhm ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩ │ 0 │ 20 │ 159870 │ 662.077 │ 18.289 │ │ 1 │ 21 │ 159437 │ 662.077 │ 20.2275 │ │ 2 │ 22 │ 150003 │ 1662.08 │ 41.7434 │ │ 3 │ 23 │ 160262 │ 662.077 │ 48.3928 │ │ 4 │ 24 │ 167983 │ 662.077 │ 54.7266 │ └───────┴───────────────┴────────┴───────────────────────────────┴─────────┘
fwhm min: 9.6592 max: 77.0534 mean: 26.8685 (25 pts sampled)
─────────────────────────────────────────── Iteration 5 / 6 (5 points) ───────────────────────────────────────────
Acquire UID 99a7bbcf-8a73-49a7-a4ad-feb306cc1024
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ big_r ┃ toroid_focus:toroidMirror01:r ┃ fwhm ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩ │ 0 │ 25 │ 143287 │ 986.585 │ 12.4555 │ │ 1 │ 26 │ 137983 │ 1118.15 │ 16.3164 │ │ 2 │ 27 │ 148904 │ 1078.24 │ 20.1454 │ │ 3 │ 28 │ 140074 │ 1294.89 │ 13.1625 │ │ 4 │ 29 │ 140902 │ 1485.31 │ 12.0901 │ └───────┴───────────────┴────────┴───────────────────────────────┴─────────┘
fwhm min: 9.6592 max: 77.0534 mean: 24.8627 (30 pts sampled)
─────────────────────────────────────────── Iteration 6 / 6 (5 points) ───────────────────────────────────────────
Acquire UID 8d246185-6c1b-49f9-93b0-2156a5cf05a6
┏━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┓ ┃ Event ┃ Suggestion ID ┃ big_r ┃ toroid_focus:toroidMirror01:r ┃ fwhm ┃ ┡━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━┩ │ 0 │ 30 │ 143106 │ 1145.4 │ 11.2553 │ │ 1 │ 31 │ 137983 │ 1662.08 │ 17.4012 │ │ 2 │ 32 │ 141701 │ 1155.68 │ 8.74728 │ │ 3 │ 33 │ 143979 │ 1215.47 │ 13.7494 │ │ 4 │ 34 │ 144830 │ 1013.19 │ 14.6752 │ └───────┴───────────────┴────────┴───────────────────────────────┴─────────┘
fwhm min: 8.74728 max: 77.0534 mean: 23.1917 (35 pts sampled)
Summary Statistics ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┓ ┃ Name ┃ Type ┃ Min ┃ Max ┃ Mean ┃ Std ┃ Count ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━┩ │ big_r │ param │ 137983 │ 167983 │ 147966 │ 8841.61 │ 35 │ │ toroid_focus:toroidMirror01:r │ param │ 662.077 │ 1662.08 │ 1157.67 │ 347.125 │ 35 │ │ fwhm │ outcome │ 8.74728 │ 77.0534 │ 23.1917 │ 17.5212 │ 35 │ └───────────────────────────────┴─────────┴─────────┴─────────┴─────────┴─────────┴───────┘
────────────────────────────────────────────── Optimization Complete ──────────────────────────────────────────────
('0a07e5e9-57c6-4d40-8ee2-ba6f731f5228',
'1cf0057b-cab9-4c9c-be8e-85961a845d2f',
'32f78c2e-2850-4a2d-b911-544976f40bac',
'835c82f3-2c9a-43f6-80eb-6c493693f001',
'99a7bbcf-8a73-49a7-a4ad-feb306cc1024',
'8d246185-6c1b-49f9-93b0-2156a5cf05a6')
_ = agent.ax_client.compute_analyses()
[ERROR 07-28 17:30:45] ax.core.experiment: Encountered ValueError Data to attach is empty. while attaching results. Proceeding and returning results fetched without attaching.
[ERROR 07-28 17:30:45] ax.core.experiment: Encountered ValueError Data to attach is empty. while attaching results. Proceeding and returning results fetched without attaching.
[ERROR 07-28 17:30:45] ax.core.experiment: Encountered ValueError Data to attach is empty. while attaching results. Proceeding and returning results fetched without attaching.
[ERROR 07-28 17:30:45] ax.core.experiment: Encountered ValueError Data to attach is empty. while attaching results. Proceeding and returning results fetched without attaching.
[ERROR 07-28 17:30:45] ax.core.experiment: Encountered ValueError Data to attach is empty. while attaching results. Proceeding and returning results fetched without attaching.
[ERROR 07-28 17:30:45] ax.core.experiment: Encountered ValueError Data to attach is empty. while attaching results. Proceeding and returning results fetched without attaching.
[ERROR 07-28 17:30:45] ax.core.experiment: Encountered ValueError Data to attach is empty. while attaching results. Proceeding and returning results fetched without attaching.
[ERROR 07-28 17:30:45] ax.analysis.analysis: Failed to compute TransferLearningAnalysis
[ERROR 07-28 17:30:45] ax.analysis.analysis: Traceback (most recent call last):
File "/home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.13/site-packages/ax/analysis/analysis.py", line 115, in compute_result
card = self.compute(
experiment=experiment,
generation_strategy=generation_strategy,
adapter=adapter,
)
File "/home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.13/site-packages/ax/analysis/healthcheck/transfer_learning_analysis.py", line 104, in compute
transferable_experiments = identify_transferable_experiments(
search_space=experiment.search_space,
...<4 lines>...
experiment_name=experiment.name,
)
File "/home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.13/site-packages/ax/storage/sqa_store/load.py", line 839, in identify_transferable_experiments
experiments_search_spaces = _query_historical_experiments_given_parameters(
parameter_names=list(search_space.parameters.keys()),
experiment_types=experiment_types,
config=config,
)
File "/home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.13/site-packages/ax/storage/sqa_store/load.py", line 759, in _query_historical_experiments_given_parameters
with session_scope() as session:
~~~~~~~~~~~~~^^
File "/home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.13/contextlib.py", line 141, in __enter__
return next(self.gen)
File "/home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.13/site-packages/ax/storage/sqa_store/db.py", line 287, in session_scope
session = get_session()
File "/home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.13/site-packages/ax/storage/sqa_store/db.py", line 263, in get_session
init_engine_and_session_factory()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^
File "/home/runner/work/blop/blop/.pixi/envs/docs/lib/python3.13/site-packages/ax/storage/sqa_store/db.py", line 191, in init_engine_and_session_factory
raise ValueError("Must specify either `url` or `creator`.")
ValueError: Must specify either `url` or `creator`.
This analysis provides an overview of the entire optimization process. It includes visualizations of the results obtained so far, insights into the parameter and metric relationships learned by the Ax model, diagnostics such as model fit, and health checks to assess the overall health of the experiment.
Result Analyses provide a high-level overview of the results of the optimization process so far with respect to the metrics specified in experiment design.
These pair of plots visualize the metric effects for each arm, with the Ax model predictions on the left and the raw observed data on the right. The predicted effects apply shrinkage for noise and adjust for non-stationarity in the data, so they are more representative of the reproducible effects that will manifest in a long-term validation experiment.
| trial_index | arm_name | trial_status | generation_node | fwhm | big_r | toroid_focus:toroidMirror01:r | |
|---|---|---|---|---|---|---|---|
| 0 | 32 | 32_0 | COMPLETED | MBM | 8.747275 | 141700.622181 | 1155.676177 |
| trial_index | arm_name | trial_status | generation_node | fwhm | big_r | toroid_focus:toroidMirror01:r | |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0_0 | COMPLETED | CenterOfSearchSpace | 38.301529 | 152982.843276 | 1162.076570 |
| 1 | 1 | 1_0 | COMPLETED | Sobol | 16.201340 | 145398.236121 | 1309.918679 |
| 2 | 2 | 2_0 | COMPLETED | Sobol | 17.427218 | 160157.286524 | 1041.052447 |
| 3 | 3 | 3_0 | COMPLETED | Sobol | 60.735904 | 165845.632869 | 1443.179306 |
| 4 | 4 | 4_0 | COMPLETED | Sobol | 26.643834 | 151077.091554 | 674.439288 |
| 5 | 5 | 5_0 | COMPLETED | Sobol | 19.171328 | 146024.532346 | 1581.858320 |
| 6 | 6 | 6_0 | COMPLETED | Sobol | 15.849621 | 161288.831494 | 848.275501 |
| 7 | 7 | 7_0 | COMPLETED | Sobol | 77.053370 | 155573.462676 | 1198.582433 |
| 8 | 8 | 8_0 | COMPLETED | Sobol | 12.619759 | 140372.670637 | 964.873435 |
| 9 | 9 | 9_0 | COMPLETED | Sobol | 15.949864 | 138226.612601 | 1474.784081 |
| 10 | 10 | 10_0 | COMPLETED | MBM | 10.567268 | 142552.529623 | 1662.076570 |
| 11 | 11 | 11_0 | COMPLETED | MBM | 20.740411 | 138912.300526 | 662.076570 |
| 12 | 12 | 12_0 | COMPLETED | MBM | 15.603704 | 142901.500396 | 662.076570 |
| 13 | 13 | 13_0 | COMPLETED | MBM | 13.467454 | 140113.143129 | 1662.076570 |
| 14 | 14 | 14_0 | COMPLETED | MBM | 24.543823 | 146846.087723 | 662.076570 |
| 15 | 15 | 15_0 | COMPLETED | MBM | 9.659196 | 142176.329772 | 1308.949748 |
| 16 | 16 | 16_0 | COMPLETED | MBM | 10.016747 | 142559.880620 | 1311.335974 |
| 17 | 17 | 17_0 | COMPLETED | MBM | 10.662418 | 141775.818810 | 1331.373970 |
| 18 | 18 | 18_0 | COMPLETED | MBM | 63.313327 | 161162.570712 | 1662.076570 |
| 19 | 19 | 19_0 | COMPLETED | MBM | 9.804084 | 142556.439659 | 1430.043773 |
| 20 | 20 | 20_0 | COMPLETED | MBM | 18.288981 | 159870.192969 | 662.076570 |
| 21 | 21 | 21_0 | COMPLETED | MBM | 20.227451 | 159436.628663 | 662.076570 |
| 22 | 22 | 22_0 | COMPLETED | MBM | 41.743425 | 150002.566849 | 1662.076570 |
| 23 | 23 | 23_0 | COMPLETED | MBM | 48.392807 | 160262.239497 | 662.076570 |
| 24 | 24 | 24_0 | COMPLETED | MBM | 54.726581 | 167982.843276 | 662.076570 |
| 25 | 25 | 25_0 | COMPLETED | MBM | 12.455523 | 143287.336686 | 986.585398 |
| 26 | 26 | 26_0 | COMPLETED | MBM | 16.316409 | 137982.843276 | 1118.146096 |
| 27 | 27 | 27_0 | COMPLETED | MBM | 20.145375 | 148904.012598 | 1078.240649 |
| 28 | 28 | 28_0 | COMPLETED | MBM | 13.162487 | 140073.859933 | 1294.887357 |
| 29 | 29 | 29_0 | COMPLETED | MBM | 12.090061 | 140902.378246 | 1485.310689 |
| 30 | 30 | 30_0 | COMPLETED | MBM | 11.255295 | 143106.209136 | 1145.395445 |
| 31 | 31 | 31_0 | COMPLETED | MBM | 17.401187 | 137982.843276 | 1662.076570 |
| 32 | 32 | 32_0 | COMPLETED | MBM | 8.747275 | 141700.622181 | 1155.676177 |
| 33 | 33 | 33_0 | COMPLETED | MBM | 13.749409 | 143978.719797 | 1215.471240 |
| 34 | 34 | 34_0 | COMPLETED | MBM | 14.675176 | 144829.635065 | 1013.187010 |
Insight Analyses display information to help understand the underlying experiment i.e parameter and metric relationships learned by the Ax model.Use this information to better understand your experiment space and users.
The top surfaces analysis displays three analyses in one. First, it shows parameter sensitivities, which shows the sensitivity of the metrics in the experiment to the most important parameters. Subsetting to only the most important parameters, it then shows slice plots and contour plots for each metric in the experiment, displaying the relationship between the metric and the most important parameters.
These plots show the relationship between a metric and a parameter. They show the predicted values of the metric on the y-axis as a function of the parameter on the x-axis while keeping all other parameters fixed at their status_quo value (if available), best trial value, or the center of the search space.
These plots show the relationship between a metric and two parameters. They show the predicted values of the metric (indicated by color) as a function of the two parameters on the x- and y-axes while keeping all other parameters fixed at their status_quo value (if available), best trial value, or the center of the search space.
Diagnostic Analyses provide information about the optimization process and the quality of the model fit. You can use this information to understand if the experimental design should be adjusted to improve optimization quality.
Cross-validation plots display the model fit for each metric in the experiment. The model is trained on a subset of the data and then predicts the outcome for the remaining subset. The plots show the predicted outcome for the validation set on the y-axis against its actual value on the x-axis. Points that align closely with the dotted diagonal line indicate a strong model fit, signifying accurate predictions. Additionally, the plots include confidence intervals that provide insight into the noise in observations and the uncertainty in model predictions.
NOTE: A horizontal, flat line of predictions indicates that the model has not picked up on sufficient signal in the data, and instead is just predicting the mean.
Comprehensive health checks designed to identify potential issues in the Ax experiment. These checks cover areas such as metric fetching, search space configuration, and candidate generation, with the aim of flagging areas where user intervention may be necessary to ensure the experiment's robustness and success.
| Metric | Status | Details | |
|---|---|---|---|
| 0 | fwhm | Improved | **Metric `fwhm` improved 77.16%** from `38.30` in arm `'0_0'` to `8.75` in arm `'32_0'`. |
agent.ax_client.summarize()
| trial_index | arm_name | trial_status | generation_node | fwhm | big_r | toroid_focus:toroidMirror01:r | |
|---|---|---|---|---|---|---|---|
| 0 | 0 | 0_0 | COMPLETED | CenterOfSearchSpace | 38.301529 | 152982.843276 | 1162.076570 |
| 1 | 1 | 1_0 | COMPLETED | Sobol | 16.201340 | 145398.236121 | 1309.918679 |
| 2 | 2 | 2_0 | COMPLETED | Sobol | 17.427218 | 160157.286524 | 1041.052447 |
| 3 | 3 | 3_0 | COMPLETED | Sobol | 60.735904 | 165845.632869 | 1443.179306 |
| 4 | 4 | 4_0 | COMPLETED | Sobol | 26.643834 | 151077.091554 | 674.439288 |
| 5 | 5 | 5_0 | COMPLETED | Sobol | 19.171328 | 146024.532346 | 1581.858320 |
| 6 | 6 | 6_0 | COMPLETED | Sobol | 15.849621 | 161288.831494 | 848.275501 |
| 7 | 7 | 7_0 | COMPLETED | Sobol | 77.053370 | 155573.462676 | 1198.582433 |
| 8 | 8 | 8_0 | COMPLETED | Sobol | 12.619759 | 140372.670637 | 964.873435 |
| 9 | 9 | 9_0 | COMPLETED | Sobol | 15.949864 | 138226.612601 | 1474.784081 |
| 10 | 10 | 10_0 | COMPLETED | MBM | 10.567268 | 142552.529623 | 1662.076570 |
| 11 | 11 | 11_0 | COMPLETED | MBM | 20.740411 | 138912.300526 | 662.076570 |
| 12 | 12 | 12_0 | COMPLETED | MBM | 15.603704 | 142901.500396 | 662.076570 |
| 13 | 13 | 13_0 | COMPLETED | MBM | 13.467454 | 140113.143129 | 1662.076570 |
| 14 | 14 | 14_0 | COMPLETED | MBM | 24.543823 | 146846.087723 | 662.076570 |
| 15 | 15 | 15_0 | COMPLETED | MBM | 9.659196 | 142176.329772 | 1308.949748 |
| 16 | 16 | 16_0 | COMPLETED | MBM | 10.016747 | 142559.880620 | 1311.335974 |
| 17 | 17 | 17_0 | COMPLETED | MBM | 10.662418 | 141775.818810 | 1331.373970 |
| 18 | 18 | 18_0 | COMPLETED | MBM | 63.313327 | 161162.570712 | 1662.076570 |
| 19 | 19 | 19_0 | COMPLETED | MBM | 9.804084 | 142556.439659 | 1430.043773 |
| 20 | 20 | 20_0 | COMPLETED | MBM | 18.288981 | 159870.192969 | 662.076570 |
| 21 | 21 | 21_0 | COMPLETED | MBM | 20.227451 | 159436.628663 | 662.076570 |
| 22 | 22 | 22_0 | COMPLETED | MBM | 41.743425 | 150002.566849 | 1662.076570 |
| 23 | 23 | 23_0 | COMPLETED | MBM | 48.392807 | 160262.239497 | 662.076570 |
| 24 | 24 | 24_0 | COMPLETED | MBM | 54.726581 | 167982.843276 | 662.076570 |
| 25 | 25 | 25_0 | COMPLETED | MBM | 12.455523 | 143287.336686 | 986.585398 |
| 26 | 26 | 26_0 | COMPLETED | MBM | 16.316409 | 137982.843276 | 1118.146096 |
| 27 | 27 | 27_0 | COMPLETED | MBM | 20.145375 | 148904.012598 | 1078.240649 |
| 28 | 28 | 28_0 | COMPLETED | MBM | 13.162487 | 140073.859933 | 1294.887357 |
| 29 | 29 | 29_0 | COMPLETED | MBM | 12.090061 | 140902.378246 | 1485.310689 |
| 30 | 30 | 30_0 | COMPLETED | MBM | 11.255295 | 143106.209136 | 1145.395445 |
| 31 | 31 | 31_0 | COMPLETED | MBM | 17.401187 | 137982.843276 | 1662.076570 |
| 32 | 32 | 32_0 | COMPLETED | MBM | 8.747275 | 141700.622181 | 1155.676177 |
| 33 | 33 | 33_0 | COMPLETED | MBM | 13.749409 | 143978.719797 | 1215.471240 |
| 34 | 34 | 34_0 | COMPLETED | MBM | 14.675176 | 144829.635065 | 1013.187010 |
optimal_parameters, metrics, _, _ = agent.ax_client.get_best_parameterization(use_model_predictions=False)
optimal_parameters
{'big_r': 141700.62218067932,
'toroid_focus:toroidMirror01:r': 1155.676177494709}
from bluesky.plans import list_scan
uid = RE(
list_scan(
[screen],
toro_r,
[optimal_parameters[toro_r.name]],
toro_R,
[optimal_parameters[toro_R.name]],
)
)