From a21adaaf7884900feeb0f5f078a7999585aede08 Mon Sep 17 00:00:00 2001
From: David Hammer <dhammer@mailbox.org>
Date: Tue, 8 Feb 2022 13:50:59 +0100
Subject: [PATCH] Add useful overview scenes

---
 src/calng/CalibrationManager.py |  17 ++++-
 src/calng/scenes.py             | 107 +++++++++++++++++++++++++++++---
 2 files changed, 115 insertions(+), 9 deletions(-)

diff --git a/src/calng/CalibrationManager.py b/src/calng/CalibrationManager.py
index 07f12772..bde13b4b 100644
--- a/src/calng/CalibrationManager.py
+++ b/src/calng/CalibrationManager.py
@@ -292,7 +292,11 @@ class CalibrationManager(DeviceClientBase, Device):
         displayType='Scenes',
         requiredAccessLevel=AccessLevel.OBSERVER,
         accessMode=AccessMode.READONLY,
-        defaultValue=['overview', 'managed_keys'],
+        defaultValue=[
+            'overview',
+            'managed_keys',
+            'correction_performance_overview',
+            'correction_constant_overview'],
         daqPolicy=DaqPolicy.OMIT)
 
     @slot
@@ -308,6 +312,17 @@ class CalibrationManager(DeviceClientBase, Device):
                 self._domain_device_ids,
             )
             payload = Hash('success', True, 'name', name, 'data', scene_data)
+        elif name == "correction_performance_overview":
+            scene_data = scenes.correction_device_performance_dashboard(
+                self._correction_device_ids,
+            )
+            payload = Hash('success', True, 'name', name, 'data', scene_data)
+        elif name == "correction_constant_overview":
+            scene_data = scenes.correction_constant_dashboard(
+                self._correction_device_ids,
+                self._correction_device_schema,
+            )
+            payload = Hash('success', True, 'name', name, 'data', scene_data)
         elif name.startswith('browse_schema'):
             if ':' in name:
                 prefix = name[len('browse_schema:'):]
diff --git a/src/calng/scenes.py b/src/calng/scenes.py
index 2d714f9d..d550ce91 100644
--- a/src/calng/scenes.py
+++ b/src/calng/scenes.py
@@ -20,6 +20,7 @@ from karabo.common.scenemodel.api import (
     RectangleModel,
     SceneModel,
     SceneTargetWindow,
+    TrendGraphModel,
     write_scene,
 )
 
@@ -33,9 +34,7 @@ PADDING = 5
 RECONFIGURABLE = 4  # TODO: look up proper enum
 NODE_TYPE_NODE = 1
 
