Source code for dodal.devices.selectable_source
from typing import TypeVar
from ophyd_async.core import (
NotConnectedError,
SignalR,
SignalRW,
StandardReadable,
StandardReadableFormat,
StrictEnum,
derived_signal_r,
soft_signal_r_and_setter,
)
[docs]
class SelectedSource(StrictEnum):
SOURCE1 = "source1"
SOURCE2 = "source2"
T = TypeVar("T")
[docs]
def get_obj_from_selected_source(selected_source: SelectedSource, s1: T, s2: T) -> T:
"""Util function that maps enum values for SelectedSource to two objects. It then
returns one of the objects that corrosponds to the selected_source value.
"""
match selected_source:
case SelectedSource.SOURCE1:
return s1
case SelectedSource.SOURCE2:
return s2
[docs]
class DualEnergySource(StandardReadable):
"""Provides a signal to read energy depending on
which source is selected. The energy is the one that corrosponds to the
selected_source signal. For example, selected_source is source1 if selected_source
is at SelectedSource.SOURCE1 and vise versa for source2 and
SelectedSource.SOURCE2.
Args:
source1 (SignalRW): Energy source that corrosponds to SelectedSource.SOURCE1.
source2 (SignalRW): Energy source that corrosponds to SelectedSource.SOURCE2.
selected_source (SignalRW): Signal that decides the active energy source.
name (str, optional): Name of this device.
"""
def __init__(
self,
source1: SignalR[float],
source2: SignalR[float],
selected_source: SignalRW[SelectedSource],
name: str = "",
):
with self.add_children_as_readables(StandardReadableFormat.HINTED_SIGNAL):
self.energy = derived_signal_r(
self._energy_from_selected_source,
"eV",
selected_source=selected_source,
s1=source1,
s2=source2,
)
self._validate_config_signal([source1, source2])
with self.add_children_as_readables(StandardReadableFormat.CONFIG_SIGNAL):
self.source1_name, _ = soft_signal_r_and_setter(
str, initial_value=source1.name
)
self.source2_name, _ = soft_signal_r_and_setter(
str, initial_value=source2.name
)
self.add_readables([selected_source, source1, source2])
super().__init__(name)
def _energy_from_selected_source(
self, selected_source: SelectedSource, s1: float, s2: float
) -> float:
return get_obj_from_selected_source(selected_source, s1, s2)
def _validate_config_signal(self, signals: list[SignalR]) -> None:
for signal in signals:
if signal.name == "":
raise NotConnectedError(
'Signal cannot have name "". Make sure the signal has been '
f"connected and named before passing to class {self.__class__.__name__}"
)