Badger

ML optimization for accelerator control rooms — in daily use at 7+ facilities.

Badger is the optimizer that sits in the accelerator control room: an operator picks a routine, sets bounds, presses run, and a Bayesian or evolutionary algorithm tunes the live machine while every step is archived. I created it at SLAC in 2021 and led it through 2025; it is now the tuning front end at accelerator facilities across the US and Europe.

Why

Machine tuning used to be a person at a console turning knobs one at a time, and the optimization algorithms that could do it better lived in notebooks that only their authors could run. The gap was not algorithms; it was a product: something an operator on shift could trust, that spoke the control system's protocols, respected hardware limits, and left a record. Badger is that layer, built on the Xopt optimization engine so the algorithms stay shared across labs.

How

Three small abstractions carry the whole design, and they are the reason it travels between machines:

Badger architecture: an algorithm exposed as an optimize(evaluate, params) function exchanges X and Y with Badger; Badger calls an environment class whose evaluate(X) returns Y, and the environment talks to the machine through an interface class; the Badger GUI exchanges configs and (X, Y) with the core.
Figure 1. The three abstractions. An algorithm only sees an evaluate function; the environment turns a trial point X into machine settings and returns objectives and constraints Y; the interface alone speaks the control-system protocol; the GUI, CLI and API sit on top of the same core. Figure from the IPAC'22 paper.

The same routine runs from a GUI, a CLI, a Python API or a minimal launcher. Runs execute in a subprocess and are written to disk every second, so a crashed session or a killed process never loses the data that explains what the machine did. Facilities add their own environments and interfaces through a plugin repository rather than by forking the app.

Screenshot of the Badger main window: a history navigator of archived runs by date on the left, the routine editor with variables, bounds, initial points and objectives in the centre, and live plots of objectives and variables with a run-data table on the right.
Figure 2. The operator's view (Badger 1.3, from the project README): archived runs by date, the routine editor with per-variable bounds and initial points, live objective and variable traces, the raw run data, and run controls along the bottom.

What I did. Designed the architecture, wrote about half of all commits across 16 contributors, shipped its releases through mid-2025, ran all of its LCLS beamline testing through 2025, and first-authored the paper. Since then I have kept contributing the agent-facing remote-control surface (launch with a routine, hot-swap from a watched file, stream evaluations, stop without closing the window) that Otter uses to drive a Badger window while the operator watches the same plots.

Results

Outcomes reported by the facilities running it, not benchmark numbers:

Facility results are from the operators' own publications (ICALEPCS'25 for SLAC, ICALEPCS'23 for ESRF).