Premise
A subset of Bluesky RunEngine optimization streams should be well-structured within the event model (i.e. data lives directly in event documents) and acquisition plans (default_acquire). Because of this, we can provide reusable default implementations for evaluation-function data handling using common stream/data-store patterns. The goal is to providing utility to avoid "reinventing" the wheel every time they want to do a simple opt without taking on strict internal API guarantees around data handling.
I've been experimenting with decorators to separate data handling from explicit per sample data processing, also enabling code separation between:
- run-to-run configuration changes
- system/setup-level configuration
For simple or tightly integrated systems, this could make fast-start optimization workflows much cleaner.
Example
dofs = [
RangeDOF(actuator=motor1, bounds=(-3, 3), parameter_type="float"),
RangeDOF(actuator=motor2, bounds=(-3, 3), parameter_type="float"),
RangeDOF(actuator=motor3, bounds=(-3, 3), parameter_type="float"),
RangeDOF(actuator=motor4, bounds=(-3, 3), parameter_type="float"),
]
objectives = [
Objective(name="beam_peak", minimize=False),
]
readables = [det]
//////////////////////////// new:
@tiled_link(tiled_client,channels=[det])
def cost(measures):
evaluation = 5*np.exp(-.1*measures[det.name])+.1
return {"beam_peak" : evaluation}
or
\\ exists as a proof of concept to decouple Tiled as core data store and feasibly use another within a conv func
stream_store = OptimizationCache()
RE.subscribe(stream_store)
@direct_link(stream_store=stream_store)
def cost(measures):
evaluation = 5*np.exp(-.1*measures[det.name])+.1
return {"beam_peak" : evaluation}
//////////////////////////////
agent = Agent(
sensors=readables,
dofs=dofs,
objectives=objectives,
evaluation_function=cost.linked,
name="simple-experiment",
description="A simple experiment optimizing the beam peak intensity",
)
RE(agent.optimize(iterations=4,n_points=3))
Note:
The Eval-function-wrapper branch contains the current prototype. I'll be adding examples and comments over the next few days.
Its a novel and narrow use case, but TBH, this is more of a bet on future optimizations will likely focus more on "too high degree to optimize by hand" rather than "novel data processing, novel target results" when coming to beam-line optimizations. The core API still supports both, but this approach aims to make common/simple optimization workflows easier to learn and compose.
Premise
A subset of Bluesky RunEngine optimization streams should be well-structured within the event model (i.e. data lives directly in event documents) and acquisition plans (default_acquire). Because of this, we can provide reusable default implementations for evaluation-function data handling using common stream/data-store patterns. The goal is to providing utility to avoid "reinventing" the wheel every time they want to do a simple opt without taking on strict internal API guarantees around data handling.
I've been experimenting with decorators to separate data handling from explicit per sample data processing, also enabling code separation between:
For simple or tightly integrated systems, this could make fast-start optimization workflows much cleaner.
Example
Note:
The
Eval-function-wrapperbranch contains the current prototype. I'll be adding examples and comments over the next few days.Its a novel and narrow use case, but TBH, this is more of a bet on future optimizations will likely focus more on "too high degree to optimize by hand" rather than "novel data processing, novel target results" when coming to beam-line optimizations. The core API still supports both, but this approach aims to make common/simple optimization workflows easier to learn and compose.