Skip to content

Xopt integration - #318

Merged
thopkins32 merged 26 commits into
bluesky:mainfrom
roussel-ryan:xopt
Jul 9, 2026
Merged

Xopt integration#318
thopkins32 merged 26 commits into
bluesky:mainfrom
roussel-ryan:xopt

Conversation

@roussel-ryan

Copy link
Copy Markdown
Contributor

This pull request adds support for integrating the Xopt optimization library into blop, introducing a new agent, optimizer, and mapping utilities, along with comprehensive tests for these components. The changes enable users to use Xopt Generator objects within the existing framework, and ensure robust mapping and interaction between the framework's abstractions and Xopt's API.

This PR should serve as a starting point for discussing Xopt integration into blop or bluesky-adaptive (bluesky/bluesky-adaptive#61).

The most important changes are:

Xopt Integration:

  • Added XoptAgent, XoptOptimizer, and build_vocs to the codebase, providing a new agent and optimizer that wrap Xopt generators and a utility for mapping framework abstractions to Xopt's VOCS format (src/blop/xopt/agent.py, src/blop/xopt/optimizer.py, src/blop/xopt/mapping.py, src/blop/xopt/__init__.py). [1] [2]

  • Made the new Xopt components available at the top-level API by importing them in src/blop/__init__.py and adding them to __all__. [1] [2]

Dependency Management:

  • Added xopt as an optional dependency in pyproject.toml to enable Xopt-based optimization.

Testing and Validation:

  • Added comprehensive tests for the Xopt agent (test_agent.py), optimizer (test_optimizer.py), and VOCS mapping (test_mapping.py), covering initialization, suggestion, ingestion, checkpointing, constraint handling, and error cases. [1] [2] [3]

@checkmarx-gh-ast-us-povs

checkmarx-gh-ast-us-povs Bot commented Jun 4, 2026

Copy link
Copy Markdown

Logo
Checkmarx One – Scan Summary & Detailsc7733f77-c632-419a-967c-1d7ef41d7346


New Issues (1) Checkmarx found the following issues in this Pull Request
# Severity Issue Source File / Package Checkmarx Insight
1 HIGH Deserialization_of_Untrusted_Data src/blop/xopt/optimizer.py: 49
detailsThe serialized object stream processed in  in the file /src/blop/xopt/optimizer.py at line 49 is deserialized by load in the file /src/blop/xopt/o...
ID: rrz2NO86clojLL1mHn8JwmtiXOE%3D
Attack Vector

Communicate with Checkmarx by submitting a PR comment with @Checkmarx followed by one of the supported commands. Learn about the supported commands here.

Comment thread src/blop/xopt/mapping.py Outdated
@roussel-ryan

Copy link
Copy Markdown
Contributor Author

Note: after discussion, I will refactor this PR to not do automatic conversion to VOCS parlance and just pass the generator object to an optimizer

@roussel-ryan

roussel-ryan commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@thopkins32 so it looks like we need to make a decision since the more recent versions of botorch (.v0.17.0) require python >=3.11 meaning that Xopt does the same, how do you think we should resolve this? I could potentially re-enable support 3.10, but only if this is something you all think is necessary

@thopkins32

Copy link
Copy Markdown
Collaborator

@roussel-ryan I will open a separate issue to remove Python 3.10 support, feel free to do that in this PR for now to unblock

@whs92

whs92 commented Jun 6, 2026

Copy link
Copy Markdown
Member

Can you give a quick overview of the advantages of using Xopt over AX? Why might I use one or the other? Or is there just an existing community using Xopt that we want to serve?

@roussel-ryan

roussel-ryan commented Jun 7, 2026

Copy link
Copy Markdown
Contributor Author

Hi, there are several advantages to using Xopt over Ax for blop, primarily due to our focus on R&D towards accelerator / beam physics, however we do not intend to replace Ax completely. Some of the reasons:

  • Xopt supports other optimization algorithms that can be used for online operation / optimization including Simplex, RCDS, Extremum Seeking, Genetic algorithms, and multiple variants of BO (most based on botorch, just as Ax is). We will shortly be adding methods for Reinforcement Learning and algorithms provided by scipy minimize
  • We have added features to BO that are not included out of the box in Ax as it is currently implemented in blop, including first class support for trust region BO, time-dependent / contextual BO, multi-fidelity BO, interpolated measurements etc. (see https://journals.aps.org/prab/abstract/10.1103/PhysRevAccelBeams.27.084801)
  • Xopt is wrapped by Badger https://github.com/xopt-org/Badger which provides a GUI interface for running optimization in control rooms. Utilizing Xopt generators in blop takes a step forward for creating a GUI that works for blop
  • The same algorithms provided by Xopt used in online control via blop can be easily applied towards simulations and arbitrary problems, improving consistent use of algorithms across problems for users

Finally, supporting Xopt in blop more closely connects R&D efforts in accelerators and photon beamlines, allowing developments in one field to benefit the other. This PR is motivated by discussions this past week at the DSSI workshop for autonomous beamline control at BNL with @thopkins32 @tacaswell @mrakitin and others

@whs92

whs92 commented Jun 8, 2026

Copy link
Copy Markdown
Member

@roussel-ryan I am particularly interested in adding context to optimization. Thanks for your explanation.

@roussel-ryan

Copy link
Copy Markdown
Contributor Author

Good to hear, please keep an eye on xopt-org/Xopt#425 which should be in the next release

@whs92

whs92 commented Jun 8, 2026

Copy link
Copy Markdown
Member

As far as I know adding additional observations for context was already supported by the earlier pre-AX version of blop. Whatever we come up with, blop should abstract away the differences (if they exist) between the different back ends so that if I want to provide context (or anything else) I shouldn't care whether I am talking to AX or XopT in the background.

@roussel-ryan

Copy link
Copy Markdown
Contributor Author

Based on previous discussions, we wanted to try to keep the Ax/Xopt interfaces separate (see previous comments above) and not include a translation layer to unify the interfaces to the user. I think we should discuss this further, but it may be a good initial step to get Xopt support capability integrated into blop first and then work on improving the user interface. I want to hear other folks opinions on the matter

@roussel-ryan

Copy link
Copy Markdown
Contributor Author

I've addressed all the issues on my side, I didn't make any changes to tutorials/xrt-kb-mirrors.md so I think that might be an issue that you all want to work on

@roussel-ryan
roussel-ryan marked this pull request as ready for review June 8, 2026 15:52

@thopkins32 thopkins32 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initial review done. I'll follow up with a more in-depth one after I get clarification on one point.

Comment on lines +41 to +43
self._next_id = 0
self._params_by_id: dict[int | str, dict[str, Any]] = {}
self._seed_state_from_existing_data()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the Xopt docs, is the data frame index of self._generator.data something we can use instead of doing ID tracking in Blop? I don't want to duplicate state tracking here if Xopt already has a mechanism for this.

The reason we have an ID associated with every suggestion is that when we evaluate multiple points in a single optimizer iteration (e.g., RE(optimize(..., n_points=5))) we may have a more optimal sampling route than the default order provided by the optimizer. Bluesky always emits events in the order they were collected (and we cache this reordering information in the Bluesky metadata). Therefore, to match Bluesky's event/collection order with the optimizer suggestion order, we need to track IDs for each suggestion.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would keep the ID tracking in Blop, certainly for now, but going forward as well. I think Xopt may adopt a more formal ID tracking formalism. Certainly we shouldn't hold up this PR to decide this IMO

@thopkins32

Copy link
Copy Markdown
Collaborator

Also, I merged the change removing Python 3.10 support if you would like to rebase or merge main into this branch.

@roussel-ryan roussel-ryan left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread src/blop/xopt/optimizer.py Outdated
Comment thread src/blop/xopt/optimizer.py Outdated
Comment thread src/blop/xopt/optimizer.py
Comment thread src/blop/xopt/optimizer.py Outdated
Comment thread src/blop/xopt/optimizer.py Outdated
Comment thread src/blop/tests/xopt/test_optimizer.py
Comment thread src/blop/xopt/optimizer.py
Comment thread src/blop/__init__.py Outdated
Comment thread src/blop/__init__.py Outdated
@thopkins32
thopkins32 self-requested a review July 9, 2026 18:25
@thopkins32
thopkins32 merged commit 9e0f135 into bluesky:main Jul 9, 2026
10 checks passed
@roussel-ryan

Copy link
Copy Markdown
Contributor Author

@whs92 just as a followup the most recent version of Xopt (3.2.0) now supports contextual BO (see https://xopt.xopt.org/examples/single_objective_bayes_opt/contextual_bo/ for an example)

jessica-moylan added a commit to jessica-moylan/blop that referenced this pull request Jul 28, 2026
commit 39b6afc
Merge: 2441457 9bcc903
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Thu Jul 23 12:37:56 2026 -0400

    Merge pull request bluesky#331 from bluesky/contributing

    Add CONTRIBUTING.md

commit 9bcc903
Author: thomashopkins32 <thopkins1@bnl.gov>
Date:   Thu Jul 23 10:40:12 2026 -0400

    pre-commit

commit 2b68d8a
Author: thomashopkins32 <thopkins1@bnl.gov>
Date:   Thu Jul 23 10:39:51 2026 -0400

    Updated Review and Merge Policy; Types of Changes section

commit 2441457
Author: josephhanrahan <79729091+josephhanrahan@users.noreply.github.com>
Date:   Wed Jul 22 14:36:00 2026 -0400

    move queueserver_agent testcases to new test module (bluesky#332)

commit 1fee80a
Author: thomashopkins32 <thopkins1@bnl.gov>
Date:   Wed Jul 22 14:07:09 2026 -0400

    Add CONTRIBUTING.md

commit c2332cf
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Wed Jul 22 13:38:41 2026 -0400

    Set checkpoint path after init on Ax agent and optimizer (bluesky#327)

commit 0a75969
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Wed Jul 22 13:34:21 2026 -0400

    Add checkpointing to queueserver runner (bluesky#328)

    * Add checkpointing to queueserver runner

    * Add checkpoint_interval argument to QueueserverAgent.run

commit 70468ab
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Thu Jul 16 15:43:52 2026 -0400

    Final edits before v1.0 release (bluesky#324)

    * Cleaned up all docstrings and other misc items

    * Add release history for v1.0.0

    * Add deployments page

    * Add docs on callbacks

    * Update timepix3 description

commit 9e0f135
Author: Ryan Roussel <rroussel@slac.stanford.edu>
Date:   Thu Jul 9 11:36:34 2026 -0700

    Xopt integration (bluesky#318)

    * initial commit

    * add tests

    * Update test_optimizer.py

    * linting

    * linting

    * inline comments

    * refactor code to only define an XoptOptimizer class

    * linting

    * solving pre-commit issues

    * change code to native xopt vocs methods

    * remove python 3.10

    * linting

    * Update test_optimizer.py

    * add tests for coverage

    * Update pyproject.toml

    * linting

    * create RunEngine test and random initial point generation

    * remove fixed parameters in favor of VOCS constants

    * utilize pydantic serialization, fix ingest append/insert issues

    * code simplification /modernization

    * additional code simplification

    * linting

    * Update xrt-kb-mirrors.md

    * Update src/blop/__init__.py

    * Update src/blop/__init__.py

    ---------

    Co-authored-by: Thomas Hopkins <thomashopkins000@gmail.com>

commit 1406049
Merge: 697ca51 7e3d7c3
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Mon Jul 6 11:10:50 2026 -0400

    Merge pull request bluesky#323 from bluesky/Explanation_docs

    Explanation passages to go into depth about user responsible components

commit 7e3d7c3
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Mon Jul 6 10:31:25 2026 -0400

    Update docs/source/explanations/evaluation-function.rst

    dropping highly contextual sidenote

    Co-authored-by: Thomas Hopkins <thopkins1@bnl.gov>

commit aa83a24
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Mon Jul 6 10:23:14 2026 -0400

    Update docs/source/explanations/evaluation-function.rst

    Yeah, I had this in to personally disambiguate between bluesky document driven and run end uid event driven processing. But, given that i explicitly stated uid this is a bit of a muddying reference.

    Co-authored-by: Thomas Hopkins <thopkins1@bnl.gov>

commit 13d14e0
Author: Rhys Takahashi <19mt01@gmail.com>
Date:   Mon Jun 29 13:46:40 2026 -0400

    impl fixed suggested by J Moylan

commit 7b8db61
Author: Rhys Takahashi <19mt01@gmail.com>
Date:   Mon Jun 29 12:38:02 2026 -0400

    added explanation passages to go into more depth about user responsible components

commit 697ca51
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Mon Jun 8 15:40:36 2026 -0400

    Update & Rework Dependencies (bluesky#321)

    * Update & rework dependencies

    * Update docs with dependencies

    * Add 'all' extra; Rename 'qs' to 'queueserver'; Add extras table to installation docs

commit 90a01fa
Author: Will Smith <ecgatt.ws@gmail.com>
Date:   Mon Jun 8 20:26:02 2026 +0200

    Start queueserver listener in runner init (bluesky#316)

    * Start queueserver listener in runner init

    * Ignore unrelated Blop documents in queueserver listener

    * ruff formatting

    * removed redundant start_doc_filter

    * moved correlation id check bcack into _process_acquisition method

    * corrected pytest to match previous check on ignoring other blop runs

    * ruff linting for queueserver.py2

commit 7af7cc1
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Thu May 28 14:58:46 2026 -0400

    Replace ZMQ address argument with RemoteDispatcher for queueserver integration (bluesky#308)

commit df10ad6
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Thu May 28 12:04:02 2026 -0400

    version bump (bluesky#315)

commit 2ddab57
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Tue May 26 12:51:28 2026 -0400

    XRT KB mirror tutorial improvements (bluesky#311)

    * Fix z-coordinate of toroid

    * Minimize fwhm; track intensity and ensure > 10000

    * Removed checking optimization health section; Reduced BO iterations to 10 from 20

    * Fix best parameters returned by Ax

commit fb28042
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Mon May 25 09:00:52 2026 -0400

    Stop publishing docs on scheduled workflow (bluesky#310)

commit 69d1ff7
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Sun May 24 11:56:33 2026 -0400

    Document that queueserver integration is experimental (bluesky#309)
jessica-moylan added a commit to jessica-moylan/blop that referenced this pull request Jul 28, 2026
commit 0dfa3f2
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Tue Jul 28 13:10:14 2026 -0400

    Use proper autostart API for queueserver (bluesky#326)

    * Add temp raw prefix

    * Add sleeps

    * Autostart the queue properly

    * Fix merge issue

commit 39b6afc
Merge: 2441457 9bcc903
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Thu Jul 23 12:37:56 2026 -0400

    Merge pull request bluesky#331 from bluesky/contributing

    Add CONTRIBUTING.md

commit 9bcc903
Author: thomashopkins32 <thopkins1@bnl.gov>
Date:   Thu Jul 23 10:40:12 2026 -0400

    pre-commit

commit 2b68d8a
Author: thomashopkins32 <thopkins1@bnl.gov>
Date:   Thu Jul 23 10:39:51 2026 -0400

    Updated Review and Merge Policy; Types of Changes section

commit 2441457
Author: josephhanrahan <79729091+josephhanrahan@users.noreply.github.com>
Date:   Wed Jul 22 14:36:00 2026 -0400

    move queueserver_agent testcases to new test module (bluesky#332)

commit 1fee80a
Author: thomashopkins32 <thopkins1@bnl.gov>
Date:   Wed Jul 22 14:07:09 2026 -0400

    Add CONTRIBUTING.md

commit c2332cf
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Wed Jul 22 13:38:41 2026 -0400

    Set checkpoint path after init on Ax agent and optimizer (bluesky#327)

commit 0a75969
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Wed Jul 22 13:34:21 2026 -0400

    Add checkpointing to queueserver runner (bluesky#328)

    * Add checkpointing to queueserver runner

    * Add checkpoint_interval argument to QueueserverAgent.run

commit 70468ab
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Thu Jul 16 15:43:52 2026 -0400

    Final edits before v1.0 release (bluesky#324)

    * Cleaned up all docstrings and other misc items

    * Add release history for v1.0.0

    * Add deployments page

    * Add docs on callbacks

    * Update timepix3 description

commit 9e0f135
Author: Ryan Roussel <rroussel@slac.stanford.edu>
Date:   Thu Jul 9 11:36:34 2026 -0700

    Xopt integration (bluesky#318)

    * initial commit

    * add tests

    * Update test_optimizer.py

    * linting

    * linting

    * inline comments

    * refactor code to only define an XoptOptimizer class

    * linting

    * solving pre-commit issues

    * change code to native xopt vocs methods

    * remove python 3.10

    * linting

    * Update test_optimizer.py

    * add tests for coverage

    * Update pyproject.toml

    * linting

    * create RunEngine test and random initial point generation

    * remove fixed parameters in favor of VOCS constants

    * utilize pydantic serialization, fix ingest append/insert issues

    * code simplification /modernization

    * additional code simplification

    * linting

    * Update xrt-kb-mirrors.md

    * Update src/blop/__init__.py

    * Update src/blop/__init__.py

    ---------

    Co-authored-by: Thomas Hopkins <thomashopkins000@gmail.com>

commit 1406049
Merge: 697ca51 7e3d7c3
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Mon Jul 6 11:10:50 2026 -0400

    Merge pull request bluesky#323 from bluesky/Explanation_docs

    Explanation passages to go into depth about user responsible components

commit 7e3d7c3
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Mon Jul 6 10:31:25 2026 -0400

    Update docs/source/explanations/evaluation-function.rst

    dropping highly contextual sidenote

    Co-authored-by: Thomas Hopkins <thopkins1@bnl.gov>

commit aa83a24
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Mon Jul 6 10:23:14 2026 -0400

    Update docs/source/explanations/evaluation-function.rst

    Yeah, I had this in to personally disambiguate between bluesky document driven and run end uid event driven processing. But, given that i explicitly stated uid this is a bit of a muddying reference.

    Co-authored-by: Thomas Hopkins <thopkins1@bnl.gov>

commit 13d14e0
Author: Rhys Takahashi <19mt01@gmail.com>
Date:   Mon Jun 29 13:46:40 2026 -0400

    impl fixed suggested by J Moylan

commit 7b8db61
Author: Rhys Takahashi <19mt01@gmail.com>
Date:   Mon Jun 29 12:38:02 2026 -0400

    added explanation passages to go into more depth about user responsible components

commit 697ca51
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Mon Jun 8 15:40:36 2026 -0400

    Update & Rework Dependencies (bluesky#321)

    * Update & rework dependencies

    * Update docs with dependencies

    * Add 'all' extra; Rename 'qs' to 'queueserver'; Add extras table to installation docs

commit 90a01fa
Author: Will Smith <ecgatt.ws@gmail.com>
Date:   Mon Jun 8 20:26:02 2026 +0200

    Start queueserver listener in runner init (bluesky#316)

    * Start queueserver listener in runner init

    * Ignore unrelated Blop documents in queueserver listener

    * ruff formatting

    * removed redundant start_doc_filter

    * moved correlation id check bcack into _process_acquisition method

    * corrected pytest to match previous check on ignoring other blop runs

    * ruff linting for queueserver.py2

commit 7af7cc1
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Thu May 28 14:58:46 2026 -0400

    Replace ZMQ address argument with RemoteDispatcher for queueserver integration (bluesky#308)

commit df10ad6
Author: MTakahashi-KWH <60798296+MTakahashi-KWH@users.noreply.github.com>
Date:   Thu May 28 12:04:02 2026 -0400

    version bump (bluesky#315)

commit 2ddab57
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Tue May 26 12:51:28 2026 -0400

    XRT KB mirror tutorial improvements (bluesky#311)

    * Fix z-coordinate of toroid

    * Minimize fwhm; track intensity and ensure > 10000

    * Removed checking optimization health section; Reduced BO iterations to 10 from 20

    * Fix best parameters returned by Ax

commit fb28042
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Mon May 25 09:00:52 2026 -0400

    Stop publishing docs on scheduled workflow (bluesky#310)

commit 69d1ff7
Author: Thomas Hopkins <thopkins1@bnl.gov>
Date:   Sun May 24 11:56:33 2026 -0400

    Document that queueserver integration is experimental (bluesky#309)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants