frappy_psi.lakeshore: improved calcurve handling
instead of keeping track a lookup for curve keys and of empty curves, loop over curve_cache. this is easier code and not a real performace problem
This commit is contained in:
+52
-39
@@ -129,13 +129,11 @@ class Device(HasLscIO, Module):
|
||||
log_formats = True, False # tuple (<log Ohm allowed>, <log K allowed>)
|
||||
max_curve_length = 200
|
||||
cmds_per_line = 5 # number of commands / replies allowed on one line
|
||||
_empty_curves = None
|
||||
_request_lock = None
|
||||
FAST_POLL = 0.01
|
||||
|
||||
def initModule(self):
|
||||
self._empty_curves = {} # dict <curve no> of None (used as ordered set)
|
||||
self._curve_map = {} # dict CurveHeader.key of curve_no
|
||||
self._to_delete = [] # curves to delete
|
||||
self._requests = {} # dict <calcurve> of CurveRequest
|
||||
self._sensors = {} # dict <channel> of sensors
|
||||
self._disable_channels = set(self.channels)
|
||||
@@ -188,12 +186,6 @@ class Device(HasLscIO, Module):
|
||||
for curve_no in range(*self.user_curves):
|
||||
crvhdr = CurveHeader(*headers[curve_no].split(','))
|
||||
self.curve_cache[curve_no] = crvhdr
|
||||
if crvhdr.key:
|
||||
if crvhdr in self._curve_map:
|
||||
# this is a duplicate, add to empty curves
|
||||
self._empty_curves[curve_no] = None
|
||||
else:
|
||||
self._curve_map[crvhdr.key] = curve_no
|
||||
try:
|
||||
check_item = None
|
||||
with self._request_lock:
|
||||
@@ -219,6 +211,10 @@ class Device(HasLscIO, Module):
|
||||
sensor = self._sensors.get(ch)
|
||||
if sensor is None or sensor.disabled:
|
||||
self.disable_channel(ch)
|
||||
if self._to_delete:
|
||||
no = self._to_delete.pop(0)
|
||||
if self.curve_cache[no].key is None:
|
||||
self.command(f'CRVDEL {no}')
|
||||
except Exception as e:
|
||||
request.loading = False
|
||||
request.status = ERROR, repr(e)
|
||||
@@ -237,25 +233,23 @@ class Device(HasLscIO, Module):
|
||||
|
||||
def get_empty(self):
|
||||
"""get curve no of a curve to be reused"""
|
||||
if self._empty_curves:
|
||||
# we have unused curve slots
|
||||
curve_no = next(iter(self._empty_curves))
|
||||
self._empty_curves.pop(curve_no)
|
||||
for curve_no in range(*self.user_curves):
|
||||
if not self.curve_cache[curve_no].key:
|
||||
return curve_no
|
||||
used_no = set(s.curve_no for s in self._sensors.values())
|
||||
for req in self._requests.values():
|
||||
used_no.add(req.invalidate)
|
||||
n0, n = self.user_curves
|
||||
n -= n0
|
||||
# instead of taking the lowest available number, start at a
|
||||
# random index, else most recent curves would be overridden
|
||||
offset = random.randrange(n)
|
||||
for i in range(n):
|
||||
curve_no = n0 + (i + offset) % n
|
||||
if curve_no not in used_no:
|
||||
break
|
||||
else:
|
||||
used_no = set(s.curve_no for s in self._sensors.values())
|
||||
for req in self._requests.values():
|
||||
used_no.add(req.invalidate)
|
||||
n0, n = self.user_curves
|
||||
n -= n0
|
||||
# avoid to take the lower numbers first
|
||||
# as then the most recent curves would be overridden
|
||||
offset = random.randrange(n)
|
||||
for i in range(n):
|
||||
curve_no = n0 + (i + offset) % n
|
||||
if curve_no not in used_no:
|
||||
break
|
||||
else:
|
||||
raise ValueError('no empty curves available')
|
||||
raise ValueError('no empty curves available')
|
||||
return curve_no
|
||||
|
||||
def get_calib_state(self, sensor):
|
||||
@@ -269,7 +263,7 @@ class Device(HasLscIO, Module):
|
||||
return ImpossibleError('error while loading calibration curve')
|
||||
return None
|
||||
|
||||
def verify_ends(self, request):
|
||||
def verify_ends(self, request, no):
|
||||
"""preliminary check: check if the ends of the curve are matching the stored ones"""
|
||||
npnt = len(request.points)
|
||||
numbers = [1, npnt]
|
||||
@@ -277,8 +271,12 @@ class Device(HasLscIO, Module):
|
||||
if npnt < self.max_curve_length:
|
||||
numbers.append(npnt + 1)
|
||||
points.append((0, 0))
|
||||
for pairs in zip(points, self.get_crvpts(request.curve_no, *numbers)):
|
||||
stored_points = self.get_crvpts(no, *numbers)
|
||||
for pairs in zip(points, stored_points):
|
||||
if not self.is_equal(*pairs):
|
||||
self.log.info('not equal %r', pairs)
|
||||
self.log.info('requested points %r', points)
|
||||
self.log.info('stored points %r', stored_points)
|
||||
return False
|
||||
return True
|
||||
|
||||
@@ -288,11 +286,25 @@ class Device(HasLscIO, Module):
|
||||
:param request: the curve request
|
||||
:return: next action
|
||||
"""
|
||||
no = self._curve_map.get(request.crvhdr.key)
|
||||
if no:
|
||||
key = request.crvhdr.key
|
||||
duplicates = []
|
||||
for no, crvhdr in self.curve_cache.items():
|
||||
if key == crvhdr.key:
|
||||
if self.verify_ends(request, no):
|
||||
ends_ok = True
|
||||
for delno in duplicates:
|
||||
self.curve_cache[delno] = CurveHeader()
|
||||
self._to_delete.append(delno)
|
||||
break
|
||||
else:
|
||||
duplicates.append(no)
|
||||
else:
|
||||
no = None
|
||||
ends_ok = False
|
||||
if no is not None:
|
||||
request.crvhdr = self.curve_cache[no]
|
||||
request.set_curve_no(no)
|
||||
if self.verify_ends(request):
|
||||
if ends_ok:
|
||||
self.log.info('calcurve #%d %s found, start to check consistency', no, request.crvhdr)
|
||||
# guess the curve is o.k. -> install
|
||||
request.install_sensors(request.sensors.values())
|
||||
@@ -305,8 +317,8 @@ class Device(HasLscIO, Module):
|
||||
request.invalidate = no
|
||||
request.set_curve_no(self.get_empty())
|
||||
request.install_sensors(request.sensors.values())
|
||||
self.log.info('%s found, but content has changed, create #%d',
|
||||
request.crvhdr.sn, request.curve_no)
|
||||
self.log.info('%s found as #%d, but content has changed, create #%d',
|
||||
request.crvhdr.sn, no, request.curve_no)
|
||||
return self.start_load
|
||||
request.set_curve_no(self.get_empty())
|
||||
for sensor in request.sensors.values():
|
||||
@@ -390,7 +402,6 @@ class Device(HasLscIO, Module):
|
||||
:return: next action
|
||||
"""
|
||||
self.curve_cache[request.curve_no] = CurveHeader(*request.crvhdr)
|
||||
self._curve_map[request.crvhdr.key] = request.curve_no
|
||||
self.put_header(request.curve_no, *request.crvhdr)
|
||||
request.install_sensors(request.sensors.values())
|
||||
no = request.invalidate
|
||||
@@ -399,7 +410,7 @@ class Device(HasLscIO, Module):
|
||||
self.log.info('calcurve #%d %s %s, clear previous #%d',
|
||||
request.curve_no, request.crvhdr, comment, no)
|
||||
self.curve_cache[no] = CurveHeader()
|
||||
self._empty_curves[no] = None
|
||||
self._to_delete.append(no)
|
||||
else:
|
||||
self.log.info('calcurve #%d %s %s',
|
||||
request.curve_no, request.crvhdr, comment)
|
||||
@@ -440,7 +451,7 @@ class Device(HasLscIO, Module):
|
||||
"""get all headers
|
||||
|
||||
for performance reasons, by default 5 headers are read in one line
|
||||
this is speeing up quite a lot on serial connections
|
||||
this speeds up quite a lot on serial connections
|
||||
"""
|
||||
n0, n1 = self.user_curves
|
||||
result = {}
|
||||
@@ -465,7 +476,7 @@ class CurveRequest:
|
||||
self.sensors = {sensor.channel: sensor}
|
||||
calcurve = CalCurve(sensor.calcurve)
|
||||
equipment_id = device.propertyValues.get('original_id') or device.secNode.equipment_id
|
||||
name = f"{equipment_id.split('.')[0]}.{sensor.name}"
|
||||
self.name = f"{equipment_id.split('.')[0]}.{sensor.name}"
|
||||
sn = calcurve.calibname
|
||||
limit = calcurve.calibrange[1]
|
||||
unit = calcurve.options.get('unit', 'Ohm')
|
||||
@@ -495,9 +506,11 @@ class CurveRequest:
|
||||
else:
|
||||
fmt = 2 if unit == 'V' else 1
|
||||
coef = 1 + (self.points[0][1] < self.points[-1][1]) # 1: ntc, 2: ptc
|
||||
self.crvhdr = CurveHeader(name, sn, fmt, limit, coef)
|
||||
self.crvhdr = CurveHeader(self.name, sn, fmt, limit, coef)
|
||||
|
||||
def set_curve_no(self, curve_no):
|
||||
if self.name != self.crvhdr.name:
|
||||
self.crvhdr = CurveHeader(self.name, *self.crvhdr[1:])
|
||||
self.curve_no = curve_no
|
||||
for s in self.sensors.values():
|
||||
s.curve_no = curve_no
|
||||
|
||||
Reference in New Issue
Block a user