-_type_to_display_model = {
-    "BOOL": CheckBoxModel
-}
+_type_to_display_model = {"BOOL": CheckBoxModel}
 _type_to_line_editable = {
     "BOOL": (CheckBoxModel, {"klass": "EditableCheckBox"}),
     "DOUBLE": (DoubleLineEditModel, {}),
@@ -125,7 +124,7 @@ def boxed(component_class):
 
 def DisplayRoundedFloat(*args, decimals=2, **kwargs):
     # note: naive subclass breaks as registry looks for writer based on exact class
-    return EvaluatorModel(*args, expression=f"f'{{x:{decimals}}}'", **kwargs)
+    return EvaluatorModel(*args, expression=f"f'{{x:.{decimals}f}}'", **kwargs)
 
 
 class Space:
@@ -472,7 +471,7 @@ class CompactCorrectionDeviceOverview(HorizontalLayout):
                 DisplayStateColorModel(
                     show_string=True,
                     keys=[f"{device_id}.state"],
-                    width=6 * BASE_INC,
+                    width=5 * BASE_INC,
                     height=BASE_INC,
                 ),
                 DisplayRoundedFloat(
@@ -490,7 +489,6 @@ class CompactCorrectionDeviceOverview(HorizontalLayout):
         )
 
 
-@titled("Other devices managed")
 @boxed
 class CompactDeviceLinkList(VerticalLayout):
     def __init__(self, device_ids):
@@ -507,7 +505,7 @@ class CompactDeviceLinkList(VerticalLayout):
                     DisplayStateColorModel(
                         show_string=True,
                         keys=[f"{device_id}.state"],
-                        width=7 * BASE_INC,
+                        width=5 * BASE_INC,
                         height=BASE_INC,
                     ),
                     padding=0,
@@ -688,12 +686,30 @@ def manager_device_overview_scene(
         HorizontalLayout(
             titled("Correction devices", width=8 * NARROW_INC)(boxed(VerticalLayout))(
                 children=[
+                    DeviceSceneLinkModel(
+                        text="Performance dashboard",
+                        keys=[f"{manager_device_id}.availableScenes"],
+                        target="correction_performance_overview",
+                        target_window=SceneTargetWindow.Dialog,
+                        width=10 * BASE_INC,
+                        height=BASE_INC,
+                    ),
+                    DeviceSceneLinkModel(
+                        text="Correction constant overview",
+                        keys=[f"{manager_device_id}.availableScenes"],
+                        target="correction_constant_overview",
+                        target_window=SceneTargetWindow.Dialog,
+                        width=10 * BASE_INC,
+                        height=BASE_INC,
+                    ),
+                ]
+                + [
                     CompactCorrectionDeviceOverview(device_id, cds_hash)
                     for device_id in sorted(correction_device_ids)
                 ],
                 padding=0,
             ),
-            CompactDeviceLinkList(
+            titled("Other devices managed")(CompactDeviceLinkList)(
                 sorted(
                     set(domain_device_ids)
                     - set(correction_device_ids)
@@ -703,6 +719,81 @@ def manager_device_overview_scene(
         ),
     )
 
+
+@scene_generator
+def correction_device_performance_dashboard(correction_device_ids):
+    correction_device_ids = sorted(correction_device_ids)
+    return HorizontalLayout(
+        titled("Correction device links")(CompactDeviceLinkList)(correction_device_ids),
+        VerticalLayout(
+            TrendGraphModel(
+                keys=[
+                    f"{device_id}.performance.rate"
+                    for device_id in correction_device_ids
+                ],
+                width=30 * BASE_INC,
+                height=15 * BASE_INC,
+            ),
+            TrendGraphModel(
+                keys=[
+                    f"{device_id}.performance.processingTime"
+                    for device_id in correction_device_ids
+                ],
+                width=30 * BASE_INC,
+                height=15 * BASE_INC,
+            ),
+            TrendGraphModel(
+                keys=[
+                    f"{device_id}.performance.ratioOfRecentTrainsReceived"
+                    for device_id in correction_device_ids
+                ],
+                width=30 * BASE_INC,
+                height=15 * BASE_INC,
+            ),
+        ),
+    )
+
+
+@scene_generator
+def correction_constant_dashboard(
+    correction_device_ids, correction_device_schema, prefix="foundConstants"
+):
+    correction_device_schema = schema_to_hash(correction_device_schema)
+    constant_names = list(correction_device_schema.get(prefix).getKeys())
+    correction_device_ids = sorted(correction_device_ids)
+    return VerticalLayout(
+        HorizontalLayout(
+            Space(width=6 * BASE_INC, height=BASE_INC),
+            *(
+                LabelModel(text=constant, width=7 * BASE_INC, height=BASE_INC)
+                for constant in constant_names
+            ),
+            padding=0,
+        ),
+        *(
+            HorizontalLayout(
+                DeviceSceneLinkModel(
+                    text=device_id.split("/")[-1],
+                    keys=[f"{device_id}.availableScenes"],
+                    width=6 * BASE_INC,
+                    height=BASE_INC,
+                ),
+                *(
+                    DisplayLabelModel(
+                        keys=[f"{device_id}.{prefix}.{constant}.validFrom"],
+                        width=7 * BASE_INC,
+                        height=BASE_INC,
+                        font_size=9,
+                    )
+                    for constant in constant_names
+                ),
+                padding=0,
+            )
+            for device_id in correction_device_ids
+        ),
+    )
+
+
 @scene_generator
 def simple_assembler_overview(device_id, geometry_device_id):
     return VerticalLayout(
-- 
GitLab