add HasOffset feature

+ remove all other unused features

Change-Id: Idff48bdabf51e7fa23547eac761f11320c41861c
This commit is contained in:
2023-05-05 13:23:14 +02:00
parent 3b95013b69
commit 6b78e69dbe

View File

@ -22,115 +22,14 @@
"""Define Mixin Features for real Modules implemented in the server""" """Define Mixin Features for real Modules implemented in the server"""
from frappy.datatypes import FloatRange, TupleOf from frappy.datatypes import FloatRange
from frappy.core import Drivable, Feature, \ from frappy.core import Feature, PersistentParam
Parameter, PersistentParam, Readable
from frappy.errors import RangeError, ConfigError
from frappy.lib import clamp
class HasSimpleOffset(Feature): class HasOffset(Feature):
"""has a client side offset parameter """has a client side offset parameter
this is just a storage! this is just a storage!
""" """
featureName = 'HasOffset'
offset = PersistentParam('offset (physical value + offset = HW value)', offset = PersistentParam('offset (physical value + offset = HW value)',
FloatRange(unit='deg'), readonly=False, default=0) FloatRange(unit='$'), readonly=False, default=0)
def write_offset(self, value):
self.offset = value
if isinstance(self, HasLimits):
self.read_limits()
if isinstance(self, Readable):
self.read_value()
if isinstance(self, Drivable):
self.read_target()
self.saveParameters()
return value
class HasTargetLimits(Feature):
"""user limits
implementation to be done in the subclass
according to standard
"""
target_limits = PersistentParam('user limits', readonly=False, default=(-9e99, 9e99),
datatype=TupleOf(FloatRange(unit='deg'), FloatRange(unit='deg')))
_limits = None
def apply_offset(self, sign, *values):
if isinstance(self, HasOffset):
return tuple(v + sign * self.offset for v in values)
return values
def earlyInit(self):
super().earlyInit()
# make limits valid
_limits = self.apply_offset(1, *self.limits)
self._limits = tuple(clamp(self.abslimits[0], v, self.abslimits[1]) for v in _limits)
self.read_limits()
def checkProperties(self):
pname = 'target' if isinstance(self, Drivable) else 'value'
dt = self.parameters[pname].datatype
min_, max_ = self.abslimits
t_min, t_max = self.apply_offset(1, dt.min, dt.max)
if t_min > max_ or t_max < min_:
raise ConfigError(f'abslimits not within {pname} range')
self.abslimits = clamp(t_min, min_, t_max), clamp(t_min, max_, t_max)
super().checkProperties()
def read_limits(self):
return self.apply_offset(-1, *self._limits)
def write_limits(self, value):
min_, max_ = self.apply_offset(-1, *self.abslimits)
if not min_ <= value[0] <= value[1] <= max_:
if value[0] > value[1]:
raise RangeError(f'invalid interval: {value!r}')
raise RangeError(f'limits not within abs limits [{min_:g}, {max_:g}]')
self.limits = value
self.saveParameters()
return self.limits
def check_limits(self, value):
"""check if value is valid"""
min_, max_ = self.target_limits
if not min_ <= value <= max_:
raise RangeError(f'limits violation: {value:g} outside [{min_:g}, {max_:g}]')
# --- legacy mixins, not agreed as standard ---
class HasOffset(Feature):
"""has an offset parameter
implementation to be done in the subclass
"""
offset = Parameter('offset (physical value + offset = HW value)',
FloatRange(unit='$'), readonly=False, default=0)
class HasLimits(Feature):
"""user limits
implementation to be done in the subclass
for a drivable, abslimits is roughly the same as the target datatype limits,
except for the offset
"""
target_limits = Parameter('user limits for target', readonly=False, default=(-9e99, 9e99),
datatype=TupleOf(FloatRange(unit='$'), FloatRange(unit='$')))
def earlyInit(self):
super().earlyInit()
dt = self.parameters['target'].datatype
self.target_limits = dt.min, dt.max
def check_limits(self, value):
"""check if value is valid"""
min_, max_ = self.target_limits
if not min_ <= value <= max_:
raise RangeError('limits violation: %g outside [%g, %g]' % (value, min_, max_))