From ff44656800efe03820257e72d41b025da921491c Mon Sep 17 00:00:00 2001
From: ahmedk <karim.ahmed@xfel.eu>
Date: Tue, 2 Aug 2022 15:41:14 +0200
Subject: [PATCH] New Settings and gain mode enums to read the jungfrau correct
 parameters

---
 ...rk_analysis_all_gains_burst_mode_NBC.ipynb | 26 +++++--
 src/cal_tools/enums.py                        | 32 +++++++-
 src/cal_tools/jungfraulib.py                  | 77 ++++++++++++++-----
 3 files changed, 106 insertions(+), 29 deletions(-)

diff --git a/notebooks/Jungfrau/Jungfrau_dark_analysis_all_gains_burst_mode_NBC.ipynb b/notebooks/Jungfrau/Jungfrau_dark_analysis_all_gains_burst_mode_NBC.ipynb
index 15c23af34..2de27f67d 100644
--- a/notebooks/Jungfrau/Jungfrau_dark_analysis_all_gains_burst_mode_NBC.ipynb
+++ b/notebooks/Jungfrau/Jungfrau_dark_analysis_all_gains_burst_mode_NBC.ipynb
@@ -89,7 +89,11 @@
     "from XFELDetAna.plotting.histogram import histPlot\n",
     "from cal_tools import jungfraulib, step_timing\n",
     "from cal_tools.ana_tools import save_dict_to_hdf5\n",
-    "from cal_tools.enums import BadPixels, JungfrauSettings\n",
+    "from cal_tools.enums import (\n",
+    "    BadPixels,\n",
+    "    JungfrauGainModes,\n",
+    "    JungfrauOldSettings,\n",
+    ")\n",
     "from cal_tools.tools import (\n",
     "    get_dir_creation_date,\n",
     "    get_pdu_from_db,\n",
@@ -112,10 +116,18 @@
     "sensor_size = (1024, 512)\n",
     "gains = [0, 1, 2]\n",
     "\n",
+    "fixed_settings_old = [\n",
+    "    str(JungfrauOldSettings.FIX_GAIN_1),\n",
+    "    str(JungfrauOldSettings.FIX_GAIN_2),\n",
+    "    ]\n",
     "fixed_settings = [\n",
-    "    JungfrauSettings.FIX_GAIN_1.value, JungfrauSettings.FIX_GAIN_2.value]  # noqa\n",
+    "    str(JungfrauGainModes.FIX_GAIN_1),\n",
+    "    str(JungfrauGainModes.FIX_GAIN_2),\n",
+    "]\n",
     "dynamic_settings = [\n",
-    "    JungfrauSettings.FORCE_SWITCH_HG1.value, JungfrauSettings.FORCE_SWITCH_HG2.value]  # noqa\n",
+    "    str(JungfrauGainModes.FORCE_SWITCH_HG1),\n",
+    "    str(JungfrauGainModes.FORCE_SWITCH_HG2),\n",
+    "    ]\n",
     "\n",
     "creation_time = None\n",
     "if use_dir_creation_date:\n",
@@ -168,7 +180,7 @@
     "    run_dc = RunDirectory(f\"{in_folder}/r{run_n:04d}/\")\n",
     "    gain_runs[run_n] = [gain, run_dc]\n",
     "    ctrl_data = jungfraulib.JungfrauCtrl(run_dc, ctrl_src)\n",
-    "    run_settings = ctrl_data.run_settings.value if ctrl_data.run_settings else ctrl_data.run_settings  # noqa\n",
+    "    run_settings = ctrl_data.run_settings\n",
     "    # Read control data for the high gain run only.\n",
     "    if run_n == run_high:\n",
     "\n",
@@ -192,7 +204,7 @@
     "    else:\n",
     "        gain_mode = ctrl_data.get_gain_mode()\n",
     "\n",
-    "        med_low_settings.append(run_settings)\n",
+    "        med_low_settings.append(str(run_settings))\n",
     "\n",
     "# A transperent workaround for old raw data with wrong/missing medium and low settings\n",
     "if med_low_settings == [None, None]:\n",
