diff --git a/lofar_station_client/device_proxy.py b/lofar_station_client/device_proxy.py new file mode 100644 index 0000000000000000000000000000000000000000..18ebb3e32ab36698fe0e31960d65d4e79d16333a --- /dev/null +++ b/lofar_station_client/device_proxy.py @@ -0,0 +1,40 @@ +import ast +from functools import lru_cache + +import numpy + +from tango import DeviceProxy +from tango import ExtractAs + + +class LofarDeviceProxy(DeviceProxy): + """A LOFAR-specific tango.DeviceProxy that provides + a richer experience.""" + + # cache attribute configurations, as they are not expected to change, + # but carry a cost to retrieve from the server. + @lru_cache() + def get_attribute_config(self, name): + return super().get_attribute_config(name) + + def read_attribute(self, name, extract_as=ExtractAs.Numpy): + attr = super().read_attribute(name, extract_as) + + # "format" property describes actual dimensions as a tuple (x, y, z, ...), + # so reshape the value accordingly. + fmt = self.get_attribute_config(name).format + if fmt and fmt[0] == "(" and isinstance(attr.value, numpy.ndarray): + shape = ast.literal_eval(fmt) + attr.value = attr.value.reshape(shape) + + return attr + + def write_attribute(self, name, value): + config = self.get_attribute_config(name) + + # 2D arrays also represent arrays of higher dimensionality. reshape them + # to fit their original Tango shape before writing. + if config.max_dim_y > 0: + attr.value = attr.value.reshape((config.max_dim_y, config.max_dim_x)) + + return super().write_attribute(name, value) diff --git a/requirements.txt b/requirements.txt index ef6adefd36e51eee51da83af1c324d3780fa9732..3043b88c0c118e78329cd6b654f46b4085cd7d17 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,3 +4,4 @@ numpy>=1.21.0 # BSD nptyping>=2.3.0 # MIT matplotlib>=3.5.0 # PSF pyDeprecate>=0.3.0 # MIT +tango # LGPLv3