Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 13 additions & 11 deletions src/fastcs/transports/epics/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
from fastcs.attributes import Attribute, AttrR, AttrRW, AttrW
from fastcs.datatypes import (
Bool,
DataType,
Enum,
Float,
Int,
Expand Down Expand Up @@ -57,8 +56,8 @@ def _get_pv(self, attr_path: list[str], name: str):
)
return f"{attr_prefix}:{snake_to_pascal(name)}"

def _get_read_widget(self, fastcs_datatype: DataType) -> ReadWidgetUnion | None:
match fastcs_datatype:
def _get_read_widget(self, attribute: Attribute) -> ReadWidgetUnion | None:
match attribute.datatype:
case Bool():
return LED()
case Int():
Expand All @@ -71,15 +70,18 @@ def _get_read_widget(self, fastcs_datatype: DataType) -> ReadWidgetUnion | None:
return TextRead(format=TextFormat.string)
case Waveform() as waveform:
if len(waveform.shape) > 1:
logger.warning("EPICS CA transport only supports 1D waveforms")
logger.warning(
"EPICS CA transport only supports 1D waveforms, "
f"{attribute} is a {len(waveform.shape)}D waveform"
)
return None

return ArrayTrace(axis="x")
case datatype:
raise TypeError(f"Unsupported type {type(datatype)}: {datatype}")

def _get_write_widget(self, fastcs_datatype: DataType) -> WriteWidgetUnion | None:
match fastcs_datatype:
def _get_write_widget(self, attribute: Attribute) -> WriteWidgetUnion | None:
match attribute.datatype:
case Bool():
return ToggleButton()
case Int():
Expand All @@ -89,7 +91,7 @@ def _get_write_widget(self, fastcs_datatype: DataType) -> WriteWidgetUnion | Non
case String():
return TextWrite(format=TextFormat.string)
case Enum():
return ComboBox(choices=fastcs_datatype.names)
return ComboBox(choices=attribute.datatype.names)
case Waveform():
return None
case datatype:
Expand All @@ -102,8 +104,8 @@ def _get_attribute_component(
name = snake_to_pascal(name)
match attribute:
case AttrRW():
read_widget = self._get_read_widget(attribute.datatype)
write_widget = self._get_write_widget(attribute.datatype)
read_widget = self._get_read_widget(attribute)
write_widget = self._get_write_widget(attribute)
if write_widget is None or read_widget is None:
return None
return SignalRW(
Expand All @@ -115,7 +117,7 @@ def _get_attribute_component(
read_widget=read_widget,
)
case AttrR():
read_widget = self._get_read_widget(attribute.datatype)
read_widget = self._get_read_widget(attribute)
if read_widget is None:
return None
return SignalR(
Expand All @@ -125,7 +127,7 @@ def _get_attribute_component(
read_widget=read_widget,
)
case AttrW():
write_widget = self._get_write_widget(attribute.datatype)
write_widget = self._get_write_widget(attribute)
if write_widget is None:
return None
return SignalW(
Expand Down
24 changes: 13 additions & 11 deletions src/fastcs/transports/epics/pva/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
WriteWidgetUnion,
)

from fastcs.datatypes import Bool, DataType, Table, Waveform, numpy_to_fastcs_datatype
from fastcs.attributes import Attribute, AttrR, AttrW
from fastcs.datatypes import Bool, Table, Waveform, numpy_to_fastcs_datatype
from fastcs.transports.epics.gui import EpicsGUI


Expand All @@ -20,17 +21,18 @@ class PvaEpicsGUI(EpicsGUI):
def _get_pv(self, attr_path: list[str], name: str):
return f"pva://{super()._get_pv(attr_path, name)}"

def _get_read_widget(self, fastcs_datatype: DataType) -> ReadWidgetUnion | None:
match fastcs_datatype:
def _get_read_widget(self, attribute: Attribute) -> ReadWidgetUnion | None:
match attribute.datatype:
case Table():
fastcs_datatypes = [
numpy_to_fastcs_datatype(datatype)
for _, datatype in fastcs_datatype.structured_dtype
for _, datatype in attribute.datatype.structured_dtype
]

base_get_read_widget = super()._get_read_widget
widgets = [
base_get_read_widget(datatype) for datatype in fastcs_datatypes
base_get_read_widget(AttrR(datatype))
for datatype in fastcs_datatypes
]

return TableRead(widgets=widgets) # type: ignore
Expand All @@ -39,20 +41,20 @@ def _get_read_widget(self, fastcs_datatype: DataType) -> ReadWidgetUnion | None:
height=height, width=width, color_map=ImageColorMap.GRAY
)
case _:
return super()._get_read_widget(fastcs_datatype)
return super()._get_read_widget(attribute)

def _get_write_widget(self, fastcs_datatype: DataType) -> WriteWidgetUnion | None:
match fastcs_datatype:
def _get_write_widget(self, attribute: Attribute) -> WriteWidgetUnion | None:
match attribute.datatype:
case Table():
widgets = []
for _, datatype in fastcs_datatype.structured_dtype:
for _, datatype in attribute.datatype.structured_dtype:
fastcs_datatype = numpy_to_fastcs_datatype(datatype)
if isinstance(fastcs_datatype, Bool):
# Replace with compact version for Table row
widget = CheckBox()
else:
widget = super()._get_write_widget(fastcs_datatype)
widget = super()._get_write_widget(AttrW(fastcs_datatype))
widgets.append(widget)
return TableWrite(widgets=widgets)
case _:
return super()._get_write_widget(fastcs_datatype)
return super()._get_write_widget(attribute)
4 changes: 3 additions & 1 deletion tests/transports/epics/ca/test_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,9 @@ def test_get_attribute_component_none(mocker):

def test_get_write_widget_none():
gui = EpicsGUI(ControllerAPI(), "DEVICE")
assert gui._get_write_widget(fastcs_datatype=Waveform(np.int32)) is None
assert (
gui._get_write_widget(attribute=AttrR(Waveform(array_dtype=np.int32))) is None
)


def test_get_components(controller_api):
Expand Down