Plans#

While the bluesky project uses plan in a general sense to refer to any Iterable of Msg’s which may be run by the RunEngine, blueapi distinguishes between a plan and a stub. This distinction is made to allow for a subset of stub’s to be exposed and run, as stub’s may not make sense to run alone.

Generally, a plan includes at least one open_run and close_run and is a complete description of an experiment. If it does not, it is a stub. This distinction is made in the bluesky core library between the plan’s and plan_stub’s modules.

Allowed Argument Types#

When added to the blueapi context, PlanGenerator’s are formalised into their schema - a Pydantic BaseModel with the expected argument types and their defaults.

Therefore, PlanGenerator’s must only take as arguments those types which are valid Pydantic fields or Device types which implement BLUESKY_PROTOCOLS defined in dodal, which are fetched from the context at runtime.

Allowed argument types for Pydantic BaseModels include the primitives, types that extend BaseModel and dict’s, list’s and other sequence’s of supported types. Blueapi will deserialise these types from JSON, so dict’s must use str keys.

Stubs#

Some functionality in your plans may make sense to factor out to allow re-use. These pieces of functionality may or may not make sense outside of the context of a plan. Some will, such as nudging a motor, but others may not, such as waiting to consume data from the previous position, or opening a run without an equivalent closure.

To enable blueapi to expose the stubs that it makes sense to, but not the others, blueapi will only expose a subset of MsgGenerator’s under the following conditions:

  • __init__.py in directory has __exports__: List[str]: only those named in __exports__

  • __init__.py in directory has __all__: List[str] but no __exports__: only those named in __all__

This allows other python packages (such as plans) to access every function in __all__, while only allowing a subset to be called from blueapi as standalone.

# Rehomes all of the beamline's devices. May require to be run standalone
from .package import rehome_devices
# Awaits a standard callback from analysis. Should not be run standalone
from .package import await_callback

# Exported from the module for use by other modules
__all__ = [
    "rehome_devices",
    "await_callback",
]

# Imported by instances of blueapi and allowed to be run
__exports__ = [
    "rehome_devices",
]