frappy_psi.softcal: add function evaluator

This commit is contained in:
2025-11-12 17:24:47 +01:00
parent a8b8fa1cc4
commit af28f33018

View File

@@ -30,6 +30,8 @@ from frappy.core import Attached, BoolType, Parameter, Readable, StringType, \
FloatRange, nopoll
from frappy_psi.convergence import HasConvergence
from frappy_psi.picontrol import PImixin
from frappy.lib.mathparser import MathParser
from frappy.errors import RangeError
def linear(x):
@@ -238,3 +240,60 @@ class Sensor(Readable):
class SoftPiLoop(HasConvergence, PImixin, Sensor):
pass
class Function(Readable):
rawsensor = Attached()
formula = Parameter('calib function', StringType(), readonly=False)
value = Parameter('physical quantity', FloatRange())
_parser = MathParser(x=0)
_value_error = None
def initModule(self):
super().initModule()
self.rawsensor.registerCallbacks(self, ['status']) # auto update status
if self.description == '':
self.description = f'{self.rawsensor!r} with applied function'
def _get_status(self, rawstatus):
return rawstatus if self._value_error is None else (self.Status.ERROR, self._value_error)
def update_value(self, rawvalue, err=None):
if err:
err = repr(err)
else:
try:
self.value = self._get_value(rawvalue)
except Exception as e:
err = repr(e)
if err != self._value_error:
self._value_error = err
self.status = self._get_status(self.rawsensor.status)
def update_status(self, rawstatus):
self.status = self._get_status(rawstatus)
def write_formula(self, formula):
self._parser = MathParser(x=0)
self.formula = formula
self.read_value()
self._value_error = None
self.read_status()
def _get_value(self, rawvalue):
try:
return self._parser.calculate(self.formula, x=rawvalue)
except Exception as e:
self._value_error = f'error in formula {self.formula!r}: {e!r}'
self.read_status()
raise RangeError(self._value_error) from None
@nopoll
def read_value(self):
return self._get_value(self.rawsensor.read_value())
@nopoll
def read_status(self):
return self._get_status(self.rawsensor.read_status())