-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discussion: Architecture for inject #874
Comments
My personal preference is 3. I think it is more readable as "this is just a blueAPI thing I can ignore generally" and it is beamline independent. |
I prefer 1; or some version of it that linting is happy with e.g. eiger = ixx.eiger()
def initialise_detector(det:Eiger = eiger):
... With ophyd-async calling connect only when required, the only [required] side effect is creating light weight Signals without backends. Any device that needs to e.g. read from the filesystem should do that on first connect. I'd much rather have 3 or 4 than 2 or 5. RE: 5 I really really want to avoid re-inventing the Finder: once we re-introduce the idea that you can get anything anywhere in your plan, the signature of every plan is degenerate, and it's a race to the bottom of not knowing what was available/required at the start of your plan and not able to pass any overrides so you simultaneously have N plans for the same scan with each of N devices, and none of them have the device as an argument... RE: 3 it would give us a hook to ensure the device is connected too, at the start of the scan. But it also means there is an inconsistency between running the scan with blueapi and from a terminal. |
I still think doing this on import is bad:
|
From discussion with @DominicOram and @DiamondJoseph: There is some disagreement over just how terrible a thing having tens of defaulted arguments for complex plans would be. It's messy, but explicit e.g. def my_plan(x: Motor = inject(ixx.x), y: Motor = inject(ixx.y), z: Motor = inject(ixx.z), ...) -> MsgGenerator:
... @DiamondJoseph and I had previously envisioned The current, boilerplate-heavy solution would be: def plan_for_beamline_1(eiger: Eiger = inject(beamline_1.eiger)) -> MsgGenerator:
yield from base_plan(eiger=eiger)
def plan_for_beamline_2(eiger: Eiger = inject(beamline_2.eiger)) -> MsgGenerator:
yield from base_plan(eiger=eiger)
def base_plan(eiger: Eiger) -> MsgGenerator:
... We discussed using composites to satisfy this e.g. class ExperimentalComposite(BaseModel):
x: Motor = inject(ixx.x)
y: Motor = inject(ixx.y)
eiger: Eiger = inject(ixx.eiger)
def my_plan(composite: ExperimentalComposite), z: Motor = inject(ixx.z)-> MsgGernerator:
... |
|
We are favouring 3. because:
We could have something like this, where we have a shared set of constants for device names... # Devices
@device_factory()
def eiger() -> Eiger:
return Eiger(name=MY_EXPERIMENT_DEFINITION.main_detector)
# Plan
@export(inject={"eiger": MY_EXPERIMENT_DEFINITION.main_detector}) # This should shout at you if there is no parameter called "eiger" on import
def my_plan(eiger: Eiger) -> MsgGenerator:
... |
Thinking about how a composite device would work: class ExperimentalComposite(BaseModel):
x: Motor
y: Motor
eiger: Eiger
@export(inject={"composite": {"x": "x", "y": "y", "eiger": "eiger"}})
def my_plan(composite: ExperimentalComposite))-> MsgGenerator:
... ...can we think of a nicer way? Do we want something like this? Composite is defined as a device. @export(inject={"x": "x", "y": "y", "eiger": "eiger"})
class ExperimentalComposite(BaseModel):
x: Motor
y: Motor
eiger: Eiger
@export()
def my_plan(composite: ExperimentalComposite)) -> MsgGenerator:
... |
As a user of BlueAPI I would like to not have to specify my devices everytime I call a particular plan e.g.
Should be able to be called from
BlueAPI
with no arguments specified asBlueAPI
should already have all the devices and be able to use its existingEiger
.There are a number of ways we could do this:
As discussed on #854 this has the issue that it does work on import.
This had the issue that it was hard to fix in pydantic 2.
Acceptance Criteria
The text was updated successfully, but these errors were encountered: