-
Notifications
You must be signed in to change notification settings - Fork 76
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
v2: DeviceCollector does not connect variables that existed before being entered. #1100
Comments
@tacaswell @danielballan @prjemian @mrakitin any thoughts on this? |
I like the notion of an instrument registry that is being developed by @canismarko for our spectroscopy beam lines. |
As @prjemian mentioned, we developed an InstrumentRegistry class for Haven inspired by Pint's ureg. https://haven-spc.readthedocs.io/en/latest/topic_guides/instrument_registry.html A default registry object is created at import time and can be used either directly on Device objects:
or as a class decorator, where the device is registered regardless of the context it's created in:
I use the decorator form more since most of my devices are subclasses of You could in theory use multiple registries, but I haven't had a need for that yet. It currently checks for duplicates by name similar to this DeviceCollector, but that could change easily. |
There are 2 problems that
The first of these exists in both ophyd.v1 and v2, the second is only in v2 as it can do a concurrent connection of many devices at once. I think the registry could be made to solve the first (if you declare How do you solve 1 at present? |
I would not trust stashing the I'm very very skeptical of a global devices registry at the ophyd library level. I think "you must keep track of your devices" is way simpler to explain (and enables facility and beamline specific registries if people want them) rather than "we keep a global registry that is almost certainly not what you wanted but is close so please spend an inordinate amount of effort engineering around un-needed global state". I acknowledge my presentation of the alternatives is biased.
I think this is getting too far away from Python syntax |
Excellent, let's do that: def __enter__(self):
# Stash the names that were defined before we were called
self._objects_on_enter = self._caller_locals()
return self
...
async def _on_exit(self):
# Name and kick off connect for devices
tasks: Dict[asyncio.Task, str] = {}
for name, obj in self._objects_on_exit.items():
is_new = name not in self._objects_on_enter or obj is not self._objects_on_enter[name]
if is_new and isinstance(obj, Device):
...
if self._connect:
task = asyncio.create_task(obj.connect(self._prefix, self._sim))
tasks[task] = name
... @RAYemelyanova please can you make the changes with associated tests? |
Agreed, let's make |
In general, it seems a good idea for the DeviceCollector to be able to do something like this:
But at the moment, the DeviceCollector simply checks on the existing objects before it's been entered, and compares them to the objects on exit by name. This means any replaced objects, such as in the example above, won't be connected. In the above, trying to get and put to motor1 will get an object that has not had
connect
run, as the enter/exit definitions of DeviceCollector will not have recognizedmotor1
as a new device which needs connecting.There is a fairly straightforward way of getting around this, that @coretl has mentioned to me. At the moment, the device collector checks for objects by name on exit:
Instead, we can check for the id of the objects, and compare that as opposed to the name. This will allow re-defining motors and other ophyd v2 devices in device collectors, and will mean they get connected/named as expected. This would look like so:
What do people think of this? Is this what users would expect DeviceCollector to do?
The text was updated successfully, but these errors were encountered: