diff --git a/src/calng/AgipdCorrection.py b/src/calng/AgipdCorrection.py
index c295f6ac6fa0c676786e47bb526e49fd9c9e56d7..326197017ecd2ce4b6a945b6a62aaed0017faa88 100644
--- a/src/calng/AgipdCorrection.py
+++ b/src/calng/AgipdCorrection.py
@@ -98,13 +98,7 @@ class AgipdCorrection(BaseCorrection):
             .key("corrections.relGainXray.gGainValue")
             .displayedName("G_gain_value")
             .description(
-                "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)."
-                "Modern X-ray gain correction constants are absolute. The default "
+                "Newer X-ray gain correction constants are absolute. The default "
                 "G_gain_value of 1 means that output is expected to be in keV. If "
                 "this is not desired, one can here specify the mean X-ray gain value "
                 "over all modules to get ADU values out - operator must manually "
@@ -129,9 +123,19 @@ class AgipdCorrection(BaseCorrection):
             NODE_ELEMENT(expected)
             .key("corrections.badPixels.subsetToUse")
             .displayedName("Bad pixel flags to use")
+            .description(
+                "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)."
+            )
             .commit(),
         )
-        AgipdCorrection._managed_keys.append("corrections.relGainPc.overrideMdAdditionalOffset")
+        AgipdCorrection._managed_keys.append(
+            "corrections.relGainPc.overrideMdAdditionalOffset"
+        )
         AgipdCorrection._managed_keys.append("corrections.relGainPc.mdAdditionalOffset")
         AgipdCorrection._managed_keys.append("corrections.relGainXray.gGainValue")
         AgipdCorrection._managed_keys.append("corrections.badPixels.maskingValue")
@@ -145,7 +149,11 @@ class AgipdCorrection(BaseCorrection):
                 .reconfigurable()
                 .commit()
             )
-            AgipdCorrection._managed_keys.append(f"corrections.badPixels.subsetToUse.{field.name}")
+            AgipdCorrection._managed_keys.append(
+                f"corrections.badPixels.subsetToUse.{field.name}"
+            )
+
+        # mandatory: manager needs this in schema
         (
             VECTOR_STRING_ELEMENT(expected)
             .key("managedKeys")
@@ -347,16 +355,7 @@ class AgipdCorrection(BaseCorrection):
                 selection |= field
         self._override_bad_pixel_flags = selection
 
-    def preReconfigure(self, config):
-        super().preReconfigure(config)
-        if any(
-            path.startswith("corrections.badPixels.subsetToUse")
-            for path in config.getPaths()
-        ):
-            self._has_updated_bad_pixel_selection = False
-
     def postReconfigure(self):
-        # TODO: keep track of which things actually need updating
         super().postReconfigure()
 
         if self.get("corrections.relGainPc.overrideMdAdditionalOffset"):
@@ -369,16 +368,32 @@ class AgipdCorrection(BaseCorrection):
         else:
             self._override_md_additional_offset = None
 
-        self.gpu_runner.set_g_gain_value(self.get("corrections.relGainXray.gGainValue"))
-        self._gpu_runner_init_args["g_gain_value"] = self.get(
-            "corrections.relGainXray.gGainValue"
-        )
+        if not hasattr(self, "_prereconfigure_update_hash"):
+            return
 
-        self.bad_pixel_mask_value = eval(self.get("corrections.badPixels.maskingValue"))
-        self.gpu_runner.set_bad_pixel_mask_value(self.bad_pixel_mask_value)
-        self._gpu_runner_init_args["bad_pixel_mask_value"] = self.bad_pixel_mask_value
+        update = self._prereconfigure_update_hash
 
-        if not self._has_updated_bad_pixel_selection:
+        if update.has("corrections.relGainXray.gGainValue"):
+            self.gpu_runner.set_g_gain_value(
+                self.get("corrections.relGainXray.gGainValue")
+            )
+            self._gpu_runner_init_args["g_gain_value"] = self.get(
+                "corrections.relGainXray.gGainValue"
+            )
+
+        if update.has("corrections.badPixels.maskingValue"):
+            self.bad_pixel_mask_value = eval(
+                self.get("corrections.badPixels.maskingValue")
+            )
+            self.gpu_runner.set_bad_pixel_mask_value(self.bad_pixel_mask_value)
+            self._gpu_runner_init_args[
+                "bad_pixel_mask_value"
+            ] = self.bad_pixel_mask_value
+
+        if any(
+            path.startswith("corrections.badPixels.subsetToUse")
+            for path in update.getPaths()
+        ):
             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 fd3fbdc0cbe514de13ef8aa7cd0a4d21cc669e5b..a504ca9c95a5e83bf40d97e3117675f6166d31bc 100644
--- a/src/calng/base_correction.py
+++ b/src/calng/base_correction.py
@@ -410,13 +410,21 @@ class BaseCorrection(PythonDevice):
             )
 
     def preReconfigure(self, config):
