bluesky / ophyd-async

Hardware abstraction for bluesky written using asyncio
https://blueskyproject.io/ophyd-async
BSD 3-Clause "New" or "Revised" License
12 stars 26 forks source link

PerSignalConfig dataclass for StandardReadable devices to be used with a common implementation of prepare. #543

Closed burkeds closed 1 month ago

burkeds commented 3 months ago

This is one way prepare can be used in a standard fashion across StandardReadables while preserving the benefits of type-hinting.

PerSignalConfig is a dict-like dataclass which will take device signals as a key and a value. This dataclass is then passed to prepare and the signals will be set accordingly. Type checkers should recognize if a value not matching the signal type is assigned.

Example usage:

class MyMotor(StandardReadable):
    velocity: SignalRW[float]
    accl: SignalRW[float]

    def __init__(self, name: str = ""):
        super().__init__(name=name)
        with self.add_children_as_readables(ConfigSignal):
            self.velocity = SignalRW(name="velocity",
                                     backend=SoftSignalBackend(datatype=float,
                                                               initial_value=0.0))
            self.accl = SignalRW(name="accl",
                                 backend=SoftSignalBackend(datatype=float,
                                                           initial_value=0.0))

async def main():
    async with DeviceCollector(mock=True):
        device = MyMotor()
    config = PerSignalConfig()
    config[device.velocity] = 1.0 # Pyright throws a type-error if this is a str or something
    config[device.accl] = 2.0
    await device.prepare(config)
    print(await device.velocity.read())
    print(await device.accl.read())
    print("Finished")

if __name__ == "__main__":
    asyncio.run(main())

# OUTPUT
{'device-velocity': {'value': 1.0, 'timestamp': 6675122.751791038, 'alarm_severity': 0}}
{'device-accl': {'value': 2.0, 'timestamp': 6675122.752000068, 'alarm_severity': 0}}
Finished
burkeds commented 2 months ago

@coretl Looks like there is a new linting error regarding an incompatible override of the epics motor with prepare. How do you think we should handle this?

coretl commented 2 months ago

@coretl Looks like there is a new linting error regarding an incompatible override of the epics motor with prepare. How do you think we should handle this?

Does making FlyMotorConfig inherit from PerSignalConfig fix the issue?

burkeds commented 1 month ago

@coretl Looks like there is a new linting error regarding an incompatible override of the epics motor with prepare. How do you think we should handle this?

Does making FlyMotorConfig inherit from PerSignalConfig fix the issue?

It does not because the attributes of FlyMotorConfig are not SignalW. For this approach to work, any variables required by prepare might need to be soft signals. What do you think?

coretl commented 1 month ago

After the collab call, are we still convinced we need this, or can it be replaced by load/save?

burkeds commented 1 month ago

After the collab call, are we still convinced we need this, or can it be replaced by load/save?

I think we can shelve this now. Config via load/save and abs_set seems fine.