First pass at allowing for cached devices to be used as args to enabl…#356
First pass at allowing for cached devices to be used as args to enabl…#356jwlodek wants to merge 3 commits intopcdshub:masterfrom
Conversation
…e ophyd-async support
tangkong
left a comment
There was a problem hiding this comment.
Left a couple of thoughts, on the whole I think this is an interesting idea. My main concern is the way this becomes dependent on the order in which we load devices, which I don't think happi makes any guarantees about.
I wonder if an alternate approach might be:
- attempt to load all devices
- collect any items that have args that can't be filled by metadata and defer their instantiation
- After the first pass, attempt to fill and load the previously deferred objects
- repeat until done or the deferred list doesn't change in size?
What I suggest is a bit more involved than what you've put forward here, but it might allow us to not have to call load_devices more than once
|
|
||
|
|
||
| class OphydAsyncItem(OphydItem): | ||
| ... |
There was a problem hiding this comment.
If this is being subclassed with no changes, is it really necessary at all?
There was a problem hiding this comment.
I agree with Robert. Perhaps it's more consistent and thorough to do a simple isinstance check on the created device for whether it's from ophyd-classic, ophyd-async, or neither, rather than trusting ourselves to use containers to mark them.
There was a problem hiding this comment.
My other thought was adding an optional additional metadata key to the ophyd item class called async_device that's a boolean. I'd prefer to be able to determine the device type prior to loading so I can treat them slightly differently. How does that sound as opposed to a seperate class?
There was a problem hiding this comment.
I think a simple boolean key is a reasonable approach, instructing the loader to try instantiate the object after a first pass is completed
While your primary use case is ophyd async, I might shy away from naming any of this with ophyd-async specific terminology. happi can be used to load any arbitrary python object, and that's a generality I wouldn't want to lose
| pprint=True, | ||
| include_load_time=True, | ||
| post_load=lambda device: RE(ensure_connected(device)), | ||
| namespace=init_ns, |
There was a problem hiding this comment.
When I first read this I thought that the intent was to have happi reference this init_ns when trying to fill devices, but this isn't the case. As written the reason this works is because of the execution order of the happi.loader.load_devices calls.
Just to be sure, was this your intent?
There was a problem hiding this comment.
My original idea was to pass around a reference to init_ns, but this got a bit messy, and functionally acted the same as just using the cache - in both cases it working would be order dependant, so I figured for this initial proof of concept just using the cache would be easier with fewer code changes.
| "name": "uuid_fp", | ||
| "type": "HappiItem" | ||
| }, | ||
| "ymd_path_provider": { |
There was a problem hiding this comment.
Small aside, I don't remember happi being able to generate json files where the top-level keys differ from the name field. Am I remembering wrong?
There was a problem hiding this comment.
To be honest these were mostly copy pasted and hand edited rather than generated via the client, so very likely this wouldn't be able to be generated in-code.
| attr_name = info.pop() | ||
|
|
||
| # If the templated variable is in the cache, use it directly. | ||
| if attr_name in cache: |
There was a problem hiding this comment.
I think the order-dependency of this is a bit antithetical to the other design elements in happi and puts some burden on the user.
I should be able to request manta_cam1 and happi should figure out that it also has to instantiate ymd_pp to pass in as an argument, for example (and then simply return manta_cam1 since I didn't ask for a direct reference to ymd_pp).
To this end, maybe there needs to be special syntax to more cleanly separate other-happi-device args from basic args. Then rather than always checking the cache for all attributes, happi parses the device marker and knows that it either needs to pull the cached device or make the requested device now.
This increases complexity a bit, particularly in how this interacts with post_load handlers. Maybe that's enough of a reason to defer it until later after more thought/discussion.
There was a problem hiding this comment.
I tend to agree. The order dependency is not super nice, it would be better if there could be a way for happi to automatically generate a load order as needed. As you say though this gets somewhat more complicated then - presumably we'd need a client available during loading so we could find the dependant devices?
There was a problem hiding this comment.
That's a good point, we'd need to be able to pass the client through the whole from_container/load_device chain, preferably optionally
|
I think this is a solid idea and I appreciate you starting with a simple and effective approach |
…e ophyd-async support
Description
OphydAsyncItemclass that allows for filtering for ophyd-async devices only since they require an additional step to establish a connection to the control system.Motivation and Context
How Has This Been Tested?
TODO: Unit tests, ensure existing test suite passes. Marking as draft for review & until I have a chance to complete these.
I did test with a real camera:
Where Has This Been Documented?
TODO
Pre-merge checklist
docs/pre-release-notes.shand created a pre-release documentation page