-        for path in config.getPaths():
+        self._prereconfigure_update_hash = config
+
+    def postReconfigure(self):
+        if not hasattr(self, "_prereconfigure_update_hash"):
+            self.log_status_warn("postReconfigure without knowing update hash")
+            return
+
+        update = self._prereconfigure_update_hash
+        for path in update.getPaths():
             if path in self._schema_cache_fields:
-                self._schema_cache[path] = config.get(path)
+                self._schema_cache[path] = update.get(path)
 
         # TODO: pulse filter (after reimplementing)
         if any(
-            config.has(shape_param)
+            update.has(shape_param)
             for shape_param in (
                 "dataFormat.pixelsX",
                 "dataFormat.pixelsY",
@@ -424,31 +432,10 @@ class BaseCorrection(PythonDevice):
                 "constantParameters.memoryCells",
             )
         ):
-            # will make postReconfigure handle shape update after merging schema
-            self._has_updated_shapes = False
-
-    def log_status_info(self, msg):
-        self.log.INFO(msg)
-        self.set("status", msg)
-
-    def log_status_warn(self, msg):
-        self.log.WARN(msg)
-        self.set("status", msg)
-
-    def postReconfigure(self):
-        if not self._has_updated_shapes:
             self._update_shapes()
         # TODO: only call this if they are changed (is cheap, though)
         self._update_correction_flags()
 
-    def set(self, *args):
-        """Wrapper around PythonDevice.set to enable caching "hot" schema elements"""
-        if len(args) == 2:
-            key, value = args
-            if key in self._schema_cache_fields:
-                self._schema_cache[key] = value
-        super().set(*args)
-
     def loadMostRecentConstants(self):
         self.flush_constants()
         self.calcat_friend.flush_constants()
@@ -464,6 +451,27 @@ class BaseCorrection(PythonDevice):
         self.gpu_runner.flush_buffers()
         self._update_correction_flags()
 
+    def log_status_info(self, msg):
+        self.log.INFO(msg)
+        self.set("status", msg)
+
+    def log_status_warn(self, msg):
+        self.log.WARN(msg)
+        self.set("status", msg)
+
+    def log_status_error(self, msg):
+        self.set("status", msg)
+        self.log.ERROR(msg)
+        self.updateState(State.ERROR)
+
+    def set(self, *args):
+        """Wrapper around PythonDevice.set to enable caching "hot" schema elements"""
+        if len(args) == 2:
+            key, value = args
+            if key in self._schema_cache_fields:
+                self._schema_cache[key] = value
+        super().set(*args)
+
     def requestScene(self, params):
         payload = Hash()
         scene_name = params.get("name", default="")
diff --git a/src/tests/test_dssc_kernels.py b/src/tests/test_dssc_kernels.py
index 3790c56095b8d0dbf67318490db93e866ea97b9a..b8e90ceea635f8ad198e6ac8136a2457a21f7248 100644
--- a/src/tests/test_dssc_kernels.py
+++ b/src/tests/test_dssc_kernels.py
@@ -74,7 +74,7 @@ def test_correct_oob_cells():
 
 def test_reshape():
     kernel_runner.processed_data_gpu.set(corrected_data)
-    assert np.allclose(kernel_runner.reshape(), corrected_data.transpose())
+    assert np.allclose(kernel_runner.reshape(output_order="xyc"), corrected_data.transpose())
 
 
 def test_preview_slice():