From 2ec6706f882d08e9b188f60c2252bf0f3a2bb5b1 Mon Sep 17 00:00:00 2001
From: Marko Mecina <marko.mecina@univie.ac.at>
Date: Tue, 19 Dec 2023 18:14:32 +0100
Subject: [PATCH] use custom calibrations if defined in calibrations_*.py

---
 Ccs/calibrations_SMILE.py | 20 ++++++++++++++++++++
 Ccs/ccs_function_lib.py   | 29 ++++++++++++++++++++++++++---
 Ccs/monitor.py            |  3 +++
 Ccs/plotter.py            |  6 +++---
 4 files changed, 52 insertions(+), 6 deletions(-)

diff --git a/Ccs/calibrations_SMILE.py b/Ccs/calibrations_SMILE.py
index 70fe0e8..adaaf2d 100644
--- a/Ccs/calibrations_SMILE.py
+++ b/Ccs/calibrations_SMILE.py
@@ -696,6 +696,26 @@ def cal_fee_hk(adu, signal):
     return val
 
 
+def calibrate_ext(adu, signal, exception=False):
+    """
+    Provide unified access to customised calibrations outside MIB.
+    This function shall expose all calibrations in this module that should be accessible by other CCS modules.
+
+    :param adu:
+    :param signal:
+    :param exception:
+    :return:
+    """
+
+    try:
+        return cal_fee_hk(adu, signal)
+    except ValueError:
+        return adu if not exception else None
+
+    # to disable calibration
+    # return adu if not exception else None
+
+
 if __name__ == '__main__':
 
     import matplotlib.pyplot as plt
diff --git a/Ccs/ccs_function_lib.py b/Ccs/ccs_function_lib.py
index 46def20..1f15ec8 100644
--- a/Ccs/ccs_function_lib.py
+++ b/Ccs/ccs_function_lib.py
@@ -65,6 +65,7 @@ except SQLOperationalError as err:
 _pcf_cache = {}
 _cap_cache = {}
 _txp_cache = {}
+_pcf_descr_cache = {}
 
 project = cfg.get('ccs-database', 'project')
 pc = importlib.import_module(PCPREFIX + str(project).upper())
@@ -88,6 +89,12 @@ except AttributeError as err:
     logger.critical(err)
     raise err
 
+try:
+    cal = importlib.import_module('calibrations_' + str(project).upper())
+except Exception as err:
+    logger.warning(err)
+    cal = None
+
 SREC_MAX_BYTES_PER_LINE = 250
 SEG_HEADER_FMT = '>III'
 SEG_HEADER_LEN = struct.calcsize(SEG_HEADER_FMT)
