diff --git a/setup.py b/setup.py
index ce8c3831bec85ac67369fea7350f657bd78fdfd2..01d3fadbe09d764a055f20c63593b829e7b1681b 100644
--- a/setup.py
+++ b/setup.py
@@ -25,12 +25,11 @@ setup(name='calng',
       entry_points={
           'karabo.bound_device': [
               'AgipdCorrection = calng.AgipdCorrection:AgipdCorrection',
+              'ManualAgipdGeometry = calng.AgipdCorrection:ManualAgipdGeometry',
               'DsscCorrection = calng.DsscCorrection:DsscCorrection',
+              'ManualDsscGeometry = calng.DsscCorrection:ManualDsscGeometry',
               'JungfrauCorrection = calng.JungfrauCorrection:JungfrauCorrection',
-              'ModuleStacker = calng.ModuleStacker:ModuleStacker',
-              'ManualAgipdGeometry = calng.ManualAgipdGeometry:ManualAgipdGeometry',
-              'ManualDsscGeometry = calng.ManualDsscGeometry:ManualDsscGeometry',
-              'ManualJungfrauGeometry = calng.ManualJungfrauGeometry:ManualJungfrauGeometry',
+              'ManualJungfrauGeometry = calng.JungfrauCorrection:ManualJungfrauGeometry',
               'ShmemToZMQ = calng.ShmemToZMQ:ShmemToZMQ',
               'ShmemTrainMatcher = calng.ShmemTrainMatcher:ShmemTrainMatcher',
               'DetectorAssembler = calng.DetectorAssembler:DetectorAssembler',
diff --git a/src/calng/AgipdCorrection.py b/src/calng/AgipdCorrection.py
index 5c18952a35ba481c2225ad3edef58adb4d89490b..353de48cb44ba2d75325cdf7b242ad23582870fc 100644
--- a/src/calng/AgipdCorrection.py
+++ b/src/calng/AgipdCorrection.py
@@ -14,7 +14,7 @@ from karabo.bound import (
     VECTOR_STRING_ELEMENT,
 )
 
-from . import base_gpu, calcat_utils, utils
+from . import base_calcat, base_geometry, base_gpu, utils
 from ._version import version as deviceVersion
 from .base_correction import BaseCorrection, add_correction_step_schema, preview_schema
 
@@ -317,7 +317,7 @@ class AgipdGpuRunner(base_gpu.BaseGpuRunner):
         self.correction_kernel = self.source_module.get_function("correct")
 
 
-class AgipdCalcatFriend(calcat_utils.BaseCalcatFriend):
+class AgipdCalcatFriend(base_calcat.BaseCalcatFriend):
     _constant_enum_class = AgipdConstants
 
     def __init__(self, device, *args, **kwargs):
@@ -398,10 +398,10 @@ class AgipdCalcatFriend(calcat_utils.BaseCalcatFriend):
         managed_keys.add(f"{param_prefix}.gainMode")
         managed_keys.add(f"{param_prefix}.integrationTime")
 
-        calcat_utils.add_status_schema_from_enum(schema, status_prefix, AgipdConstants)
+        base_calcat.add_status_schema_from_enum(schema, status_prefix, AgipdConstants)
 
     def dark_condition(self):
-        res = calcat_utils.OperatingConditions()
+        res = base_calcat.OperatingConditions()
         res["Memory cells"] = self._get_param("memoryCells")
         res["Sensor Bias Voltage"] = self._get_param("biasVoltage")
         res["Pixels X"] = self._get_param("pixelsX")
@@ -832,3 +832,27 @@ class AgipdCorrection(BaseCorrection):
             self.kernel_runner.override_bad_pixel_flags_to_use(
                 self._override_bad_pixel_flags
             )
+
+
+@KARABO_CLASSINFO("ManualAgipdGeometry", deviceVersion)
+class ManualAgipdGeometry(base_geometry.ManualQuadrantsGeometryBase):
+    def __init__(self, *args, **kwargs):
+        import extra_geom
+        self.geometry_class = extra_geom.AGIPD_1MGeometry
+        super().__init__(*args, **kwargs)
+
+    @staticmethod
+    def expectedParameters(expected):
+        super(ManualAgipdGeometry, ManualAgipdGeometry).expectedParameters(expected)
+
+        expected.setDefaultValue("quadrantCorners.Q1.x", -525)
+        expected.setDefaultValue("quadrantCorners.Q1.y", 625)
+
+        expected.setDefaultValue("quadrantCorners.Q2.x", -550)
+        expected.setDefaultValue("quadrantCorners.Q2.y", -10)
+
+        expected.setDefaultValue("quadrantCorners.Q3.x", 520)
+        expected.setDefaultValue("quadrantCorners.Q3.y", -160)
+
+        expected.setDefaultValue("quadrantCorners.Q4.x", 542.5)
+        expected.setDefaultValue("quadrantCorners.Q4.y", 475)
diff --git a/src/calng/CalibrationManager.py b/src/calng/CalibrationManager.py
index b78948b0fed20605cf1f00d0e8a559ec9d9bce41..cf46b4c5f3d8374b18e9d33d3e05b508c6ddf8a7 100644
--- a/src/calng/CalibrationManager.py
+++ b/src/calng/CalibrationManager.py
@@ -18,7 +18,6 @@ import re
 
 from tornado.httpclient import AsyncHTTPClient, HTTPError
 from tornado.platform.asyncio import AsyncIOMainLoop, to_asyncio_future
-from pkg_resources import parse_version
 
 from karabo.middlelayer import (
     KaraboError, Device, DeviceClientBase, Descriptor, Hash, Configurable,
@@ -30,7 +29,6 @@ from karabo.middlelayer import (
     getConfigurationFromName, get_property)
 from karabo.middlelayer_api.proxy import ProxyFactory
 
-from karabo import version as karaboVersion
 from ._version import version as deviceVersion
 from . import scenes
 
@@ -244,10 +242,7 @@ class CalibrationManager(DeviceClientBase, Device):
     interfaces = VectorString(
         displayedName='Device interfaces',
         description='Interfaces implemented by this device.',
-        defaultValue=(
-            ['DeviceInstantiator']
-            if parse_version(karaboVersion) >= parse_version('2.11')
-            else []),
+        defaultValue=(['DeviceInstantiator']),
         accessMode=AccessMode.READONLY)
 
     availableScenes = VectorString(
@@ -380,13 +375,6 @@ class CalibrationManager(DeviceClientBase, Device):
         self.deviceServers = value
         self._servers_changed = True
 
-    imageDataPath = String(
-        displayedName='Image data path',
-        description='Path in DAQ hash to actual image data, used for preview',
-        accessMode=AccessMode.RECONFIGURABLE,
-        assignment=Assignment.OPTIONAL,
-        defaultValue='image.data')
-
     geometryDevice = String(
         displayedName='Geometry device',
         description='[NYI] Device ID for a geometry device defining the '
@@ -512,13 +500,7 @@ class CalibrationManager(DeviceClientBase, Device):
 
     async def onInitialization(self):
         self.state = State.INIT
-
-        if parse_version(karaboVersion) < parse_version('2.11'):
-            # Compatibility with 2.10 and before, where onInitialization
-            # is awaited during device instantation.
-            background(self._async_init())
-        else:
-            await self._async_init()
+        await self._async_init()
 
     @coslot
     async def slotInstanceNew(self, instance_id, info):
@@ -1306,7 +1288,6 @@ class CalibrationManager(DeviceClientBase, Device):
 
             config = Hash()
             # TODO: put _image_data_path in corr dev schema, get from there
-            config['pathToStack'] = self.imageDataPath.value
             config['sources'] = [
                 Hash('select', True,
                      'source',
diff --git a/src/calng/DetectorAssembler.py b/src/calng/DetectorAssembler.py
index 3cf5989a6b80aee725f34266b205a1d25375ab0f..47b83973fb3db4a91896159c9f801d9074e1fa22 100644
--- a/src/calng/DetectorAssembler.py
+++ b/src/calng/DetectorAssembler.py
@@ -4,7 +4,6 @@ import pickle
 import re
 import threading
 import time
-from pkg_resources import parse_version
 
 import numpy as np
 from karabo.bound import (
@@ -33,7 +32,6 @@ from karabo.bound import (
 )
 from TrainMatcher import TrainMatcher
 
-from karabo import version as karaboVersion
 from . import scenes
 from ._version import version as deviceVersion
 
@@ -232,19 +230,17 @@ class DetectorAssembler(TrainMatcher.TrainMatcher):
                         self.get("geometryInput.connectedOutputChannels")
                     )
                     # first check if geometry device not even connected
-                    if parse_version(karaboVersion) >= parse_version("2.11"):
-                        # missingConnections apparently not a thing on 2.10
-                        missing_connections = set(
-                            self.get("geometryInput.missingConnections")
-                        )
-                        geometry_device_list = [
-                            channel
-                            for channel in geometry_device_list
-                            if channel not in missing_connections
-                        ]
-                        if not geometry_device_list:
-                            self.log.INFO("No geometry device connected")
-                            continue
+                    missing_connections = set(
+                        self.get("geometryInput.missingConnections")
+                    )
+                    geometry_device_list = [
+                        channel
+                        for channel in geometry_device_list
+                        if channel not in missing_connections
+                    ]
+                    if not geometry_device_list:
+                        self.log.INFO("No geometry device connected")
+                        continue
                     geometry_device = geometry_device_list[0].split(":")[0]
                     self.log.INFO(f"Asking {geometry_device} for a geometry")
                     self.signalSlotable.call(geometry_device, "pleaseSendYourGeometry")
diff --git a/src/calng/DsscCorrection.py b/src/calng/DsscCorrection.py
index 446cb064fa3090eac55c3f97094f145bbd01dd28..4df05a25d434ae86237ad9ccd2a1bca5ef1715d4 100644
--- a/src/calng/DsscCorrection.py
+++ b/src/calng/DsscCorrection.py
@@ -9,7 +9,7 @@ from karabo.bound import (
     VECTOR_STRING_ELEMENT,
 )
 
-from . import base_gpu, calcat_utils, utils
+from . import base_calcat, base_geometry, base_gpu, utils
 from ._version import version as deviceVersion
 from .base_correction import BaseCorrection, add_correction_step_schema
 
@@ -99,7 +99,7 @@ class DsscGpuRunner(base_gpu.BaseGpuRunner):
         self.correction_kernel = self.source_module.get_function("correct")
 
 
-class DsscCalcatFriend(calcat_utils.BaseCalcatFriend):
+class DsscCalcatFriend(base_calcat.BaseCalcatFriend):
     _constant_enum_class = DsscConstants
 
     def __init__(self, device, *args, **kwargs):
@@ -149,10 +149,10 @@ class DsscCalcatFriend(calcat_utils.BaseCalcatFriend):
             .commit(),
         )
 
-        calcat_utils.add_status_schema_from_enum(schema, status_prefix, DsscConstants)
+        base_calcat.add_status_schema_from_enum(schema, status_prefix, DsscConstants)
 
     def dark_condition(self):
-        res = calcat_utils.OperatingConditions()
+        res = base_calcat.OperatingConditions()
         res["Memory cells"] = self._get_param("memoryCells")
         res["Sensor Bias Voltage"] = self._get_param("biasVoltage")
         res["Pixels X"] = self._get_param("pixelsX")
@@ -286,3 +286,27 @@ class DsscCorrection(BaseCorrection):
 
         self._update_correction_flags()
         self.log_status_info(f"Done loading {constant.name} to GPU")
+
+
+@KARABO_CLASSINFO("ManualDsscGeometry", deviceVersion)
+class ManualDsscGeometry(base_geometry.ManualQuadrantsGeometryBase):
+    def __init__(self, *args, **kwargs):
+        import extra_geom
+        self.geometry_class = extra_geom.DSSC_1MGeometry
+        super().__init__(*args, **kwargs)
+
+    @staticmethod
+    def expectedParameters(expected):
+        super(ManualDsscGeometry, ManualDsscGeometry).expectedParameters(expected)
+
+        expected.setDefaultValue("quadrantCorners.Q1.x", -130)
+        expected.setDefaultValue("quadrantCorners.Q1.y", 5)
+
+        expected.setDefaultValue("quadrantCorners.Q2.x", -130)
+        expected.setDefaultValue("quadrantCorners.Q2.y", -125)
+
+        expected.setDefaultValue("quadrantCorners.Q3.x", 5)
+        expected.setDefaultValue("quadrantCorners.Q3.y", -125)
+
+        expected.setDefaultValue("quadrantCorners.Q4.x", 5)
+        expected.setDefaultValue("quadrantCorners.Q4.y", 5)
diff --git a/src/calng/JungfrauCorrection.py b/src/calng/JungfrauCorrection.py
index 8caa81c6d88a03fe48e6e84a76e567c8acd23262..836da2849611565861cf50a4a1a694dc710a805e 100644
--- a/src/calng/JungfrauCorrection.py
+++ b/src/calng/JungfrauCorrection.py
@@ -9,9 +9,10 @@ from karabo.bound import (
     OVERWRITE_ELEMENT,
     STRING_ELEMENT,
     VECTOR_STRING_ELEMENT,
+    Hash,
 )
 
-from . import base_gpu, calcat_utils, utils
+from . import base_calcat, base_geometry, base_gpu, utils
 from ._version import version as deviceVersion
 from .base_correction import BaseCorrection, add_correction_step_schema, preview_schema
 
@@ -128,7 +129,7 @@ class JungfrauGpuRunner(base_gpu.BaseGpuRunner):
         )
 
 
-class JungfrauCalcatFriend(calcat_utils.BaseCalcatFriend):
+class JungfrauCalcatFriend(base_calcat.BaseCalcatFriend):
     _constant_enum_class = JungfrauConstants
 
     def __init__(self, device, *args, **kwargs):
@@ -221,12 +222,12 @@ class JungfrauCalcatFriend(calcat_utils.BaseCalcatFriend):
         managed_keys.add(f"{param_prefix}.gainSetting")
         managed_keys.add(f"{param_prefix}.gainMode")
 
-        calcat_utils.add_status_schema_from_enum(
+        base_calcat.add_status_schema_from_enum(
             schema, status_prefix, JungfrauConstants
         )
 
     def dark_condition(self):
-        res = calcat_utils.OperatingConditions()
+        res = base_calcat.OperatingConditions()
         res["Memory cells"] = self._get_param("memoryCells")
         res["Sensor Bias Voltage"] = self._get_param("biasVoltage")
         res["Pixels X"] = self._get_param("pixelsX")
@@ -414,3 +415,29 @@ class JungfrauCorrection(BaseCorrection):
 
         self._update_correction_flags()
         self.log_status_info(f"Done loading {constant.name} to GPU")
+
+
+@KARABO_CLASSINFO("ManualJungfrauGeometry", deviceVersion)
+class ManualJungfrauGeometry(base_geometry.ManualModulesGeometryBase):
+    def __init__(self, *args, **kwargs):
+        import extra_geom
+        self.geometry_class = extra_geom.JUNGFRAUGeometry
+        super().__init__(*args, **kwargs)
+
+    @staticmethod
+    def expectedParameters(expected):
+        # TODO: come up with some sweet defaults (this is two modules from docs 4M)
+        (
+            OVERWRITE_ELEMENT(expected)
+            .key("modules")
+            .setNewDefaultValue(
+                [
+                    Hash(
+                        "posX", 95, "posY", 564, "orientationX", -1, "orientationY", -1
+                    ),
+                    Hash(
+                        "posX", 95, "posY", 17, "orientationX", -1, "orientationY", -1
+                    ),
+                ]
+            )
+        )
diff --git a/src/calng/ManualAgipdGeometry.py b/src/calng/ManualAgipdGeometry.py
deleted file mode 100644
index 20428d6bdbfe38709305c6fc90820445e25e14f2..0000000000000000000000000000000000000000
--- a/src/calng/ManualAgipdGeometry.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import extra_geom
-from karabo.bound import KARABO_CLASSINFO
-
-from ._version import version as deviceVersion
-from .manual_geometry_base import ManualQuadrantsGeometryBase
-
-
-@KARABO_CLASSINFO("ManualAgipdGeometry", deviceVersion)
-class ManualAgipdGeometry(ManualQuadrantsGeometryBase):
-    geometry_class = extra_geom.AGIPD_1MGeometry
-
-    @staticmethod
-    def expectedParameters(expected):
-        super(ManualAgipdGeometry, ManualAgipdGeometry).expectedParameters(expected)
-
-        expected.setDefaultValue("quadrantCorners.Q1.x", -525)
-        expected.setDefaultValue("quadrantCorners.Q1.y", 625)
-
-        expected.setDefaultValue("quadrantCorners.Q2.x", -550)
-        expected.setDefaultValue("quadrantCorners.Q2.y", -10)
-
-        expected.setDefaultValue("quadrantCorners.Q3.x", 520)
-        expected.setDefaultValue("quadrantCorners.Q3.y", -160)
-
-        expected.setDefaultValue("quadrantCorners.Q4.x", 542.5)
-        expected.setDefaultValue("quadrantCorners.Q4.y", 475)
diff --git a/src/calng/ManualDsscGeometry.py b/src/calng/ManualDsscGeometry.py
deleted file mode 100644
index 5b3d9b2e4d2394bf67b78c7fed2cc084d384612f..0000000000000000000000000000000000000000
--- a/src/calng/ManualDsscGeometry.py
+++ /dev/null
@@ -1,26 +0,0 @@
-import extra_geom
-from karabo.bound import KARABO_CLASSINFO
-
-from ._version import version as deviceVersion
-from .manual_geometry_base import ManualQuadrantsGeometryBase
-
-
-@KARABO_CLASSINFO("ManualDsscGeometry", deviceVersion)
-class ManualDsscGeometry(ManualQuadrantsGeometryBase):
-    geometry_class = extra_geom.DSSC_1MGeometry
-
-    @staticmethod
-    def expectedParameters(expected):
-        super(ManualDsscGeometry, ManualDsscGeometry).expectedParameters(expected)
-
-        expected.setDefaultValue("quadrantCorners.Q1.x", -130)
-        expected.setDefaultValue("quadrantCorners.Q1.y", 5)
-
-        expected.setDefaultValue("quadrantCorners.Q2.x", -130)
-        expected.setDefaultValue("quadrantCorners.Q2.y", -125)
-
-        expected.setDefaultValue("quadrantCorners.Q3.x", 5)
-        expected.setDefaultValue("quadrantCorners.Q3.y", -125)
-
-        expected.setDefaultValue("quadrantCorners.Q4.x", 5)
-        expected.setDefaultValue("quadrantCorners.Q4.y", 5)
diff --git a/src/calng/ManualJungfrauGeometry.py b/src/calng/ManualJungfrauGeometry.py
deleted file mode 100644
index 57f7da914e77cb7aee28ffd078fe64c13231c259..0000000000000000000000000000000000000000
--- a/src/calng/ManualJungfrauGeometry.py
+++ /dev/null
@@ -1,28 +0,0 @@
-import extra_geom
-from karabo.bound import KARABO_CLASSINFO, OVERWRITE_ELEMENT, Hash
-
-from ._version import version as deviceVersion
-from .manual_geometry_base import ManualModulesGeometryBase
-
-
-@KARABO_CLASSINFO("ManualJungfrauGeometry", deviceVersion)
-class ManualJungfrauGeometry(ManualModulesGeometryBase):
-    geometry_class = extra_geom.JUNGFRAUGeometry
-
-    @staticmethod
-    def expectedParameters(expected):
-        # TODO: come up with some sweet defaults (this is two modules from docs 4M)
-        (
-            OVERWRITE_ELEMENT(expected)
-            .key("modules")
-            .setNewDefaultValue(
-                [
-                    Hash(
-                        "posX", 95, "posY", 564, "orientationX", -1, "orientationY", -1
-                    ),
-                    Hash(
-                        "posX", 95, "posY", 17, "orientationX", -1, "orientationY", -1
-                    ),
-                ]
-            )
-        )
diff --git a/src/calng/ModuleStacker.py b/src/calng/ModuleStacker.py
deleted file mode 100644
index 95abe95ee79f05007fffe98bb4c73b1fad6c6f08..0000000000000000000000000000000000000000
--- a/src/calng/ModuleStacker.py
+++ /dev/null
@@ -1,142 +0,0 @@
-import numpy as np
-from karabo.bound import (
-    FLOAT_ELEMENT,
-    KARABO_CLASSINFO,
-    NODE_ELEMENT,
-    STRING_ELEMENT,
-    ChannelMetaData,
-    Epochstamp,
-    Hash,
-    MetricPrefix,
-    Schema,
-    Timestamp,
-    Trainstamp,
-    Unit,
-)
-from TrainMatcher import TrainMatcher
-
-from ._version import version as deviceVersion
-
-
-@KARABO_CLASSINFO("ModuleStacker", deviceVersion)
-class ModuleStacker(TrainMatcher.TrainMatcher):
-    """This will be deprecated: now just equivalent to ModuleMatcher except this
-    stacks `image.data` instead of `data.adc`
-
-    """
-
-    def __init__(self, conf):
-        super().__init__(conf)
-        self.info.merge(Hash("timeOfFlight", 0))
-
-    @staticmethod
-    def expectedParameters(expected):
-        (
-            FLOAT_ELEMENT(expected)
-            .key("timeOfFlight")
-            .displayedName("Time of flight")
-            .description(
-                "Time elapsed from DAQ sent data until train was matched and ready to "
-                "send from here. Measured for latest train matched. Maximum over all "
-                "sources included in said train."
-            )
-            .unit(Unit.SECOND)
-            .metricPrefix(MetricPrefix.MILLI)
-            .readOnly()
-            .commit(),
-
-            STRING_ELEMENT(expected)
-            .key("pathToStack")
-            .displayedName("Data path to stack")
-            .description(
-                "Typically, image.data will be used for full data going through the "
-                "pipeline. Set this when input is dataOutput from a correction device "
-                "and output goes to a bridge. For previews, data.adc is used as part "
-                "of the combiner format. Set to data.adc when input is a preview "
-                "output and output goes to a femDataAssembler."
-            )
-            .options("image.data,data.adc")
-            .assignmentOptional()
-            .defaultValue("image.data")
-            .commit(),
-        )
-
-    def initialization(self):
-        """Apply configuration and automatically start.
-
-        Upon instantiation, the device will automatically start matching data
-        from the specified data sources.
-        """
-        super().initialization()
-
-        # Disable the start and stop slots.
-        # It's not possible to pop items from the full schema. The slots are
-        # therefore converted to unused nodes.
-        desc = (
-            "Disable slots from the parent class. The acquisition start automatically "
-            "on instantiation. Check that the `fastSources` table is populated and "
-            "its booleans set to True the project configuration (not instantiated). "
-            "These nodes are not used."
-        )
-        schema = Schema()
-        (
-            NODE_ELEMENT(schema).key("start").description(desc).commit(),
-
-            NODE_ELEMENT(schema).key("stop").description(desc).commit(),
-        )
-        self.path_to_stack = self.get("pathToStack")
-        self.updateSchema(schema)
-
-        super().start()
-
-    def _send(self, tid, sources):
-        # Add control data
-        timestamp = Timestamp(Epochstamp(), Trainstamp(tid))
-
-        # Reuse arbitrary hash from existing ones (among the ones to stack)
-        try:
-            out_hash = next(
-                data
-                for (data, _) in iter(sources.values())
-                if data.has(self.path_to_stack)
-            )
-        except StopIteration:
-            out_hash = Hash()
-
-        # TODO: handle missing modules properly (track all sources)
-        stacked_data = []
-        stacked_sources = []
-        stacked_present = []
-        # TODO: should this be threaded?
-        time_of_flight = 0
-        for source, (data, metadata) in sources.items():
-            if not data.has(self.path_to_stack):
-                # may add sources not for stacking
-                # TODO: make stack or no part of source configuration
-                out_hash[f"unstacked.{source}"] = data
-                continue
-            old_ts = metadata.getTimestamp()
-            elapsed = timestamp.toTimestamp() - old_ts.toTimestamp()
-            time_of_flight = max(time_of_flight, elapsed)
-            image_data = data.get(self.path_to_stack)
-            stacked_data.append(image_data)
-            stacked_sources.append(source)
-            stacked_present.append(True)
-
-        for source, data in self.ctrlmon.get(tid):
-            out_hash[f"unstacked.{source}"] = data
-
-        if stacked_data:
-            if not isinstance(stacked_data[0], str):
-                # strings (like shmem handles) should stay list
-                stacked_data = np.stack(stacked_data, axis=0)
-            # TODO: merge with super().update_info (throttled updates)
-            self.info["timeOfFlight"] = time_of_flight * 1000
-
-        out_hash[self.path_to_stack] = stacked_data
-        out_hash["sources"] = stacked_sources
-        out_hash["modulesPresent"] = stacked_present
-        channel = self.signalSlotable.getOutputChannel("output")
-        channel.write(out_hash, ChannelMetaData(self.getInstanceId(), timestamp))
-        channel.update()
-        self.rate_out.update()
diff --git a/src/calng/calcat_utils.py b/src/calng/base_calcat.py
similarity index 96%
rename from src/calng/calcat_utils.py
rename to src/calng/base_calcat.py
index 76b27adf0d18e3129daf5e331bd5492caef59ce1..9e2963113b487cd312ae407d7cfece0cabe3408f 100644
--- a/src/calng/calcat_utils.py
+++ b/src/calng/base_calcat.py
@@ -24,8 +24,6 @@ from karabo.bound import (
     UINT32_ELEMENT,
     VECTOR_UINT32_ELEMENT,
 )
-from karabo import version as karaboVersion
-from pkg_resources import parse_version
 
 from . import utils
 
@@ -98,14 +96,12 @@ def add_status_schema_from_enum(schema, prefix, enum_class):
             .defaultValue("")
             .reconfigurable()
             .commit(),
+
+            SLOT_ELEMENT(schema)
+            .key(f"{constant_node}.overrideConstantVersion")
+            .displayedName("Override constant version")
+            .commit(),
         )
-        if parse_version(karaboVersion) >= parse_version("2.11"):
-            (
-                SLOT_ELEMENT(schema)
-                .key(f"{constant_node}.overrideConstantVersion")
-                .displayedName("Override constant version")
-                .commit(),
-            )
 
 
 class OperatingConditions(dict):
@@ -343,9 +339,7 @@ class BaseCalcatFriend:
         """Helper to update information about found constants on device"""
         self.device.set(f"{self.status_prefix}.{constant.name}.{key}", value)
 
-    # Python 3.6 does not have functools.cached_property or even functools.cache
-    @property
-    @functools.lru_cache()
+    @functools.cached_property
     def detector_id(self):
         detector_name = self._get_param("detectorName")
         resp = Detector.get_by_identifier(self.client, detector_name)
@@ -354,8 +348,7 @@ class BaseCalcatFriend:
         self._set_param("detectorId", str(res))
         return res
 
-    @property
-    @functools.lru_cache()
+    @functools.cached_property
     def detector_type_id(self):
         detector_type = self._get_param("detectorType")
         resp = DetectorType.get_by_name(self.client, detector_type)
@@ -366,8 +359,7 @@ class BaseCalcatFriend:
         self._set_param("detectorTypeId", str(res))
         return res
 
-    @property
-    @functools.lru_cache()
+    @functools.cached_property
     def pdus(self):
         resp = PhysicalDetectorUnit.get_all_by_detector(
             self.client, self.detector_id, self._get_param("deviceMappingSnapshotAt")
@@ -378,13 +370,11 @@ class BaseCalcatFriend:
                 del pdu[irrelevant_key]
         return resp["data"]
 
-    @property
-    @functools.lru_cache()
+    @functools.cached_property
     def _karabo_da_to_float_uuid(self):
         return {pdu["karabo_da"]: pdu["float_uuid"] for pdu in self.pdus}
 
-    @property
-    @functools.lru_cache()
+    @functools.cached_property
     def _karabo_da_to_id(self):
         return {pdu["karabo_da"]: pdu["id"] for pdu in self.pdus}
 
diff --git a/src/calng/base_correction.py b/src/calng/base_correction.py
index 9a18a0186246ba81eaf2474eb3884dd32ea8e8d4..8de51c95a2ee069446f86fd926cee7732cee92ac 100644
--- a/src/calng/base_correction.py
+++ b/src/calng/base_correction.py
@@ -33,8 +33,6 @@ from karabo.bound import (
     Unit,
 )
 from karabo.common.api import KARABO_SCHEMA_DISPLAY_TYPE_SCENES as DT_SCENES
-from karabo import version as karaboVersion
-from pkg_resources import parse_version
 
 from . import scenes, shmem_utils, utils
 from ._version import version as deviceVersion
@@ -614,25 +612,24 @@ class BaseCorrection(PythonDevice):
         self._last_processing_started = 0  # used for processing time and timeout
 
         # register slots
-        if parse_version(karaboVersion) >= parse_version("2.11"):
-            # TODO: the CalCatFriend could add these for us
-            # note: overly complicated for closure to work
-            def make_wrapper_capturing_constant(constant):
-                def aux():
-                    self.calcat_friend.get_specific_constant_version_and_call_me_back(
-                        constant, self._load_constant_to_runner
-                    )
-
-                return aux
-
-            for constant in self._constant_enum_class:
-                slot_name = f"foundConstants.{constant.name}.overrideConstantVersion"
-                meth_name = slot_name.replace(".", "_")
-                self.KARABO_SLOT(
-                    make_wrapper_capturing_constant(constant),
-                    slotName=meth_name,
+        # TODO: the CalCatFriend could add these for us
+        # note: overly complicated for closure to work
+        def make_wrapper_capturing_constant(constant):
+            def aux():
+                self.calcat_friend.get_specific_constant_version_and_call_me_back(
+                    constant, self._load_constant_to_runner
                 )
 
+            return aux
+
+        for constant in self._constant_enum_class:
+            slot_name = f"foundConstants.{constant.name}.overrideConstantVersion"
+            meth_name = slot_name.replace(".", "_")
+            self.KARABO_SLOT(
+                make_wrapper_capturing_constant(constant),
+                slotName=meth_name,
+            )
+
         self.KARABO_SLOT(self.loadMostRecentConstants)
         self.KARABO_SLOT(self.requestScene)
 
diff --git a/src/calng/manual_geometry_base.py b/src/calng/base_geometry.py
similarity index 100%
rename from src/calng/manual_geometry_base.py
rename to src/calng/base_geometry.py