def _getDecodePyTangoAttr(self, attr_name, cfg): """Helper for decode the PyTango attribute infoex """ dev = PyTango.DeviceProxy(self.DEV_NAME) infoex = dev.get_attribute_config_ex(attr_name)[0] try: unit = UR.parse_units(infoex.unit) except (UndefinedUnitError, UnicodeDecodeError): unit = UR.parse_units(None) if cfg in ['range', 'alarms', 'warnings']: if cfg == 'range': low = infoex.min_value high = infoex.max_value elif cfg == 'alarms': low = infoex.alarms.min_alarm high = infoex.alarms.max_alarm elif cfg == 'warnings': low = infoex.alarms.min_warning high = infoex.alarms.max_warning if low == 'Not specified': low = '-inf' if high == 'Not specified': high = 'inf' return [Quantity(float(low), unit), Quantity(float(high), unit)] elif cfg == 'label': return infoex.label else: return None
def decode(self, attr_value): """ Decode the dataset to the corresponding python attribute :param attr_value: hdf5 dataset :return:taurus valid type """ # Transform hdf5 attribute to numpy array attr_value_np = np.array(attr_value) # TODO: extract scalars from hdf5 attribute # attr_value = attr_value_np[0] # get the attribute type hdfdtype = attr_value_np.dtype.kind self.type = self.hdfdtype2taurusdtype.get(hdfdtype) dimension = len(np.shape(attr_value_np)) if dimension == 0: self.data_format = DataFormat._0D elif dimension == 1: self.data_format = DataFormat._1D elif dimension == 2: self.data_format = DataFormat._2D if self.isNumeric(): # get units hdf5 attribute if it exist units = attr_value.attrs.get("units") # numeric attributes must be Quantities try: value = Quantity(attr_value_np, units=units) except UndefinedUnitError: value = Quantity(attr_value_np, units="dimensionless") elif self.type is DataType.String: value = attr_value_np.tolist() return value
def get_quantity(value, units=None, fmt=None): if value is None: return None res = Quantity(value, units=units) if fmt is not None: res.default_format = fmt + res.default_format return res
def __decode_limit(self, l, h): units = self.__pv.units if l is None or numpy.isnan(l): l = None else: l = Quantity(l, units) if l is None or numpy.isnan(h): h = None else: h = Quantity(h, units) return [l, h]
def _value2Quantity(value, units): ''' Creates a Quantity from value and forces units if the vaule is unitless :param value: (int, float or str) a number or a string from which a quantity can be created :param units: (str or Pint units) Units to use if the value is unitless :return: (Quantity) ''' q = Quantity(value) if q.unitless: q = Quantity(q, units) return q
def test1(): n = 'eval:@c=taurus.core.evaluation.test.res.mymod.MyClass(987)/c.foo' a = taurus.Attribute(n) print("READ 1: ", a.read()) # print a.range print("WRITE+READ", a.write(Quantity(999, "m"))) print("READ 2: ", a.read(cache=False))
def setTop(self, top): """ Set maximum limit :param top: (Quantity or None) maximum acceptable value or None if it is not to be enforced """ self._top = Quantity(top)
def setBottom(self, bottom): """ Set minimum limit :param bottom: (Quantity or None) minimum acceptable value or None if it is not to be enforced """ self._bottom = Quantity(bottom)
def _getSingleStepQuantity(self): """ :return: (Quantity) returns a single step with the units of the current value """ value = self.getValue() if value is None: return None return Quantity(self.getSingleStep(), value.units)
def getValue(self): text = self.text() model_obj = self.getModelObj() if model_obj is None: return None val = self.validator() try: model_type = model_obj.type model_format = model_obj.data_format if model_type in [DataType.Integer, DataType.Float]: try: # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # workaround for https://github.com/hgrecco/pint/issues/614 text = text.lstrip('0') or '0' # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ q = Quantity(text) # allow implicit units (assume wvalue.units implicitly) if q.unitless: q = Quantity(q.magnitude, val.units) return q except: return None elif model_type == DataType.Boolean: if model_format == DataFormat._0D: return bool(int(eval(text))) else: return numpy.array(eval(text), dtype=int).astype(bool) elif model_type == DataType.String: if model_format == DataFormat._0D: return str(text) else: return numpy.array(eval(text), dtype=str).tolist() elif model_type == DataType.Bytes: return bytes(text, self._bytesEncoding) else: raise TypeError('Unsupported model type "%s"' % model_type) except Exception as e: msg = 'Cannot return value for "%s". Reason: %r' if text in (str(None), self.getNoneValue()): self.debug(msg, text, e) else: self.warning(msg, text, e) return None
def _stepBy(self, steps): value = self.getValue() self.setValue(value + Quantity(steps * self._singleStep, value.units)) if self.getAutoApply(): self.editingFinished.emit() else: kmods = Qt.QCoreApplication.instance().keyboardModifiers() controlpressed = bool(kmods & Qt.Qt.ControlModifier) if controlpressed: self.writeValue(forceApply=True)
def getFreeSpace(self, dir): """ return free space (in bytes). (Recipe adapted from `http://stackoverflow.com/questions/51658`) """ if platform.system() == 'Windows': free_bytes = ctypes.c_ulonglong(0) ctypes.windll.kernel32.GetDiskFreeSpaceExW( ctypes.c_wchar_p(dir), None, None, ctypes.pointer(free_bytes)) ret = free_bytes.value else: s = os.statvfs(dir) ret = s.f_bsize * s.f_bavail return Quantity(ret, 'B')
def validate(self, input, pos): """Reimplemented from :class:`QValidator` to validate if the input string is a representation of a quantity within the set bottom and top limits """ try: q = Quantity(input) except: return Qt.QValidator.Intermediate, input, pos if self._implicit_units is not None: if q.unitless: # "cast" to implicit units q = Quantity(q.magnitude, self.units) # check coherence with implicit units elif self._implicit_units.dimensionality != q.dimensionality: return Qt.QValidator.Intermediate, input, pos try: if self.bottom is not None and q < self.bottom: return Qt.QValidator.Intermediate, input, pos if self.top is not None and q > self.top: return Qt.QValidator.Intermediate, input, pos except DimensionalityError: return Qt.QValidator.Intermediate, input, pos return Qt.QValidator.Acceptable, input, pos
def decode(self, pv): """Decodes an epics PV object into a TaurusValue, and also updates other properties of the Attribute object """ attr_value = TaurusAttrValue() if not pv.connected: attr_value.error = ChannelAccessException('PV "%s" not connected' % pv.pvname) return attr_value v = pv.value # type try: self.type = Dbr2TaurusType[pv.ftype] except KeyError: raise ValueError('Unsupported epics type "%s"' % pv.type) # writable self.writable = pv.write_access # data_format if numpy.isscalar(v): self.data_format = DataFormat._0D else: self.data_format = DataFormat(len(numpy.shape(v))) # units and limits support if self.type in (DataType.Integer, DataType.Float): v = Quantity(v, pv.units) self._range = self.__decode_limit(pv.lower_ctrl_limit, pv.upper_ctrl_limit) self._alarm = self.__decode_limit(pv.lower_alarm_limit, pv.upper_alarm_limit) self._warning = self.__decode_limit(pv.lower_warning_limit, pv.upper_warning_limit) # rvalue attr_value.rvalue = v # wvalue if pv.write_access: attr_value.wvalue = v # time if pv.timestamp is None: attr_value.time = TaurusTimeVal.now() else: attr_value.time = TaurusTimeVal.fromtimestamp(pv.timestamp) # quality if pv.severity > 0: attr_value.quality = AttrQuality.ATTR_ALARM else: attr_value.quality = AttrQuality.ATTR_VALID return attr_value
def __assertValidValue(self, exp, got, msg): # if we are dealing with quantities, use the magnitude for comparing if isinstance(got, Quantity): got = got.to(Quantity(exp).units).magnitude if isinstance(exp, Quantity): exp = exp.magnitude try: # for those values that can be handled by numpy.allclose() chk = numpy.allclose(got, exp) except: # for the rest if isinstance(got, numpy.ndarray): got = got.tolist() chk = bool(got == exp) self.assertTrue(chk, msg)
def _set_value(self, value): '''for backwards compat with taurus < 4''' debug('Setting %r to %s' % (value, self.name)) if self.rvalue is None: # we do not have a previous rvalue import numpy dtype = numpy.array(value).dtype if numpy.issubdtype(dtype, int) or numpy.issubdtype(dtype, float): msg = 'Refusing to set ambiguous value (deprecated .value API)' raise ValueError(msg) else: self.rvalue = value elif hasattr(self.rvalue, 'units'): # we do have it and is a Quantity self.rvalue = Quantity(value, units=self.rvalue.units) else: # we do have a previous value and is not a quantity self.rvalue = value
def __assertValidValue(self, exp, got, msg): # if we are dealing with quantities, use the magnitude for comparing if isinstance(got, Quantity): got = got.to(Quantity(exp).units).magnitude if isinstance(exp, Quantity): exp = exp.magnitude try: # first try the most generic equality chk = bool(got == exp) except: chk = False if not chk: # some cases may fail the simple equality but still be True try: # for those values that can be handled by numpy.allclose() chk = numpy.allclose(got, exp) except: if isinstance(got, numpy.ndarray): # uchars were not handled with allclose # UGLY!! but numpy.all does not work chk = got.tolist() == exp.tolist() self.assertTrue(chk, msg)
def applyTransformation(self): if self._transformation is None: return try: evaluator = self.getParentObj() rvalue = evaluator.eval(self._transformation) # --------------------------------------------------------- # Workaround for https://github.com/hgrecco/pint/issues/509 # The numpy.shape method over a Quantity mutates # the type of its magnitude. # TODO: remove "if" when the bug is solved in pint if hasattr(rvalue, "magnitude"): value_dimension = len(numpy.shape(rvalue.magnitude)) else: value_dimension = len(numpy.shape(rvalue)) # --------------------------------------------------------- value_dformat = DataFormat(value_dimension) self.data_format = value_dformat self.type = self._encodeType(rvalue, value_dformat) if self.type is None: raise TypeError("Unsupported returned type, %r" % rvalue) if self.type in [DataType.Integer, DataType.Float] and\ not isinstance(rvalue, Quantity): self.debug("Transformation converted to Quantity") rvalue = Quantity(rvalue) elif self.type == DataType.Boolean and value_dimension > 1: self.debug("Transformation converted to numpy.array") rvalue = numpy.array(rvalue) self._value.rvalue = rvalue self._value.time = TaurusTimeVal.now() self._value.quality = AttrQuality.ATTR_VALID except Exception as e: self._value.quality = AttrQuality.ATTR_INVALID msg = " the function '%s' could not be evaluated. Reason: %s" \ % (self._transformation, repr(e)) self.warning(msg)
def __init__(self, foomag=123): self._foo = Quantity(foomag, "m")
# __all__ = [] import numpy import unittest from taurus.core.units import Quantity import taurus from taurus.test import insertTest from taurus.core.taurusbasetypes import DataType, DataFormat, AttrQuality from taurus.core.evaluation.evalattribute import EvaluationAttrValue @insertTest(helper_name='read_attr', attr_fullname='eval:1', expected=dict( rvalue=Quantity(1, 'dimensionless'), type=DataType.Integer, label='1', writable=False, ), expected_attrv=dict(rvalue=Quantity([], 'dimensionless'), wvalue=None), expectedshape=None) @insertTest(helper_name='read_attr', attr_fullname='eval:Quantity("1m")+Quantity("2m")', expected=dict( rvalue=Quantity(3, 'm'), type=DataType.Integer, label='Quantity("1m")+Quantity("2m")', writable=False, ),
expected=dict(rvalue=8, value=8, wvalue=None, w_value=None, type=DataType.Integer)) @insertTest(helper_name='read_attr', name='eval:"split.split".split("split")', expected=dict(rvalue=['', '.', ''], value=['', '.', ''], wvalue=None, w_value=None, label='"split.split".split("split")', type=DataType.String)) @insertTest(helper_name='read_attr', name='eval:Quantity(1.0)', expected=dict(rvalue=Quantity(1.0), value=1.0, w_value=None, wvalue=None, label='Quantity(1.0)', type=DataType.Float, data_format=DataFormat._0D)) @insertTest(helper_name='read_attr', name='eval:Quantity("1km")', expected=dict(rvalue=Quantity(1000, 'm'), value=1, w_value=None, wvalue=None, label='Quantity("1km")', type=DataType.Integer, data_format=DataFormat._0D))
import os import sys import numpy import subprocess import unittest from taurus.core.units import Quantity import taurus from taurus.test import insertTest, getResourcePath from taurus.core.taurusbasetypes import DataType, AttrQuality, DataFormat from taurus.core.taurusbasetypes import TaurusAttrValue import pytest @insertTest(helper_name='write_read_attr', attrname='ca:test:a', setvalue=Quantity('1000mm'), expected=dict( rvalue=Quantity('1m'), type=DataType.Float, writable=True, data_format=DataFormat._0D, range=[Quantity('-10m'), Quantity('10m')], alarms=[None, None], warnings=[None, None], ), expected_attrv=dict( rvalue=Quantity('1m'), wvalue=Quantity('1m'), quality=AttrQuality.ATTR_VALID, error=None, ))
_FLOAT_SPE = _INT_SPE * .1 _BOOL_IMG = numpy.array([[True, False], [False, True]]) _BOOL_SPE = [True, False] _STR = 'foo BAR |-+#@!?_[]{}' _UINT8_IMG = numpy.array([[1, 2], [3, 4]], dtype='uint8') _UINT8_SPE = _UINT8_IMG[1, :] # ============================================================================== # Test writing fragment values @insertTest(helper_name='write_read_conf', attr_name='short_scalar_nu', cfg='range', value=[float('-inf'), float('inf')], expected=[Quantity(float('-inf')), Quantity(float('inf'))]) @insertTest(helper_name='write_read_conf', attr_name='short_scalar_nu', cfg='range', value=[Quantity(float('-inf')), Quantity(float('inf'))], expected=[Quantity(float('-inf')), Quantity(float('inf'))]) @insertTest(helper_name='write_read_conf', attr_name='short_scalar_nu', cfg='range', value=[100, 300], expected=[Quantity(100), Quantity(300)]) @insertTest(helper_name='write_read_conf', attr_name='short_scalar_nu',