@@ -202,10 +214,10 @@
     "    print(f\"WARNING: run.settings for medium and low gain runs are wrong {med_low_settings}. \"\n",
     "          f\"This is an expected bug for old raw data. Setting gain_mode to {gain_mode}.\")\n",
     "# Validate that low_med_settings is not a mix of adaptive and fixed settings.\n",
-    "elif not (sorted(med_low_settings) in [fixed_settings, dynamic_settings]):  # noqa\n",
+    "elif not (sorted(med_low_settings) in [fixed_settings, dynamic_settings, fixed_settings_old]):  # noqa\n",
     "    raise ValueError(\n",
     "        \"Medium and low run settings are not as expected. \"\n",
-    "        f\"Either {dynamic_settings} or {fixed_settings} are expected.\\n\"\n",
+    "        f\"Either {dynamic_settings}, {fixed_settings}, or {fixed_settings_old} are expected.\\n\"\n",
     "        f\"Got {sorted(med_low_settings)} for both runs, respectively.\")\n",
     "\n",
     "print(f\"Gain mode is {gain_mode} ({med_low_settings})\")\n",
diff --git a/src/cal_tools/enums.py b/src/cal_tools/enums.py
index d800eecc8..823b82529 100644
--- a/src/cal_tools/enums.py
+++ b/src/cal_tools/enums.py
@@ -1,4 +1,9 @@
-from enum import Enum, IntEnum, IntFlag
+from enum import Enum, IntEnum, IntFlag, EnumMeta
+
+
+class MetaValueCheck(EnumMeta):  
+    def __contains__(cls, item): 
+        return item in [i.value for i in cls.__members__.values()]
 
 
 class BadPixels(IntFlag):
@@ -45,11 +50,32 @@ class AgipdGainMode(IntEnum):
     FIXED_LOW_GAIN = 3
 
 
-class JungfrauSettings(Enum):
-    """ Jungfrau run gain settings."""
+class JungfrauOldSettings(Enum, metaclass=MetaValueCheck):
+    """ Jungfrau run gain settings before changes in jungfrau software.
+    https://git.xfel.eu/karaboDevices/slsDetectors/-/commit/4433ae9c00edcca3309bec8b7515e0938f5f502c  # noqa
+    """
     DYNAMIC_GAIN = "dynamicgain"
     DYNAMIC_GAIN_HG0 = "dynamichg0"
     FIX_GAIN_1 = "fixgain1"
     FIX_GAIN_2 = "fixgain2"
     FORCE_SWITCH_HG1 = "forceswitchg1"
     FORCE_SWITCH_HG2 = "forceswitchg2"
+    def __str__(self):
+        return str(self.value)
+
+class JungfrauSettings(Enum, metaclass=MetaValueCheck):
+    """ Jungfrau run gain settings."""
+    DYNAMIC_GAIN = "gain0"
+    DYNAMIC_GAIN_HG0 = "highgain0"
+    def __str__(self):
+        return str(self.value)
+
+class JungfrauGainModes(Enum, metaclass=MetaValueCheck):
+    """ Jungfrau run gain modes."""
+    DYNAMIC = "dynamic"
+    FIX_GAIN_1 = "fixg1"
+    FIX_GAIN_2 = "fixg2"
+    FORCE_SWITCH_HG1 = "forceswitchg1"
+    FORCE_SWITCH_HG2 = "forceswitchg2"
+    def __str__(self):
+        return str(self.value)
\ No newline at end of file
diff --git a/src/cal_tools/jungfraulib.py b/src/cal_tools/jungfraulib.py
index 402888dfa..df9e8b65f 100644
--- a/src/cal_tools/jungfraulib.py
+++ b/src/cal_tools/jungfraulib.py
@@ -1,33 +1,43 @@
 from typing import Tuple
 
-from cal_tools.enums import JungfrauSettings
+from cal_tools.enums import (
+    JungfrauSettings,
+    JungfrauOldSettings,
+    JungfrauGainModes,
+    )
+import extra_data
 
 
-def _get_settings(run_dc, ctrl_src) -> str:
+def _get_settings(
+    run_dc: extra_data.DataCollection,
+    ctrl_src: str
+    ) -> Tuple[str, "enum"] :
+    """Get run settings string value and identify
+    the enum to use for the jungfau run settings.
+    """
     try:
