Skip to content

Names for signals in DeviceVector should be allowed to override for read #1281

Description

@oliwenmandiamond

I am porting some logic from GDA. It is a device that can be configured with channels and then give those channels names when being read.

class MyDevice(StandardReadable):
    def __init__(self, prefix: str, name: str = ""):
        with self.add_children_as_readables():
            self.hm3amp20 = epics_signal_r(float, prefix + f".S{2}")
            self.sm5amp8 = epics_signal_r(float, prefix + f".S{3}")
            self.smpmamp39 = epics_signal_r(float, prefix + f".S{4}")
            self.rfdamp10 = epics_signal_r(float, prefix + f".S{5}")
        super().__init__(name)

So this translated to the above, however this has hardcoded the channels. I wanted to use the device vector for this instead and have it be configurable:

class MyDevice(StandardReadable):
    def __init__(self, prefix: str, config: dict[int, str], name: str = ""):
        with self.add_children_as_readables():
            self.channels = DeviceVector(
                {
                    key: epics_signal_r(float, prefix + f".S{key}", name=value)
                    for key, value in config.items()
                }
            )
        super().__init__(name)
@pytest.fixture
def my_device() -> MyDevice:
    with init_devices(mock=True):
        my_device = MyDevice(
            "TEST:", {2: "hm3amp20", 3: "sm5amp8", 4: "smpmamp39", 5: "rfdamp10"}
        )
    return my_device

However, the read outputs is this:

        {
            "my_device-channels-2": partial_reading(0),
            "my_device-channels-3": partial_reading(0),
            "my_device-channels-4": partial_reading(0),
            "my_device-channels-5": partial_reading(0),
        }

rather than

        {
            "my_device-channels-hm3amp20": partial_reading(0),
            "my_device-channels-sm5amp8": partial_reading(0),
            "my_device-channels-smpmamp39": partial_reading(0),
            "my_device-channels-rfdamp10": partial_reading(0),
        },

So the name that I provided to the signal was ignored and overwritten by key value int instead. I think we should be able to customise the signals name so that the read outputs the desired users format. We can do this very easily by adding this small change to DeviceVector

from this

    def children(self) -> Iterator[tuple[str, Device]]:
        for key, child in self._children.items():
            yield str(key), child
        yield from super().children()

to this

    def children(self) -> Iterator[tuple[str, Device]]:
        for key, child in self._children.items():
            name = str(key) if child.name == "" else child.name
            yield name, child
        yield from super().children()

This way, we can still access the signals via my_device.channels[x] but the read is the desired output.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions