From 79a30a5979d29705f7146d41524ee8bb15dcb720 Mon Sep 17 00:00:00 2001
From: David Hammer <dhammer@mailbox.org>
Date: Mon, 1 Nov 2021 14:28:24 +0100
Subject: [PATCH] Automatically reload BadPixel constants if reenabling fields

---
 src/calng/AgipdCorrection.py | 18 +++++++++++++++---
 src/calng/base_correction.py | 14 +++++++-------
 src/calng/calcat_utils.py    |  7 +++++--
 3 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/src/calng/AgipdCorrection.py b/src/calng/AgipdCorrection.py
index b6c4cb4a..10da69ce 100644
--- a/src/calng/AgipdCorrection.py
+++ b/src/calng/AgipdCorrection.py
@@ -151,9 +151,8 @@ class AgipdCorrection(BaseCorrection):
                 "The booleans under this node allow for selecting a subset of bad "
                 "pixel types to take into account when doing bad pixel masking. "
                 "Upon updating these flags, the map used for bad pixel masking will "
-                "be ANDed with this selection. Therefore, if you want to toggle a "
-                "disabled flag back on, please reload constants for this to take "
-                "effect (will be triggered automatically in future version)."
+                "be ANDed with this selection. Turning disabled flags back on causes "
+                "reloading of cached constants."
             )
             .commit(),
         )
@@ -478,6 +477,19 @@ class AgipdCorrection(BaseCorrection):
             path.startswith("corrections.badPixels.subsetToUse")
             for path in update.getPaths()
         ):
+            self.log_status_info("Updating bad pixel maps based on subset specified")
+            if any(
+                update.get(f"corrections.badPixels.subsetToUse.{field.name}", default=False)
+                for field in BadPixelValues
+            ):
+                self.log_status_info("Some fields reenabled, reloading cached bad pixel constants")
+                with self.calcat_friend.cached_constants_lock:
+                    for (
+                        constant,
+                        data,
+                    ) in self.calcat_friend.cached_constants.items():
+                        if "BadPixels" in constant.name:
+                            self._load_constant_to_gpu(constant, data)
             self._update_bad_pixel_selection()
             self.gpu_runner.override_bad_pixel_flags_to_use(
                 self._override_bad_pixel_flags
diff --git a/src/calng/base_correction.py b/src/calng/base_correction.py
index 1d971b93..40f633f2 100644
--- a/src/calng/base_correction.py
+++ b/src/calng/base_correction.py
@@ -661,13 +661,13 @@ class BaseCorrection(PythonDevice):
             **self._gpu_runner_init_args,
         )
 
-        # TODO: lock to avoid dict changing size underneath us
-        for (
-            constant,
-            data,
-        ) in self.calcat_friend.cached_constants.items():
-            self.log_status_info(f"Reload constant {constant}")
-            self._load_constant_to_gpu(constant, data)
+        with self.calcat_friend.cached_constants_lock:
+            for (
+                constant,
+                data,
+            ) in self.calcat_friend.cached_constants.items():
+                self.log_status_info(f"Reload constant {constant}")
+                self._load_constant_to_gpu(constant, data)
 
         self._has_updated_shapes = True
 
diff --git a/src/calng/calcat_utils.py b/src/calng/calcat_utils.py
index ed6ae21f..ce9d9811 100644
--- a/src/calng/calcat_utils.py
+++ b/src/calng/calcat_utils.py
@@ -266,6 +266,7 @@ class BaseCalcatFriend:
         self.param_prefix = param_prefix
         self.status_prefix = status_prefix
         self.cached_constants = {}
+        self.cached_constants_lock = threading.Lock()
 
         if not secrets_fn.is_file():
             self.device.log_status_warn(
@@ -435,7 +436,8 @@ class BaseCalcatFriend:
         # TODO: handle FileNotFoundError if we are led astray
         with h5py.File(file_path, "r") as fd:
             constant_data = np.array(fd[resp["data"]["data_set_name"]]["data"])
-        self.cached_constants[constant] = constant_data
+        with self.cached_constants_lock:
+            self.cached_constants[constant] = constant_data
         self._set_status(constant, "found", True)
         self.device.log_status_info(f"Done finding {constant} for {karabo_da}")
 
@@ -455,7 +457,8 @@ class BaseCalcatFriend:
         )
         with h5py.File(file_path, "r") as fd:
             constant_data = np.array(fd[resp["data"]["data_set_name"]]["data"])
-        self.cached_constants[constant] = constant_data
+        with self.cached_constants_lock:
+            self.cached_constants[constant] = constant_data
         self._set_status(constant, "validFrom", resp["data"]["begin_at"])
         self._set_status(constant, "calibrationId", "manual override")
         self._set_status(constant, "conditionId", "manual override")
-- 
GitLab