@@ -1770,6 +1777,9 @@ def get_calibrated(pcf_name, rawval, properties=None, numerical=False, dbcon=Non
     elif type_par.startswith('oct'):
         return rawval.hex().upper()
     elif curtx is None:
+        if not nocal and cal is not None:
+            calval = cal.calibrate_ext(rawval, pcf_name_to_descr(pcf_name))
+            return calval if floatfmt is None else format(calval, floatfmt)
         try:
             return rawval if isinstance(rawval, (int, float)) else rawval[0]
         except IndexError:
@@ -2202,9 +2212,10 @@ def get_param_values(tmlist=None, hk=None, param=None, last=0, numerical=False,
         apid = int(pktkey[2]) if pktkey[2] != 'None' else None
         sid = int(pktkey[3]) if pktkey[3] != 'None' else None
         # name, descr, _, offbi, ptc, pfc, unit, _, bitlen = parinfo
-        _, descr, ptc, pfc, curtx, bitlen, _, _, _, _, _ = parinfo
-        unit = None
-        name = None
+        name, descr, ptc, pfc, curtx, bitlen, unit, _, _, _, _ = parinfo
+        if name in ['user_defined', 'user_defined_nopos', 'dp_item']:
+            unit = None
+            name = None
         offbi = 0
 
         offby = sum([x[5] for x in pktinfo[:pktinfo.index(parinfo)]]) // 8 + TM_HEADER_LEN  # +TM_HEADER_LEN for header
@@ -2259,13 +2270,20 @@ def get_param_values(tmlist=None, hk=None, param=None, last=0, numerical=False,
 
     try:
         arr = np.array(np.array(xy).T, dtype='float')
+
         # calibrate y values
         if not nocal and name is not None:
             get_cap_yval(name, arr[1, 0])  # calibrate one value to get name into _cap_cache
+
             if _cap_cache[name] is None:
+                # try custom calibration if not in MIB
+                if cal is not None:
+                    arr[1, :] = cal.calibrate_ext(arr[1, :], pcf_name_to_descr(name))
                 return arr, (descr, unit)
+
             xvals, yvals = _cap_cache[name]
             arr[1, :] = np.interp(arr[1, :], xvals, yvals, left=np.nan, right=np.nan)
+
         return arr, (descr, unit)
 
     except (ValueError, IndexError):
@@ -4442,10 +4460,15 @@ def pcf_name_to_descr(pcfname):
     """
     Look up PCF_DESCR for PCF_NAME in MIB
     """
+
+    if pcfname in _pcf_descr_cache:
+        return _pcf_descr_cache[pcfname]
+
     que = 'SELECT pcf_descr FROM pcf WHERE pcf_name="{}"'.format(pcfname)
     res = scoped_session_idb.execute(que).fetchall()
 
     if res:
+        _pcf_descr_cache[pcfname] = res[0][0]
         return res[0][0]
 
 
diff --git a/Ccs/monitor.py b/Ccs/monitor.py
index f468ae9..9cd4c88 100644
--- a/Ccs/monitor.py
+++ b/Ccs/monitor.py
@@ -535,6 +535,9 @@ class ParameterMonitor(Gtk.Window):
         elif curtx is not None:  # numerically calibrated
             return '.7G'
         else:
+            # check if externally calibrated
+            if cfl.cal is not None and cfl.cal.calibrate_ext(0, name, exception=True) is not None:
+                return '.7G'
             return 'd'
 
     def pckt_counter(self, rows, st, sst, pidx=0):
diff --git a/Ccs/plotter.py b/Ccs/plotter.py
index 006f92d..46a5cec 100644
--- a/Ccs/plotter.py
+++ b/Ccs/plotter.py
@@ -635,7 +635,7 @@ class PlotViewer(Gtk.Window):
                     bufidx = rows.order_by(DbTelemetry.idx.desc()).first().idx
                     self._pkt_buffer[hk] = (bufidx, pkts)
 
-            xy, (descr, unit) = cfl.get_param_values(pkts, hk=hk, param=parameter,
+            xy, (descr, unit) = cfl.get_param_values(tmlist=pkts, hk=hk, param=parameter,
                                                      numerical=True, tmfilter=False, nocal=nocal)
 
             if len(xy) == 0:
@@ -838,7 +838,7 @@ class PlotViewer(Gtk.Window):
 
                 try:
                     # xnew, ynew = cfl.get_param_values([row.raw for row in new_rows], hk, parameter, numerical=True)[0]
-                    xnew, ynew = cfl.get_param_values([row.raw for row in new_rows], hk, parameter, numerical=True, tmfilter=False, nocal=nocal)[0]
+                    xnew, ynew = cfl.get_param_values(tmlist=[row.raw for row in new_rows], hk=hk, param=parameter, numerical=True, tmfilter=False, nocal=nocal)[0]
                     idx_new = new_rows.order_by(DbTelemetry.idx.desc()).first().idx
                 except ValueError:
                     continue
@@ -985,7 +985,7 @@ class PlotViewer(Gtk.Window):
             params = list(d[n].keys())
             head = '# {}\n# CUC_Time\t\t'.format(n) + '\t\t'.join(params) + '\n'
             datablock = '\n'.join(['{:.6F}\t\t'.format(d[n][params[0]][i, 0]) + '\t\t'.join(
-                ['{:.12G}'.format(d[n][param][i, 1]) for param in params]) for i in range(len(d[n][params[0]][:, 1]))])
+                ['{:.15G}'.format(d[n][param][i, 1]) for param in params]) for i in range(len(d[n][params[0]][:, 1]))])
             hkblocks.append(head + datablock)
             text = '\n\n'.join(hkblocks)
 
-- 
GitLab