-        return(JungfrauSettings(
-            run_dc.get_run_value(ctrl_src, "settings.value")))
-    except KeyError:
-        print(
-            "WARNING: \'settings.value\' key is not available at "
-            f"{run_dc.select(ctrl_src).files[0].filename},\n")
-        return
+        settings = run_dc.get_run_value(ctrl_src, "settings.value")
+        if settings in JungfrauOldSettings:
+            return settings, JungfrauOldSettings
+        else:
+            return settings, JungfrauSettings
+    except extra_data.PropertyNameError:
+        return None, JungfrauSettings
 
 
 class JungfrauCtrl():
     def __init__(
         self,
-        run_dc: "extra_data.DataCollection",  # noqa
+        run_dc: extra_data.DataCollection,
         ctrl_src: str,
     ):
-
         """Read slow data from RUN source.
         :param run_dir: EXtra-data RunDirectory DataCollection object.
         :param ctrl_src: Control source name for accessing run slow data.
         """
         self.run_dc = run_dc
         self.ctrl_src = ctrl_src
-        self.run_settings = _get_settings(run_dc, ctrl_src)
+        self.run_settings, self.settings_enum = _get_settings(run_dc, ctrl_src)
 
     def get_memory_cells(self) -> Tuple[int, int]:
         n_storage_cells = int(self.run_dc.get_run_value(
@@ -45,18 +55,47 @@ class JungfrauCtrl():
             self.ctrl_src, "exposureTime.value")) * 1e6)
 
     def get_gain_setting(self) -> int:
-        if self.run_settings == JungfrauSettings.DYNAMIC_GAIN_HG0:
+        """Get run gain settings to identify if run is in
+        High CDS or Low CDS.
+        """
+        if self.run_settings == self.settings_enum.DYNAMIC_GAIN_HG0:
             gain_setting = 1
-        else:  # JungfrauSettings.DYNAMIC_GAIN
+        else:  # JungfrauOldSettings.DYNAMIC_GAIN
             gain_setting = 0
-            if self.run_settings != JungfrauSettings.DYNAMIC_GAIN:
+            if self.run_settings != str(self.settings_enum.DYNAMIC_GAIN):
                 print(
                     "WARNING: Setting gain_setting to 0, "
-                    "assuming that this is an old run.\n")
-        return gain_setting
+                    "assuming that this is an old run. "
+                    f"run.settings is {self.run_settings}\n")
+            return gain_setting
 
-    def get_gain_mode(self) -> int:
-        if self.run_settings in [JungfrauSettings.FIX_GAIN_1, JungfrauSettings.FIX_GAIN_2]:  # noqa
+    def _get_gain_mode_settings(self) -> int:
+        """Gain Mode is fixed (1) if the enum
+        is fixgain1 or fixgain2.
+        """
+        if self.run_settings in [
+            self.settings_enum.FIX_GAIN_1, self.settings_enum.FIX_GAIN_2]:
             return 1
         else:
             return 0
+
+    def _get_gain_mode_ctrl(self) -> int:
+        """From Jungfrau SW V5 gain_mode is deducted from
+        /CONTROL/..../gainMode.
+        With different enums: dynamic, fixg1, fixg2,
+        forceswitchg1, forceswitchg2. which are used to decide
+        if the value is 0 or 1.
+        Gain Mode is fixed (1) if the enum is fixg1 or fixg2.
+        """
+        gain_mode = self.run_dc[self.ctrl_src, "gainMode"].as_single_value()
+        if gain_mode in [
+            JungfrauGainModes.FIX_GAIN_1, JungfrauGainModes.FIX_GAIN_2]:
+            return 1
+        else:
+            return 0
+
+    def get_gain_mode(self) -> int:
+        if "gainMode.value" in self.run_dc.keys_for_source(self.ctrl_src):
+            return self._get_gain_mode_ctrl()
+        else:
+            return self._get_gain_mode_settings()
\ No newline at end of file
-- 
GitLab