From 4d9ddc69ad157221f6c5c85183b0c9cfa5502347 Mon Sep 17 00:00:00 2001
From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch>
Date: Wed, 6 Mar 2024 03:23:12 +0100
Subject: [PATCH] Fix typo in PhysVolSorter & add more athena tests

---
 .../GeoModelHelpers/GeoDeDuplicator.h         |  10 +
 .../GeoModelHelpers/src/GeoDeDuplicator.cxx   |  33 +-
 .../GeoModelHelpers/src/GeoPhysVolSorter.cxx  |   8 +-
 .../GeoModelHelpers/src/TransformSorter.cxx   |   5 +
 .../tests/testPhysVolSorter.cxx               |  99 ++++
 .../tests/testTransformSorter.cxx             |  28 ++
 .../GeoModelKernel/src/GeoDefinitions.cxx     |   2 +-
 .../GeoModelKernel/src/GeoShapeShift.cxx      |   2 +-
 .../GeoModelXml/Element2ShapeItem.h           |  23 +
 .../GeoModelXml/GeoModelXml/LogvolProcessor.h |   2 +
 .../GeoModelXml/MulticopyProcessor.h          |   1 +
 .../GeoModelXml/ReplicaRPhiProcessor.h        |   6 +-
 .../GeoModelXml/ReplicaXProcessor.h           |   4 +-
 .../GeoModelXml/ReplicaXYArraysProcessor.h    |   3 +-
 .../GeoModelXml/ReplicaYProcessor.h           |   2 +-
 .../GeoModelXml/ReplicaZProcessor.h           |   2 +-
 .../GeoModelXml/GeoModelXml/shape/MakeBox.h   |   4 +-
 .../GeoModelXml/GeoModelXml/shape/MakeCons.h  |   4 +-
 .../GeoModelXml/shape/MakeEllipticalTube.h    |   4 +-
 .../GeoModelXml/shape/MakeGenericTrap.h       |   4 +-
 .../GeoModelXml/shape/MakeIntersection.h      |   4 +-
 .../GeoModelXml/GeoModelXml/shape/MakePara.h  |   4 +-
 .../GeoModelXml/GeoModelXml/shape/MakePcon.h  |   5 +-
 .../GeoModelXml/GeoModelXml/shape/MakePgon.h  |   4 +-
 .../GeoModelXml/shape/MakeShaperef.h          |   6 +-
 .../GeoModelXml/shape/MakeSimplePolygonBrep.h |   4 +-
 .../GeoModelXml/shape/MakeSubtraction.h       |   4 +-
 .../GeoModelXml/GeoModelXml/shape/MakeTorus.h |   6 +-
 .../GeoModelXml/GeoModelXml/shape/MakeTrap.h  |   6 +-
 .../GeoModelXml/GeoModelXml/shape/MakeTrd.h   |   6 +-
 .../GeoModelXml/GeoModelXml/shape/MakeTube.h  |   4 +-
 .../GeoModelXml/GeoModelXml/shape/MakeTubs.h  |   6 +-
 .../GeoModelXml/shape/MakeTwistedTrap.h       |   6 +-
 .../GeoModelXml/GeoModelXml/shape/MakeUnion.h |   4 +-
 .../GeoModelXml/src/Element2ShapeItem.cxx     |  29 ++
 .../GeoModelXml/src/LogvolProcessor.cxx       |   6 +-
 .../GeoModelXml/src/MakeTransformation.cxx    |   4 +-
 .../GeoModelXml/src/MulticopyProcessor.cxx    |   3 +
 .../GeoModelXml/src/ReplicaRPhiProcessor.cxx  |  31 +-
 .../GeoModelXml/src/ReplicaXProcessor.cxx     |  33 +-
 .../GeoModelXml/src/ReplicaXYArrays.cxx       |   3 +
 .../GeoModelXml/src/ReplicaYProcessor.cxx     |  37 +-
 .../GeoModelXml/src/ReplicaZProcessor.cxx     |  28 +-
 .../GeoModelXMLParser/CMakeLists.txt          |   2 +
 .../GeoModelXMLParser/XMLHandler.h            |   1 -
 .../GeoModelXMLParser/src/XMLHandler.cxx      | 430 ++++++++----------
 athena_ci/apply_patches.sh                    |   2 +
 athena_ci/athena_build.sh                     |  20 +-
 athena_ci/ci.yml                              | 102 ++++-
 athena_ci/package_filters.txt                 |   1 -
 athena_ci/patch_package_filters.txt           |   6 +
 .../patches/0001-Swap-rotation-signs.patch    | 144 ++++++
 athena_ci/patches/0001-Test-commit.patch      |  27 --
 ...ication-relic-to-fix-segfault-on-Alm.patch |  39 ++
 54 files changed, 847 insertions(+), 416 deletions(-)
 create mode 100644 GeoModelCore/GeoModelHelpers/tests/testPhysVolSorter.cxx
 create mode 100644 GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Element2ShapeItem.h
 create mode 100644 GeoModelTools/GeoModelXML/GeoModelXml/src/Element2ShapeItem.cxx
 create mode 100644 athena_ci/patch_package_filters.txt
 create mode 100644 athena_ci/patches/0001-Swap-rotation-signs.patch
 delete mode 100644 athena_ci/patches/0001-Test-commit.patch
 create mode 100644 athena_ci/patches/0002-Remove-the-QApplication-relic-to-fix-segfault-on-Alm.patch

diff --git a/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h b/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h
index 614bc6606..b34ca918c 100644
--- a/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h
+++ b/GeoModelCore/GeoModelHelpers/GeoModelHelpers/GeoDeDuplicator.h
@@ -78,13 +78,23 @@ class GeoDeDuplicator {
         GeoLogVolPtr cacheVolume(GeoLogVolPtr vol) const;
         GeoShapePtr cacheShape(GeoShapePtr shape) const;
 
+        void setShapeDeduplication(bool enable);
+        void setLogVolDeDuplication(bool enable);
+        void setTransformDeDuplication(bool enable);
+        void setPhysVolDeDuplication(bool enable);
+
     private:
+        bool m_deDuplicateLogVol{true};
+        bool m_deDuplicatePhysVol{true};
+        bool m_deDuplicateTransform{true};
+        bool m_deDuplicateShape{true};
         using PhysVolSet = std::set<GeoIntrusivePtr<GeoPhysVol>, GeoPhysVolSorter>;
         using LogVolSet = std::set<GeoLogVolPtr, GeoLogVolSorter>;
         using TrfSet = std::set<GeoTrfPtr, GeoTrf::TransformSorter>;
         using ShapeSet = std::set<GeoShapePtr, GeoShapeSorter>;
         mutable PhysVolSet m_physVolStore{};
         mutable LogVolSet m_logVolStore{};
+        mutable std::vector<GeoIntrusivePtr<const RCBase>> m_genericCache{};
 
         static TrfSet s_trfStore;
         static ShapeSet s_shapeStore;
diff --git a/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx b/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx
index 8ba6eab4a..d0ffee65c 100644
--- a/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx
+++ b/GeoModelCore/GeoModelHelpers/src/GeoDeDuplicator.cxx
@@ -8,19 +8,50 @@
 GeoDeDuplicator::TrfSet GeoDeDuplicator::s_trfStore{};
 GeoDeDuplicator::ShapeSet GeoDeDuplicator::s_shapeStore{};
 
+
+void GeoDeDuplicator::setShapeDeduplication(bool enable){
+    m_deDuplicateShape = enable;
+}
+void GeoDeDuplicator::setLogVolDeDuplication(bool enable) {
+    m_deDuplicateLogVol = enable;
+}
+void GeoDeDuplicator::setTransformDeDuplication(bool enable) {
+    m_deDuplicateTransform = enable;
+}
+void GeoDeDuplicator::setPhysVolDeDuplication(bool enable) {
+    m_deDuplicatePhysVol = enable;
+}
+
 GeoDeDuplicator::GeoTrfPtr 
     GeoDeDuplicator::makeTransform(const GeoTrf::Transform3D& trf) const {
-        return *s_trfStore.emplace(new GeoTransform(trf)).first;
+        GeoTrfPtr trfNode{new GeoTransform(trf)};
+        if (!m_deDuplicateTransform) {
+            m_genericCache.push_back(trfNode);
+            return trfNode;
+        }
+        return *s_trfStore.emplace(trfNode).first;
     }
 GeoDeDuplicator::GeoPhysVolPtr 
     GeoDeDuplicator::cacheVolume(GeoPhysVolPtr vol) const {
+        if (!m_deDuplicatePhysVol) {
+            m_genericCache.push_back(vol);
+            return vol;
+        }
         return *m_physVolStore.insert(vol).first;
     }
 GeoDeDuplicator::GeoLogVolPtr 
     GeoDeDuplicator::cacheVolume(GeoLogVolPtr vol) const {
+        if (!m_deDuplicateLogVol) {
+            m_genericCache.push_back(vol);
+            return vol;
+        }
         return *m_logVolStore.insert(vol).first;
     }
 GeoDeDuplicator::GeoShapePtr 
     GeoDeDuplicator::cacheShape(GeoShapePtr shape) const {
+        if (!m_deDuplicateShape) {
+            m_genericCache.push_back(shape);
+            return shape;
+        } 
         return *s_shapeStore.insert(shape).first;
     }
diff --git a/GeoModelCore/GeoModelHelpers/src/GeoPhysVolSorter.cxx b/GeoModelCore/GeoModelHelpers/src/GeoPhysVolSorter.cxx
index d5f72bd28..73ee5dc0f 100644
--- a/GeoModelCore/GeoModelHelpers/src/GeoPhysVolSorter.cxx
+++ b/GeoModelCore/GeoModelHelpers/src/GeoPhysVolSorter.cxx
@@ -8,13 +8,15 @@
 #include "GeoModelHelpers/GeoLogVolSorter.h"
 #include "GeoModelKernel/GeoVolumeCursor.h"
 #include "GeoModelHelpers/getChildNodesWithTrf.h"
+#include "GeoModelHelpers/throwExcept.h"
+
 
 int GeoPhysVolSorter::compare(const GeoVPhysVol* a, const GeoVPhysVol* b) const {
     /// If one of the given volumes is a full physical volume, let's assume that they've been
     /// put on purpose into the node. Ensure that they're added to the set eventhough they
     /// are equivalent in the terms of this sorter.
     if (typeid(*a) == typeid(GeoFullPhysVol) || typeid(*b) == typeid(GeoFullPhysVol)) {
-        return a < b;
+        return a == b ? 0 : (a < b ? -1 : 1);
     }
     
     /// A check on different logical volumes is already a good start
@@ -35,11 +37,11 @@ int GeoPhysVolSorter::compare(const GeoVPhysVol* a, const GeoVPhysVol* b) const
         cursB.next();
         /// Check whether there's an alignable transform somewhere
         if (childA.isAlignable != childB.isAlignable) {
-            return childA.isAlignable;
+            return childA.isAlignable ? -1 : 1;
         }
         /// Check whether the voumes are full physical volumes
         if (childA.isSensitive != childB.isSensitive) {
-            return childA.isSensitive;
+            return childA.isSensitive ? -1 : 1;
         }
         /// Check equivalance of the transformations
         const int transCmp = sorter.compare(childA.transform,
diff --git a/GeoModelCore/GeoModelHelpers/src/TransformSorter.cxx b/GeoModelCore/GeoModelHelpers/src/TransformSorter.cxx
index 59567fc3c..bf77383bf 100644
--- a/GeoModelCore/GeoModelHelpers/src/TransformSorter.cxx
+++ b/GeoModelCore/GeoModelHelpers/src/TransformSorter.cxx
@@ -2,6 +2,7 @@
   Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 #include "GeoModelHelpers/TransformSorter.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
 #include "GeoModelHelpers/throwExcept.h"
 
 namespace GeoTrf {
@@ -41,6 +42,10 @@ namespace GeoTrf {
         if (!a || !b) {
             THROW_EXCEPTION("Nullptr given to comparator");
         }
+        if (typeid(*a) == typeid(GeoAlignableTransform) ||
+            typeid(*b) == typeid(GeoAlignableTransform)) {
+            return a < b;
+        }
         return (*this)(a->getTransform(), b->getTransform());
     }
 }
\ No newline at end of file
diff --git a/GeoModelCore/GeoModelHelpers/tests/testPhysVolSorter.cxx b/GeoModelCore/GeoModelHelpers/tests/testPhysVolSorter.cxx
new file mode 100644
index 000000000..e1d8cf03f
--- /dev/null
+++ b/GeoModelCore/GeoModelHelpers/tests/testPhysVolSorter.cxx
@@ -0,0 +1,99 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "GeoModelHelpers/GeoPhysVolSorter.h"
+#include "GeoModelHelpers/defineWorld.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
+#include "GeoModelHelpers/TransformToStringConverter.h"
+#include "GeoModelKernel/GeoFullPhysVol.h"
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/Units.h"
+#include <stdlib.h>
+#include <iostream>
+#include <set>
+
+
+int main() {
+    std::set<PVLink, GeoPhysVolSorter> physVolSet{};
+
+    GeoIntrusivePtr<GeoPhysVol> world{createGeoWorld()};
+
+    const GeoMaterial* air = world->getLogVol()->getMaterial();
+    GeoIntrusivePtr<GeoBox> externalBox{new GeoBox(500.,500., 500.)};
+    GeoIntrusivePtr<GeoBox> internalBox{new GeoBox(100.,100., 100.)};
+    auto  makeBox = [&](bool bigOne) {
+        return PVLink(new GeoPhysVol(new GeoLogVol("TestVolume", bigOne ? externalBox : internalBox, air)));
+    };
+
+    auto makeFullBox = [&](bool bigOne) {
+        return PVLink(new GeoFullPhysVol(new GeoLogVol("TestFullPhysVol", bigOne ? externalBox : internalBox, air)));
+    };
+    /// 
+    PVLink extVolume = makeBox(true);
+    extVolume->add(makeBox(false));
+
+    if (!physVolSet.insert(extVolume).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" Cannot insert the box into the empty set "<<std::endl;
+        return EXIT_FAILURE;
+    }
+    if (!physVolSet.insert(makeBox(true)).second){
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" Cannot inssert the empty big box "<<std::endl;
+        return EXIT_FAILURE;
+    }
+    if (!physVolSet.insert(makeBox(false)).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" Cannot inssert the empty small box "<<std::endl;
+        return EXIT_FAILURE;
+    }
+
+    /// Test whether a box with a subbox cannot be added
+    extVolume = makeBox(true);
+    extVolume->add(makeBox(false));
+    if (physVolSet.insert(extVolume).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" PhysVols can be shared. "<<std::endl;
+        return EXIT_FAILURE;
+    }
+    extVolume = makeBox(true);
+    extVolume->add(new GeoTransform(GeoTrf::TranslateX3D(50.)));
+    extVolume->add(makeBox(false));
+    if (!physVolSet.insert(extVolume).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" A box with a displaced box inside is not the same as box ception "<<std::endl;
+        return EXIT_FAILURE;
+    }
+    /// Test the full physical volumes
+
+    if (!physVolSet.insert(makeFullBox(true)).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" Full physical volume should be always added. "<<std::endl;
+        return EXIT_FAILURE;
+    }
+    if (!physVolSet.insert(makeFullBox(true)).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" Full physical volume should be always added. "<<std::endl;
+        return EXIT_FAILURE;
+    }
+    if (!physVolSet.insert(makeFullBox(false)).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" Full physical volume should be always added. "<<std::endl;
+        return EXIT_FAILURE;
+    }
+    if (!physVolSet.insert(makeFullBox(false)).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" Full physical volume should be always added. "<<std::endl;
+        return EXIT_FAILURE;
+    }
+
+    extVolume = makeBox(true);
+    extVolume->add(makeFullBox(false));    
+    if (!physVolSet.insert(extVolume).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" A box with a full physical volume inside should be always added "<<std::endl;
+        return EXIT_FAILURE;
+    }
+    
+    extVolume = makeFullBox(true);
+    extVolume->add(makeFullBox(false));    
+    if (!physVolSet.insert(extVolume).second) {
+        std::cerr<<"testPhysVolSorter() "<<__LINE__<<" A box with a full physical volume inside should be always added "<<std::endl;
+        return EXIT_FAILURE;
+    }
+
+
+
+    return EXIT_SUCCESS;
+}
\ No newline at end of file
diff --git a/GeoModelCore/GeoModelHelpers/tests/testTransformSorter.cxx b/GeoModelCore/GeoModelHelpers/tests/testTransformSorter.cxx
index d82df41a7..064b6d4fb 100644
--- a/GeoModelCore/GeoModelHelpers/tests/testTransformSorter.cxx
+++ b/GeoModelCore/GeoModelHelpers/tests/testTransformSorter.cxx
@@ -3,10 +3,12 @@
 */
 
 #include "GeoModelHelpers/TransformSorter.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
 #include "GeoModelHelpers/TransformToStringConverter.h"
 #include "GeoModelKernel/Units.h"
 #include <stdlib.h>
 #include <iostream>
+#include <set>
 
 std::ostream& operator<<(std::ostream& ostr, const GeoTrf::Transform3D& trans) {
     ostr<<GeoTrf::toString(trans, true, 2);
@@ -56,6 +58,32 @@ int main() {
     TEST_TRANSFORM(transC)
     COMPARE_SORTER(transA, transC);
     COMPARE_SORTER(transB, transC);
+
+    std::set<GeoIntrusivePtr<GeoTransform>, GeoTrf::TransformSorter> geoTrfCache{};
+    {
+        GeoIntrusivePtr<GeoTransform> geoTransC{new GeoTransform(transC)};
+        if (!geoTrfCache.insert(geoTransC).second) {
+            std::cerr<<"testTransformSorter() "<<__LINE__<<" Failed to insert transform into empty set"<<std::endl;
+            return EXIT_FAILURE;
+        }
+        geoTransC.reset(new GeoTransform(transC));
+        if (geoTrfCache.insert(geoTransC).second) {
+            std::cerr<<"testTransformSorter() "<<__LINE__<<" The same transform should always point to the same object."<<std::endl;
+            return EXIT_FAILURE;
+        }
+        geoTransC.reset(new GeoAlignableTransform(transC));
+        if (!geoTrfCache.insert(geoTransC).second) {
+            std::cerr<<"testTransformSorter() "<<__LINE__<<" Alignable transforms should be never deduplicated."<<std::endl;
+            return EXIT_FAILURE;
+        }
+
+        geoTransC.reset(new GeoAlignableTransform(transC));
+        if (!geoTrfCache.insert(geoTransC).second) {
+            std::cerr<<"testTransformSorter() "<<__LINE__<<" Alignable transforms should be never deduplicated."<<std::endl;
+            return EXIT_FAILURE;
+        }
+
+    }
    
     return EXIT_SUCCESS;
 }
\ No newline at end of file
diff --git a/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx b/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx
index 4c55243d0..79dd1b7a0 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoDefinitions.cxx
@@ -23,7 +23,7 @@ namespace GeoTrf {
 
   GeoRotation::GeoRotation(double phi, double theta, double psi):
       GeoRotation{EulerAngles{phi, theta, psi}} {}
- 
+
   GeoRotation::GeoRotation(const EulerAngles& angles):
       RotationMatrix3D{get3DRotMatZ(angles.phi) * 
                        get3DRotMatX(angles.theta) *
diff --git a/GeoModelCore/GeoModelKernel/src/GeoShapeShift.cxx b/GeoModelCore/GeoModelKernel/src/GeoShapeShift.cxx
index 037fa96fe..1a6072ca8 100755
--- a/GeoModelCore/GeoModelKernel/src/GeoShapeShift.cxx
+++ b/GeoModelCore/GeoModelKernel/src/GeoShapeShift.cxx
@@ -14,7 +14,7 @@ GeoShapeShift::GeoShapeShift (const GeoShape* A, const GeoTrf::Transform3D &X):
   m_op{A}, m_shift{X} {
     /// Check whether the given shape also a shape shift. If so then we can simply
     /// take the operand of the sub shift and summarize the transformations of the two into one
-   if (A->refCount() > 1 && A->typeID() == typeID()) {
+   if (false && A->refCount() > 1 && A->typeID() == typeID()) {
        const GeoShapeShift* subShift{dynamic_cast<const GeoShapeShift*>(A)};
        GeoTrf::Transform3D updatedShift = m_shift * subShift->getX();
        m_shift = std::move(updatedShift);
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Element2ShapeItem.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Element2ShapeItem.h
new file mode 100644
index 000000000..0d80503f6
--- /dev/null
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/Element2ShapeItem.h
@@ -0,0 +1,23 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef GEO_MODEL_XML_ELEMENT_2_SHAPEITEM_H
+#define GEO_MODEL_XML_ELEMENT_2_SHAPEITEM_H
+#include "GeoModelXml/Element2GeoItem.h"
+
+#include <set>
+class Element2ShapeItem: public Element2GeoItem {
+    public:
+        Element2ShapeItem();
+        
+        virtual ~Element2ShapeItem();
+
+        static void deduplicateShapes(const bool enable);
+
+    private:
+        static std::set<Element2ShapeItem*> s_instances;
+        static bool s_applyDepluication;
+};
+
+
+#endif
\ No newline at end of file
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/LogvolProcessor.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/LogvolProcessor.h
index 2b3277554..51a83dfd9 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/LogvolProcessor.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/LogvolProcessor.h
@@ -25,6 +25,8 @@ public:
     } ; 
     void process(const xercesc::DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd);
     void zeroId(const xercesc::DOMElement *element);
+
+    LogvolProcessor();
 private:
     std::map<std::string, LogVolStore> m_map; 
 };
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/MulticopyProcessor.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/MulticopyProcessor.h
index d52033f4e..2bd5d1db8 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/MulticopyProcessor.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/MulticopyProcessor.h
@@ -16,6 +16,7 @@ class GmxUtil;
 
 class MulticopyProcessor: public ElementProcessor {
 public:
+    MulticopyProcessor();
     void process(const xercesc::DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd);
 private:
     std::map <std::string, GeoNodeList> m_map; 
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaRPhiProcessor.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaRPhiProcessor.h
index c73e0a54d..189dd9eab 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaRPhiProcessor.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaRPhiProcessor.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef GEO_MODEL_XML_REPLICARPHI_PROCESSOR_H
@@ -16,10 +16,10 @@ class GmxUtil;
 
 class ReplicaRPhiProcessor: public ElementProcessor {
 public:
+    ReplicaRPhiProcessor();
     void process(const xercesc::DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd);
 private:
-    std::map <std::string, GeoNodeList> m_map; 
-    void tokenize(std::string&,char,std::vector<std::string>&) const ;
+    std::map <std::string, GeoNodeList> m_map{}; 
 };
 
 #endif // REPLICAX_PROCESSOR_H
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaXProcessor.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaXProcessor.h
index 79820ca31..d1698e52a 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaXProcessor.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaXProcessor.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef GEO_MODEL_XML_REPLICAX_PROCESSOR_H
@@ -16,10 +16,10 @@ class GmxUtil;
 
 class ReplicaXProcessor: public ElementProcessor {
 public:
+    ReplicaXProcessor();
     void process(const xercesc::DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd);
 private:
     std::map <std::string, GeoNodeList> m_map; 
-    void tokenize(std::string&,char,std::vector<std::string>&) const ;
 };
 
 #endif // REPLICAX_PROCESSOR_H
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaXYArraysProcessor.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaXYArraysProcessor.h
index 7d53e4028..e57ef6945 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaXYArraysProcessor.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaXYArraysProcessor.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef GEO_MODEL_XML_REPLICAXYARRAYS_PROCESSOR_H
@@ -16,6 +16,7 @@ class GmxUtil;
 
 class ReplicaXYarraysProcessor: public ElementProcessor {
 public:
+    ReplicaXYarraysProcessor();
     void process(const xercesc::DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd);
 private:
     std::map <std::string, GeoNodeList> m_map; 
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaYProcessor.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaYProcessor.h
index 362ce7fa7..3bb68619c 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaYProcessor.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaYProcessor.h
@@ -16,10 +16,10 @@ class GmxUtil;
 
 class ReplicaYProcessor: public ElementProcessor {
 public:
+    ReplicaYProcessor();
     void process(const xercesc::DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd);
 private:
     std::map <std::string, GeoNodeList> m_map; 
-    void tokenize(std::string&,char,std::vector<std::string>&) const ;
 };
 
 #endif // REPLICAY_PROCESSOR_H
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaZProcessor.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaZProcessor.h
index 98096ca9e..02b8ca8b9 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaZProcessor.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/ReplicaZProcessor.h
@@ -16,10 +16,10 @@ class GmxUtil;
 
 class ReplicaZProcessor: public ElementProcessor {
 public:
+    ReplicaZProcessor();
     void process(const xercesc::DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd);
 private:
     std::map <std::string, GeoNodeList> m_map; 
-    void tokenize(std::string&,char,std::vector<std::string>&) const ;
 };
 
 #endif // REPLICAX_PROCESSOR_H
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeBox.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeBox.h
index 220b875c6..e89272085 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeBox.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeBox.h
@@ -10,10 +10,10 @@
 #define GEO_MODEL_XML_MAKE_BOX_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 #include "GeoModelKernel/GeoBox.h"
-class MakeBox: public Element2GeoItem {
+class MakeBox: public Element2ShapeItem {
 public:
     MakeBox() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeCons.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeCons.h
index 7fb7d0ebf..b02df79df 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeCons.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeCons.h
@@ -10,9 +10,9 @@
 #define GEO_MODEL_XML_MAKE_CONS_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
-class MakeCons: public Element2GeoItem {
+class MakeCons: public Element2ShapeItem {
   public:
       MakeCons() = default;
       virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeEllipticalTube.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeEllipticalTube.h
index 9609bc2e8..1cb4c1cd2 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeEllipticalTube.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeEllipticalTube.h
@@ -6,9 +6,9 @@
 #define GEO_MODEL_XML_MAKE_ELLIPTICAL_TUBE_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
-class MakeEllipticalTube: public Element2GeoItem {
+class MakeEllipticalTube: public Element2ShapeItem {
 public:
     MakeEllipticalTube() = default;;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeGenericTrap.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeGenericTrap.h
index 4e33e9e08..abf19c9d3 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeGenericTrap.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeGenericTrap.h
@@ -10,10 +10,10 @@
 #define GEO_MODEL_XML_MAKE_GENERICTRAP_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 
-class MakeGenericTrap: public Element2GeoItem {
+class MakeGenericTrap: public Element2ShapeItem {
 public:
     MakeGenericTrap() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeIntersection.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeIntersection.h
index f3ebfdf3a..c3bacc088 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeIntersection.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeIntersection.h
@@ -10,10 +10,10 @@
 #define GEO_MODEL_XML_MAKE_INTERSECTION_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 
-class MakeIntersection: public Element2GeoItem {
+class MakeIntersection: public Element2ShapeItem {
 public:
     MakeIntersection() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePara.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePara.h
index 3cf210eb0..05f9436b2 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePara.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePara.h
@@ -10,9 +10,9 @@
 #define GEO_MODEL_XML_MAKE_PARA_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
-class MakePara: public Element2GeoItem {
+class MakePara: public Element2ShapeItem {
   public:
     MakePara() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePcon.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePcon.h
index 623383296..844f5161a 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePcon.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePcon.h
@@ -10,11 +10,10 @@
 #define GEO_MODEL_XML_MAKE_PCON_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 
-
-class MakePcon: public Element2GeoItem {
+class MakePcon: public Element2ShapeItem {
 public:
     MakePcon() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePgon.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePgon.h
index 2b36bb38a..ee8bee874 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePgon.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakePgon.h
@@ -10,10 +10,10 @@
 #define GEO_MODEL_XML_MAKE_PGON_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 
-class MakePgon: public Element2GeoItem {
+class MakePgon: public Element2ShapeItem {
   public:
       MakePgon() = default;
       virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeShaperef.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeShaperef.h
index 92be5c0da..7c5ee33db 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeShaperef.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeShaperef.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 //
@@ -10,9 +10,9 @@
 #define GEO_MODEL_XML_MAKE_SHAPEREF_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
-class MakeShaperef: public Element2GeoItem {
+class MakeShaperef: public Element2ShapeItem {
 public:
   RCBase * process(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const;
 };
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeSimplePolygonBrep.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeSimplePolygonBrep.h
index 9a4f2897b..81fad3a8d 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeSimplePolygonBrep.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeSimplePolygonBrep.h
@@ -9,9 +9,9 @@
 #define GEO_MODEL_XML_MAKE_SIMPLEPOLYGONBREP_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
-class MakeSimplePolygonBrep: public Element2GeoItem {
+class MakeSimplePolygonBrep: public Element2ShapeItem {
 public:
     MakeSimplePolygonBrep() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeSubtraction.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeSubtraction.h
index cb9ac7391..0f185db1e 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeSubtraction.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeSubtraction.h
@@ -10,10 +10,10 @@
 #define GEO_MODEL_XML_MAKE_SUBTRACTION_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 
-class MakeSubtraction: public Element2GeoItem {
+class MakeSubtraction: public Element2ShapeItem {
 public:
     MakeSubtraction() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTorus.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTorus.h
index 2425818b0..d78175d9f 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTorus.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTorus.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 // Jun 2021, Riccardo Maria BIANCHI <riccardo.maria.bianchi@cern.ch>
 //
@@ -7,10 +7,10 @@
 #define GEO_MODEL_XML_MAKE_TORUS_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 
-class MakeTorus: public Element2GeoItem {
+class MakeTorus: public Element2ShapeItem {
 public:
     MakeTorus() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTrap.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTrap.h
index 3c9d4435d..d307e96e2 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTrap.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTrap.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 //
@@ -10,9 +10,9 @@
 #define GEO_MODEL_XML_MAKE_TRAP_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
-class MakeTrap: public Element2GeoItem {
+class MakeTrap: public Element2ShapeItem {
 public:
     MakeTrap() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTrd.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTrd.h
index cf758804b..1ae5b1390 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTrd.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTrd.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 //
@@ -10,9 +10,9 @@
 #define GEO_MODEL_XML_MAKE_TRD_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
-class MakeTrd: public Element2GeoItem {
+class MakeTrd: public Element2ShapeItem {
 public:
     MakeTrd() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTube.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTube.h
index eebad477c..fe347e9f8 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTube.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTube.h
@@ -10,10 +10,10 @@
 #define GEO_MODEL_XML_MAKE_TUBE_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 
-class MakeTube: public Element2GeoItem {
+class MakeTube: public Element2ShapeItem {
 public:
     MakeTube() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTubs.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTubs.h
index 7d3520c18..595c45b08 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTubs.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTubs.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 //
@@ -10,10 +10,10 @@
 #define GEO_MODEL_XML_MAKE_TUBS_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 
-class MakeTubs: public Element2GeoItem {
+class MakeTubs: public Element2ShapeItem {
 public:
     MakeTubs() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTwistedTrap.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTwistedTrap.h
index 54a88ac91..4193ba496 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTwistedTrap.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeTwistedTrap.h
@@ -1,15 +1,15 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #ifndef GEO_MODEL_XML_MAKE_TWISTED_TRAP_H
 #define GEO_MODEL_XML_MAKE_TWISTED_TRAP_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
 
-class MakeTwistedTrap: public Element2GeoItem {
+class MakeTwistedTrap: public Element2ShapeItem {
 public:
     MakeTwistedTrap() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeUnion.h b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeUnion.h
index 2606df773..67fa1be6c 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeUnion.h
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/GeoModelXml/shape/MakeUnion.h
@@ -10,9 +10,9 @@
 #define GEO_MODEL_XML_MAKE_UNION_H
 #include <xercesc/util/XercesDefs.hpp>
 
-#include "GeoModelXml/Element2GeoItem.h"
+#include "GeoModelXml/Element2ShapeItem.h"
 
-class MakeUnion: public Element2GeoItem {
+class MakeUnion: public Element2ShapeItem {
 public:
     MakeUnion() = default;
     virtual RCBase * make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const override;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/Element2ShapeItem.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/Element2ShapeItem.cxx
new file mode 100644
index 000000000..9c9dabde3
--- /dev/null
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/Element2ShapeItem.cxx
@@ -0,0 +1,29 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+#include "GeoModelXml/Element2ShapeItem.h"
+#include <mutex>
+
+namespace{
+    std::mutex s_mutex{};
+}
+
+bool Element2ShapeItem::s_applyDepluication = false;
+std::set<Element2ShapeItem*> Element2ShapeItem::s_instances{};
+
+Element2ShapeItem::Element2ShapeItem() {
+    std::lock_guard guard{s_mutex};
+    s_instances.insert(this);
+    setShapeDeduplication(s_applyDepluication);
+}
+Element2ShapeItem::~Element2ShapeItem() {
+    std::lock_guard guard{s_mutex};
+    s_instances.erase(this);
+}
+void Element2ShapeItem::deduplicateShapes(const bool enable) {
+    std::lock_guard guard{s_mutex};
+    s_applyDepluication = enable;
+    for (Element2ShapeItem* item : s_instances) {
+        item->setShapeDeduplication(enable);
+    }
+}
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/LogvolProcessor.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/LogvolProcessor.cxx
index baa1f7394..500d96805 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/src/LogvolProcessor.cxx
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/LogvolProcessor.cxx
@@ -60,7 +60,11 @@ std::string getNodeType(const GeoGraphNode* node) {
         return "GeoTransform";
     return "UnidentifiedNode";
 }
-
+LogvolProcessor::LogvolProcessor() {
+    setLogVolDeDuplication(false);
+    setPhysVolDeDuplication(false);
+      
+}
 void LogvolProcessor::process(const DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd) {
   GeoLogVolPtr lv{};
   GeoNameTag *nameTag_physChildVolName;//USed for "sensitive" PhysVols 
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/MakeTransformation.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/MakeTransformation.cxx
index 200c1d7be..fa5fb46c8 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/src/MakeTransformation.cxx
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/MakeTransformation.cxx
@@ -16,7 +16,9 @@
 using namespace xercesc;
 using namespace std;
 
-MakeTransformation::MakeTransformation() {}
+MakeTransformation::MakeTransformation() {
+    setTransformDeDuplication(false);
+}
 
 RCBase * MakeTransformation::make(const xercesc::DOMElement *element, GmxUtil &gmxUtil) const {
 char *name2release;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/MulticopyProcessor.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/MulticopyProcessor.cxx
index c332ead28..192aedf83 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/src/MulticopyProcessor.cxx
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/MulticopyProcessor.cxx
@@ -41,6 +41,9 @@
 using namespace xercesc;
 using namespace std;
 
+MulticopyProcessor::MulticopyProcessor(){
+    setTransformDeDuplication(false);
+}
 void MulticopyProcessor::process(const DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd) {
 char *toRelease;
 XMLCh *ref = XMLString::transcode("ref");
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaRPhiProcessor.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaRPhiProcessor.cxx
index dc7601ee3..85ca13124 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaRPhiProcessor.cxx
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaRPhiProcessor.cxx
@@ -18,6 +18,7 @@
 #include "GeoModelKernel/GeoVFullPhysVol.h"
 #include "GeoModelKernel/GeoNameTag.h"
 #include "GeoModelKernel/GeoDefinitions.h"
+#include "GeoModelHelpers/StringUtils.h"
 
 #include "xercesc/util/XMLString.hpp"
 #include "GeoModelXml/GeoNodeList.h"
@@ -28,17 +29,8 @@
 using namespace xercesc;
 using namespace std;
 
-
-void ReplicaRPhiProcessor::tokenize(string &str, char delim, vector<string> &out) const
-{
-	size_t start;
-	size_t end = 0;
-
-	while ((start = str.find_first_not_of(delim, end)) != string::npos)
-	{
-		end = str.find(delim, start);
-		out.push_back(str.substr(start, end - start));
-	}
+ReplicaRPhiProcessor::ReplicaRPhiProcessor(){
+    setTransformDeDuplication(false);
 }
 
 void ReplicaRPhiProcessor::process(const DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd) {
@@ -107,18 +99,15 @@ DOMDocument *doc = element->getOwnerDocument();
     	toRelease = XMLString::transcode(element->getAttribute(skip_tmp));
 	std::string skip_str(toRelease);
 	//std::cout << "skip string "<<skip_str<<std::endl;
-	std::vector<std::string> parsed;
-	tokenize(skip_str,' ',parsed);
+	std::vector<std::string> parsed = GeoStrUtils::tokenize(skip_str," ");
 	for (auto k : parsed) 
 	{
-		std::vector<std::string> tmp_parsed;
-		//std::cout<<" parsed "<<k<<std::endl;
-		tokenize(k,'-',tmp_parsed);
-		if (tmp_parsed.size()==1) elementsToSkip.push_back(std::stoi(tmp_parsed[0]));
+		std::vector<std::string> tmp_parsed = GeoStrUtils::tokenize(k, "-");
+		if (tmp_parsed.size()==1) elementsToSkip.push_back(GeoStrUtils::atoi(tmp_parsed[0]));
 		else if (tmp_parsed.size()==2)
 		{
-			int i1=std::stoi(tmp_parsed[0]);
-			int i2=std::stoi(tmp_parsed[1]);
+			int i1=GeoStrUtils::atoi(tmp_parsed[0]);
+			int i2=GeoStrUtils::atoi(tmp_parsed[1]);
 			//std::cout<<" indices "<<i1<<" "<<i2<<std::endl;
 			assert(i1<i2);
 			for (int l=i1;l<i2+1;l++) elementsToSkip.push_back(l);
@@ -168,7 +157,9 @@ DOMDocument *doc = element->getOwnerDocument();
 	    double angle=offsetPhi;
             GeoTrf::Transform3D hepXf=hepXf0; 
             for (int i = 0; i < nCopies; ++i) {
-	    	hepXf=hepXf0*GeoTrf::TranslateX3D(radius*cos(angle))*GeoTrf::TranslateY3D(radius*sin(angle))*GeoTrf::RotateZ3D(angle);
+	    	    hepXf=hepXf0*GeoTrf::TranslateX3D(radius*std::cos(angle))*
+                             GeoTrf::TranslateY3D(radius*std::sin(angle))*
+                             GeoTrf::RotateZ3D(angle);
                 xfList->push_back(makeTransform(hepXf));
                 // hepXf = hepXf * GeoTrf::RotateZ3D(stepPhi) ;
 		angle+=stepPhi;
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaXProcessor.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaXProcessor.cxx
index 1f2845d9f..a904d524b 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaXProcessor.cxx
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaXProcessor.cxx
@@ -23,23 +23,14 @@
 #include "GeoModelXml/GeoNodeList.h"
 #include "GeoModelXml/ProcessorRegistry.h"
 #include "GeoModelXml/GmxUtil.h"
+#include "GeoModelHelpers/StringUtils.h"
 
 
 using namespace xercesc;
 using namespace std;
-
-void ReplicaXProcessor::tokenize(string &str, char delim, vector<string> &out) const
-{
-        size_t start;
-        size_t end = 0;
-
-        while ((start = str.find_first_not_of(delim, end)) != string::npos)
-        {
-                end = str.find(delim, start);
-                out.push_back(str.substr(start, end - start));
-        }
+ReplicaXProcessor::ReplicaXProcessor() {
+    setTransformDeDuplication(false);
 }
-
 void ReplicaXProcessor::process(const DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd) {
 char *toRelease;
 XMLCh *ref = XMLString::transcode("ref");
@@ -86,18 +77,15 @@ DOMDocument *doc = element->getOwnerDocument();
         toRelease = XMLString::transcode(element->getAttribute(skip_tmp));
         std::string skip_str(toRelease);
         //std::cout << "skip string "<<skip_str<<std::endl;
-        std::vector<std::string> parsed;
-        tokenize(skip_str,' ',parsed);
-        for (auto k : parsed)
-        {
-                std::vector<std::string> tmp_parsed;
+        std::vector<std::string> parsed = GeoStrUtils::tokenize(skip_str," ");
+        for (const std::string&  k : parsed) {
+                std::vector<std::string> tmp_parsed = GeoStrUtils::tokenize(k, "-");
                 //std::cout<<" parsed "<<k<<std::endl;
-                tokenize(k,'-',tmp_parsed);
-                if (tmp_parsed.size()==1) elementsToSkip.push_back(std::stoi(tmp_parsed[0]));
+                if (tmp_parsed.size()==1) elementsToSkip.push_back(GeoStrUtils::atoi(tmp_parsed[0]));
                 else if (tmp_parsed.size()==2)
                 {
-                        int i1=std::stoi(tmp_parsed[0]);
-                        int i2=std::stoi(tmp_parsed[1]);
+                        int i1=GeoStrUtils::atoi(tmp_parsed[0]);
+                        int i2=GeoStrUtils::atoi(tmp_parsed[1]);
                         //std::cout<<" indices "<<i1<<" "<<i2<<std::endl;
                         assert(i1<i2);
                         for (int l=i1;l<i2+1;l++) elementsToSkip.push_back(l);
@@ -139,8 +127,7 @@ DOMDocument *doc = element->getOwnerDocument();
             if (alignable) {
                 geoAXf = new GeoAlignableTransform (hepXf0) ;
                 hepXf0 = geoAXf->getTransform();
-            }
-            else {
+            } else {
                 geoXf = makeTransform (hepXf0);
                 hepXf0 = geoXf->getTransform();
             }
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaXYArrays.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaXYArrays.cxx
index 7918f27fe..d4dff151b 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaXYArrays.cxx
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaXYArrays.cxx
@@ -28,6 +28,9 @@
 using namespace xercesc;
 using namespace std;
 
+ReplicaXYarraysProcessor::ReplicaXYarraysProcessor(){
+    setTransformDeDuplication(false);
+}
 void ReplicaXYarraysProcessor::process(const DOMElement *element, GmxUtil &gmxUtil, GeoNodeList &toAdd) {
 char *toRelease;
 XMLCh *ref = XMLString::transcode("ref");
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaYProcessor.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaYProcessor.cxx
index 1004de4b2..ee38fbfb9 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaYProcessor.cxx
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaYProcessor.cxx
@@ -1,16 +1,10 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
-//
-//   replicaY element processor.
-//
-
 #include "GeoModelXml/ReplicaYProcessor.h"
 
 #include "OutputDirector.h"
-#include <sstream>
-#include <string>
 #include <cstdlib>
 #include <xercesc/dom/DOM.hpp>
 #include "GeoModelKernel/GeoTransform.h"
@@ -18,6 +12,7 @@
 #include "GeoModelKernel/GeoVFullPhysVol.h"
 #include "GeoModelKernel/GeoNameTag.h"
 #include "GeoModelKernel/GeoDefinitions.h"
+#include "GeoModelHelpers/StringUtils.h"
 
 #include "xercesc/util/XMLString.hpp"
 #include "GeoModelXml/GeoNodeList.h"
@@ -28,16 +23,8 @@
 using namespace xercesc;
 using namespace std;
 
-void ReplicaYProcessor::tokenize(string &str, char delim, vector<string> &out) const
-{
-        size_t start;
-        size_t end = 0;
-
-        while ((start = str.find_first_not_of(delim, end)) != string::npos)
-        {
-                end = str.find(delim, start);
-                out.push_back(str.substr(start, end - start));
-        }
+ReplicaYProcessor::ReplicaYProcessor(){
+    setTransformDeDuplication(false);
 }
 
 
@@ -87,18 +74,14 @@ DOMDocument *doc = element->getOwnerDocument();
         toRelease = XMLString::transcode(element->getAttribute(skip_tmp));
         std::string skip_str(toRelease);
         //std::cout << "skip string "<<skip_str<<std::endl;
-        std::vector<std::string> parsed;
-        tokenize(skip_str,' ',parsed);
-        for (auto k : parsed)
-        {       
-                std::vector<std::string> tmp_parsed;
-                //std::cout<<" parsed "<<k<<std::endl;
-                tokenize(k,'-',tmp_parsed);
-                if (tmp_parsed.size()==1) elementsToSkip.push_back(std::stoi(tmp_parsed[0]));
+        std::vector<std::string> parsed = GeoStrUtils::tokenize(skip_str," ");
+        for (const std::string& k : parsed) {       
+                std::vector<std::string> tmp_parsed = GeoStrUtils::tokenize(k,"-");
+                if (tmp_parsed.size()==1) elementsToSkip.push_back(GeoStrUtils::atoi(tmp_parsed[0]));
                 else if (tmp_parsed.size()==2)
                 {       
-                        int i1=std::stoi(tmp_parsed[0]);
-                        int i2=std::stoi(tmp_parsed[1]);
+                        int i1=GeoStrUtils::atoi(tmp_parsed[0]);
+                        int i2=GeoStrUtils::atoi(tmp_parsed[1]);
                         //std::cout<<" indices "<<i1<<" "<<i2<<std::endl;
                         assert(i1<i2);
                         for (int l=i1;l<i2+1;l++) elementsToSkip.push_back(l);
diff --git a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaZProcessor.cxx b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaZProcessor.cxx
index b547f6e2e..7340f0eac 100644
--- a/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaZProcessor.cxx
+++ b/GeoModelTools/GeoModelXML/GeoModelXml/src/ReplicaZProcessor.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 //
@@ -18,6 +18,7 @@
 #include "GeoModelKernel/GeoVFullPhysVol.h"
 #include "GeoModelKernel/GeoNameTag.h"
 #include "GeoModelKernel/GeoDefinitions.h"
+#include "GeoModelHelpers/StringUtils.h"
 
 #include "xercesc/util/XMLString.hpp"
 #include "GeoModelXml/GeoNodeList.h"
@@ -25,19 +26,13 @@
 #include "GeoModelXml/GmxUtil.h"
 
 
+
 using namespace xercesc;
 using namespace std;
 
-void ReplicaZProcessor::tokenize(string &str, char delim, vector<string> &out) const
-{
-        size_t start;
-        size_t end = 0;
 
-        while ((start = str.find_first_not_of(delim, end)) != string::npos)
-        {
-                end = str.find(delim, start);
-                out.push_back(str.substr(start, end - start));
-        }
+ReplicaZProcessor::ReplicaZProcessor(){
+    setTransformDeDuplication(false);
 }
 
 
@@ -87,18 +82,15 @@ DOMDocument *doc = element->getOwnerDocument();
         toRelease = XMLString::transcode(element->getAttribute(skip_tmp));
         std::string skip_str(toRelease);
         //std::cout << "skip string "<<skip_str<<std::endl;
-        std::vector<std::string> parsed;
-        tokenize(skip_str,' ',parsed);
+        std::vector<std::string> parsed = GeoStrUtils::tokenize(skip_str," ");
         for (auto k : parsed)
         {
-                std::vector<std::string> tmp_parsed;
-                //std::cout<<" parsed "<<k<<std::endl;
-                tokenize(k,'-',tmp_parsed);
-                if (tmp_parsed.size()==1) elementsToSkip.push_back(std::stoi(tmp_parsed[0]));
+                std::vector<std::string> tmp_parsed =GeoStrUtils::tokenize(k,"-");
+                if (tmp_parsed.size()==1) elementsToSkip.push_back(GeoStrUtils::atoi(tmp_parsed[0]));
                 else if (tmp_parsed.size()==2)
                 {
-                        int i1=std::stoi(tmp_parsed[0]);
-                        int i2=std::stoi(tmp_parsed[1]);
+                        int i1=GeoStrUtils::atoi(tmp_parsed[0]);
+                        int i2=GeoStrUtils::atoi(tmp_parsed[1]);
                         //std::cout<<" indices "<<i1<<" "<<i2<<std::endl;
                         assert(i1<i2);
                         for (int l=i1;l<i2+1;l++) elementsToSkip.push_back(l);
diff --git a/GeoModelTools/GeoModelXMLParser/CMakeLists.txt b/GeoModelTools/GeoModelXMLParser/CMakeLists.txt
index 4ec001e6c..1b98523de 100644
--- a/GeoModelTools/GeoModelXMLParser/CMakeLists.txt
+++ b/GeoModelTools/GeoModelXMLParser/CMakeLists.txt
@@ -21,6 +21,8 @@ set_target_properties( GeoModelXMLParser PROPERTIES
 # version of the library.
 add_library( GeoModelTools::GeoModelXMLParser ALIAS GeoModelXMLParser )
 
+target_link_libraries( GeoModelXMLParser PRIVATE GeoModelCore::GeoModelHelpers  )
+
 # Install the library.
 install(TARGETS GeoModelXMLParser
     EXPORT ${PROJECT_NAME}-export
diff --git a/GeoModelTools/GeoModelXMLParser/GeoModelXMLParser/XMLHandler.h b/GeoModelTools/GeoModelXMLParser/GeoModelXMLParser/XMLHandler.h
index 716e1719d..04cc2485c 100644
--- a/GeoModelTools/GeoModelXMLParser/GeoModelXMLParser/XMLHandler.h
+++ b/GeoModelTools/GeoModelXMLParser/GeoModelXMLParser/XMLHandler.h
@@ -68,7 +68,6 @@ protected:
 		static ExpressionEvaluator* eval=ExpressionEvaluator::GetEvaluator();
 		return eval;
 	}
-	static std::vector<std::string>& tokenize(const std::string&,const std::string&);
 private:
 	void RegisterToStore();
 };
diff --git a/GeoModelTools/GeoModelXMLParser/src/XMLHandler.cxx b/GeoModelTools/GeoModelXMLParser/src/XMLHandler.cxx
index ee63ff183..82f3a6b03 100644
--- a/GeoModelTools/GeoModelXMLParser/src/XMLHandler.cxx
+++ b/GeoModelTools/GeoModelXMLParser/src/XMLHandler.cxx
@@ -1,10 +1,11 @@
 /*
-  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 #include "GeoModelXMLParser/XMLHandler.h"
 #include "GeoModelXMLParser/XMLHandlerStore.h"
-
+#include "GeoModelHelpers/StringUtils.h"
+#include "GeoModelHelpers/throwExcept.h"
 #include "ExpressionEvaluator/ExpressionEvaluator.h"
 
 #include <vector>
@@ -15,304 +16,267 @@ using namespace GeoModelTools;
 DOMNode* XMLHandler::s_currentElement=0;
 bool XMLHandler::s_printFlag=false;
 
-XMLHandler::XMLHandler(std::string n):m_name(n) 
-{
+XMLHandler::XMLHandler(std::string n):m_name(n)  {
 //    std::cout<< " creating new handler "<<n<<std::endl;
-	m_stopLoop=false;
-	RegisterToStore();
+    m_stopLoop=false;
+    RegisterToStore();
 }
 
 void XMLHandler::RegisterToStore() 
 {
-	XMLHandlerStore::GetHandlerStore()->RegisterHandler(this);
+    XMLHandlerStore::GetHandlerStore()->RegisterHandler(this);
 }
 
 void XMLHandler::StopLoop(bool v)
 {
-	m_stopLoop=v;
+    m_stopLoop=v;
 }
 bool XMLHandler::IsLoopToBeStopped()
 {
-	return m_stopLoop;
+    return m_stopLoop;
 }
 bool XMLHandler::isAttribute(const std::string name) const
 {
-	bool res;
-	std::string temp=getAttribute(name,res);
-	return res;
+    bool res;
+    std::string temp=getAttribute(name,res);
+    return res;
 }
 std::string XMLHandler::getAttribute(const std::string name, bool& isPresent) const
 {
-	std::string retValue="";
-	isPresent=false;
-	if (s_currentElement->hasAttributes()) {
-		DOMNamedNodeMap *pAttributes = s_currentElement->getAttributes();
-		DOMAttr *pAttributeNode = (DOMAttr*) pAttributes->getNamedItem(XMLString::transcode(name.c_str()));
-		if (pAttributeNode) {
+    std::string retValue="";
+    isPresent=false;
+    if (s_currentElement->hasAttributes()) {
+        DOMNamedNodeMap *pAttributes = s_currentElement->getAttributes();
+        DOMAttr *pAttributeNode = (DOMAttr*) pAttributes->getNamedItem(XMLString::transcode(name.c_str()));
+        if (pAttributeNode) {
 
-  		  char* val=XMLString::transcode(pAttributeNode->getValue());
-		  if (val) {
-			
-			isPresent=true;
-			retValue=val;
-			XMLString::release(&val);
-			return retValue;
-		  }
-		}
-		else return retValue;
-			
-	}
-	return retValue;
+            char* val=XMLString::transcode(pAttributeNode->getValue());
+          if (val) {
+            
+            isPresent=true;
+            retValue=val;
+            XMLString::release(&val);
+            return retValue;
+          }
+        }
+        else return retValue;
+            
+    }
+    return retValue;
 }
 std::string XMLHandler::getAttributeAsString(const std::string name) const
 {
-	bool isPresent;
-	std::string temp=getAttribute(name,isPresent);
-	if (!isPresent) {
-        std::cerr << "\nERROR!! XMLHandler::getAttributeAsString(name) --> Attribute '" << name << "' is not present! Check your data!" << std::endl;
-        throw std::runtime_error ("XML attribute not found!");;
+    bool isPresent{false};
+    std::string temp=getAttribute(name,isPresent);
+    if (!isPresent) {
+        THROW_EXCEPTION("--> Attribute '" << name << "' is not present! Check your data!");
     }
-	return temp;
+    return temp;
 }
 double XMLHandler::getAttributeAsDouble(const std::string name) const
-{
-        double res=0.;
-        bool isPresent;
-        std::string temp=getAttribute(name,isPresent);
-	if (!isPresent) throw;
-        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-        return res;
-}
-float XMLHandler::getAttributeAsFloat(const std::string name) const
-{
-        float res=0.;
-        bool isPresent;
-        std::string temp=getAttribute(name,isPresent);
-	if (!isPresent) throw;
-        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-        return res;
-}
-int XMLHandler::getAttributeAsInt(const std::string name) const
-{
-        int res=0;
-        bool isPresent;
-        std::string temp=getAttribute(name,isPresent);
-	if (!isPresent) throw;
-        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-        return res;
-}
-long XMLHandler::getAttributeAsLong(const std::string name) const
-{
-        long res=0;
-        bool isPresent;
-        std::string temp=getAttribute(name,isPresent);
-	if (!isPresent) throw;
-        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-        return res;
-}
-std::vector<double> XMLHandler::getAttributeAsVector(const std::string name) const
-{
-	bool isPresent;
-        std::vector<double> vect;
-        std::string temp=getAttribute(name,isPresent);
-        if (!isPresent) throw;
-        std::vector<std::string> v=tokenize(";",temp);
-        for (unsigned int i=0;i<v.size();i++)
-        {
-             vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
-        }
-        return vect;
-}
-
-std::vector<int> XMLHandler::getAttributeAsIntVector(const std::string name) const
-{
-        bool isPresent;
-        std::vector<int> vect;
-        std::string temp=getAttribute(name,isPresent);
-        if (!isPresent) throw;
-        std::vector<std::string> v=tokenize(";",temp);
-        for (unsigned int i=0;i<v.size();i++)
-        {
-             vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
-        }
-        return vect;
-}
-
-std::string XMLHandler::getAttributeAsString(const std::string name, bool& isPresent) const
-{
-        std::string temp=getAttribute(name,isPresent);
-        return temp;
-} 
-double XMLHandler::getAttributeAsDouble(const std::string name, bool& isPresent) const
 {
 	double res=0.;
+	bool isPresent{false};
 	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-	}
+	if (!isPresent) {
+        THROW_EXCEPTION("--> Attribute '" << name << "' is not present! Check your data!");
+    }
+	res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
 	return res;
 }
-float XMLHandler::getAttributeAsFloat(const std::string name, bool& isPresent) const
+float XMLHandler::getAttributeAsFloat(const std::string name) const
 {
 	float res=0.;
+	bool isPresent{false};
 	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-	}
+    if (!isPresent) {
+        THROW_EXCEPTION("--> Attribute '" << name << "' is not present! Check your data!");
+    }
+	res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
 	return res;
 }
-int XMLHandler::getAttributeAsInt(const std::string name, bool& isPresent) const
+int XMLHandler::getAttributeAsInt(const std::string name) const
 {
 	int res=0;
+	bool isPresent{false};
 	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-	}
+    if (!isPresent) {
+        THROW_EXCEPTION("--> Attribute '" << name << "' is not present! Check your data!");
+    }
+	res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
 	return res;
 }
-long XMLHandler::getAttributeAsLong(const std::string name, bool& isPresent) const
+long XMLHandler::getAttributeAsLong(const std::string name) const
 {
 	long res=0;
+	bool isPresent{false};
 	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-	}
+    if (!isPresent) {
+        THROW_EXCEPTION("--> Attribute '" << name << "' is not present! Check your data!");
+    }
+	res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
 	return res;
 }
-std::vector<double> XMLHandler::getAttributeAsVector(const std::string name, bool& isPresent) const
+std::vector<double> XMLHandler::getAttributeAsVector(const std::string name) const
 {
+	bool isPresent{false};
 	std::vector<double> vect;
 	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		std::vector<std::string> v=tokenize(";",temp);
-		for (unsigned int i=0;i<v.size();i++)
-		{
-			vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
-		}
+	if (!isPresent) {
+        THROW_EXCEPTION("--> Attribute '" << name << "' is not present! Check your data!");
+    }
+	std::vector<std::string> v= GeoStrUtils::tokenize(temp, ";");
+	for (unsigned int i=0;i<v.size();i++) {
+		vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
 	}
 	return vect;
 }
 
-std::vector<int> XMLHandler::getAttributeAsIntVector(const std::string name, bool& isPresent) const
-{
+std::vector<int> XMLHandler::getAttributeAsIntVector(const std::string name) const {
+	bool isPresent{false};
+	std::vector<int> vect;
+	std::string temp=getAttribute(name,isPresent);
+	if (!isPresent) {
+        THROW_EXCEPTION("--> Attribute '" << name << "' is not present! Check your data!");
+    }
+	std::vector<std::string> v= GeoStrUtils::tokenize(temp, ";");
+	for (unsigned int i=0;i<v.size();i++) {
+		vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
+	}
+	return vect;
+}
+
+std::string XMLHandler::getAttributeAsString(const std::string name, bool& isPresent) const {
+        std::string temp=getAttribute(name,isPresent);
+        return temp;
+} 
+double XMLHandler::getAttributeAsDouble(const std::string name, bool& isPresent) const {
+    double res=0.;
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) {
+        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
+    }
+    return res;
+}
+float XMLHandler::getAttributeAsFloat(const std::string name, bool& isPresent) const {
+    float res=0.;
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) {
+		res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
+    }
+    return res;
+}
+int XMLHandler::getAttributeAsInt(const std::string name, bool& isPresent) const {
+    int res=0;
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) {
+        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
+    }
+    return res;
+}
+long XMLHandler::getAttributeAsLong(const std::string name, bool& isPresent) const {
+    long res=0;
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) {
+        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
+    }
+    return res;
+}
+std::vector<double> XMLHandler::getAttributeAsVector(const std::string name, bool& isPresent) const {
+    std::vector<double> vect;
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) 
+    {
+        std::vector<std::string> v= GeoStrUtils::tokenize(temp, ";");
+        for (unsigned int i=0;i<v.size();i++) {
+            vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
+        }
+    }
+    return vect;
+}
+
+std::vector<int> XMLHandler::getAttributeAsIntVector(const std::string name, bool& isPresent) const {
         std::vector<int> vect;
         std::string temp=getAttribute(name,isPresent);
-        if (isPresent)
-        {
-                std::vector<std::string> v=tokenize(";",temp);
-                for (unsigned int i=0;i<v.size();i++)
-                {
-                        vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
-                }
+        if (isPresent) {
+			std::vector<std::string> v= GeoStrUtils::tokenize(temp, ";");
+			for (unsigned int i=0;i<v.size();i++) {
+				vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
+			}
         }
         return vect;
 }
 
-std::string XMLHandler::getAttributeAsString(const std::string name, const std::string def) const
-{
-	bool isPresent;
-	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) return temp;
-	else return def;
+std::string XMLHandler::getAttributeAsString(const std::string name, const std::string def) const {
+    bool isPresent{false};
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) return temp;
+    else return def;
 }
-double XMLHandler::getAttributeAsDouble(const std::string name, const double def) const
-{
-	bool isPresent;
-	double res=0.;
-	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-		return res;
-	}
-	return def;
+double XMLHandler::getAttributeAsDouble(const std::string name, const double def) const {
+    bool isPresent{false};
+    double res=0.;
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) {
+        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
+        return res;
+    }
+    return def;
 }
-float XMLHandler::getAttributeAsFloat(const std::string name, const float def) const
-{
-	bool isPresent;
-	float res=0.;
-	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-		return res;
-	}
-	return def;
+float XMLHandler::getAttributeAsFloat(const std::string name, const float def) const {
+    bool isPresent{false};
+    float res=0.;
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) {
+        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
+        return res;
+    }
+    return def;
 }
-int XMLHandler::getAttributeAsInt(const std::string name, const int def) const
-{
-	bool isPresent;
-	int res=0;
-	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-		return res;
-	}
-	return def;
+int XMLHandler::getAttributeAsInt(const std::string name, const int def) const {
+    bool isPresent{false};
+    int res=0;
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) {
+        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
+        return res;
+    }
+    return def;
 }
-long XMLHandler::getAttributeAsLong(const std::string name, const long def) const
-{
-	bool isPresent;
-	long res=0;
-	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
-		return res;
-	}
-	return def;
+long XMLHandler::getAttributeAsLong(const std::string name, const long def) const {
+    bool isPresent{false};
+    long res=0;
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) {
+        res=ExpressionEvaluator::GetEvaluator()->Eval(temp.c_str());
+        return res;
+    }
+    return def;
 }
-std::vector<double> XMLHandler::getAttributeAsVector(const std::string name, const std::vector<double> def) const
-{
-	bool isPresent;
-	std::vector<double> vect;
+std::vector<double> XMLHandler::getAttributeAsVector(const std::string name, const std::vector<double> def) const {
+    bool isPresent{false};
+    std::vector<double> vect{};
+    std::string temp=getAttribute(name,isPresent);
+    if (isPresent) {
+        std::vector<std::string> v= GeoStrUtils::tokenize(temp,";");
+        for (unsigned int i=0;i<v.size();i++){
+            vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
+        }
+        return vect;
+    }
+    return def;
+}
+
+std::vector<int> XMLHandler::getAttributeAsIntVector(const std::string name, const std::vector<int> def) const {
+	bool isPresent{false};
+	std::vector<int> vect;
 	std::string temp=getAttribute(name,isPresent);
-	if (isPresent) 
-	{
-		std::vector<std::string> v=tokenize(";",temp);
-		for (unsigned int i=0;i<v.size();i++)
-		{
+	if (isPresent) {
+		std::vector<std::string> v= GeoStrUtils::tokenize(temp, ";");
+		for (unsigned int i=0;i<v.size();i++) {
 			vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
 		}
 		return vect;
 	}
 	return def;
 }
-
-std::vector<int> XMLHandler::getAttributeAsIntVector(const std::string name, const std::vector<int> def) const
-{
-        bool isPresent;
-        std::vector<int> vect;
-        std::string temp=getAttribute(name,isPresent);
-        if (isPresent)
-        {
-                std::vector<std::string> v=tokenize(";",temp);
-                for (unsigned int i=0;i<v.size();i++)
-                {
-                        vect.push_back(ExpressionEvaluator::GetEvaluator()->Eval(v[i].c_str()));
-                }
-                return vect;
-        }
-        return def;
-}
-
-std::vector<std::string>& XMLHandler::tokenize(const std::string& sep,const std::string& expr)
-{
-        static std::vector<std::string> tempvect;
-        tempvect.clear();
-
-        std::string::size_type i=0, j=0;
-        while( (j=expr.find(sep,i))!=std::string::npos) {
-                tempvect.push_back(expr.substr(i,j-i));
-                i = j+sep.size();
-        }
-        tempvect.push_back(expr.substr(i));
-
-        return tempvect;
-}
diff --git a/athena_ci/apply_patches.sh b/athena_ci/apply_patches.sh
index 65c2f8bd5..3d61a057f 100755
--- a/athena_ci/apply_patches.sh
+++ b/athena_ci/apply_patches.sh
@@ -31,3 +31,5 @@ for p in "$SCRIPT_DIR"/patches/*.patch; do
     git --no-pager log -1 $sha
     fill_line "-"
 done
+
+git diff HEAD ${NIGHTLY_COMMIT}
\ No newline at end of file
diff --git a/athena_ci/athena_build.sh b/athena_ci/athena_build.sh
index 4b719a6e9..4260f51bc 100755
--- a/athena_ci/athena_build.sh
+++ b/athena_ci/athena_build.sh
@@ -139,18 +139,30 @@ export CMAKE_PREFIX_PATH="${gm_install_dir}:$CMAKE_PREFIX_PATH"
 
 heading "Configure Athena"
 
-package_filters=$SCRIPT_DIR/package_filters.txt
+full_package_filters=$SCRIPT_DIR/package_filters.txt
+patch_package_filters=$SCRIPT_DIR/patch_package_filters.txt
+
+package_filters=$(mktemp)
+
 
 echo "IS_MERGE_REQUEST = $IS_MERGE_REQUEST"
 echo "HEADERS_CHANGED = $HEADERS_CHANGED"
 
 if [ "$IS_MERGE_REQUEST" = "0" ] && [ "$HEADERS_CHANGED" = "1" ]; then
     echo "Is MR and header files have NOT changed"
-    package_filters=$(mktemp)
-    echo "- .*" >> "$package_filters"
+else
+    echo "Is NOT MR OR header files HAVE changed"
+    cat "$full_package_filters" > "$package_filters"
 fi
 
-echo $package_filters
+cat "$patch_package_filters" >> "$package_filters"
+
+echo "- .*" >> "$package_filters"
+
+echo "$package_filters"
+fill_line "-"
+cat "$package_filters"
+fill_line "-"
 
 mkdir athena-build
 install_dir=$PWD/athena-install
diff --git a/athena_ci/ci.yml b/athena_ci/ci.yml
index 72e0bfb6e..dd7dc2441 100644
--- a/athena_ci/ci.yml
+++ b/athena_ci/ci.yml
@@ -46,7 +46,7 @@ build_geomodel_athena:
 
 
 .run_base:
-  stage: step-A
+  stage: step-B
 
   # This image sould work, but it seems it doesn't. Using my derivative until 
   # I figure out what the difference is.
@@ -94,10 +94,106 @@ build_geomodel_athena:
 
     - source athena-install/setup.sh
     - export LD_LIBRARY_PATH=$PWD/geomodel-install/lib64:$LD_LIBRARY_PATH
-    - mkdir run
+    - mkdir -p run
+
+
+################################################
+###       Simulation_tf tests
+################################################
+simulation_tests_run2:
+  extends: .run_base
+  script:
+    - cd run
+    - RunWorkflowTests_Run2.py --CI -s -w FullSim --threads 4 -e '--maxEvents 10' --detailed-comparison
+    - mv run_s4005/log.EVNTtoHITS ./
+    - mv run_s4005/myHITS.pool.root ./
+  artifacts:
+    paths:
+      - Run2Tests.log
+      - myHITS.pool.root
+      - log.EVNTtoHITS
+
+    expire_in: 1 day
 
+simulation_tests_run3:
+  extends: .run_base
+  script:
+    - cd run
+    - RunWorkflowTests_Run3.py --CI -s -w FullSim --threads 4 -e '--maxEvents 50' --detailed-comparison
+    - mv run_s4006/log.EVNTtoHITS ./
+    - mv run_s4006/myHITS.pool.root ./
+  artifacts:
+    paths:
+      - Run3Tests.log
+      - myHITS.pool.root
+      - log.EVNTtoHITS
+
+simulation_tests_run4:
+  extends: .run_base
+  script:
+    - cd run
+    - RunWorkflowTests_Run4.py --CI -s -w FullSim --threads 4 -e '--maxEvents 10' --detailed-comparison
+    - mv run_s3761/myHITS.pool.root ../
+    - mv run_s3761/log.EVNTtoHITS ./
+  artifacts:
+    paths:
+      - myHITS.pool.root
+      - RunUpgradeTests.log
+      - log.EVNTtoHITS
+    expire_in: 1 day
+
+
+###################################################
+###         Reco_tf.py tests
+###################################################
 run_workflow_tests_run2_mc:
   extends: .run_base
   script:
     - cd run
-    - RunWorkflowTests_Run2.py --CI -r -w MCReco --threads 0 -e '--CA "all:True" "RDOtoRDOTrigger:False" --conditionsTag "default:OFLCOND-MC16-SDR-RUN2-11" "RDOtoRDOTrigger:OFLCOND-MC16-SDR-RUN2-08-02" --maxEvents 25'
+    - RunWorkflowTests_Run2.py --CI -r -w MCReco --threads 0 -e '--CA "all:True" "RDOtoRDOTrigger:False" --conditionsTag "default:OFLCOND-MC16-SDR-RUN2-11" "RDOtoRDOTrigger:OFLCOND-MC16-SDR-RUN2-08-02" --maxEvents 25' --detailed-comparison
+
+run_workflow_tests_run3_mc:
+  extends: .run_base
+  script:
+    - cd run
+    - RunWorkflowTests_Run3.py --CI -r -w MCReco -e '--maxEvents 25' --detailed-comparison
+
+run_workflow_tests_run4_reco:
+  extends: .run_base
+  needs: 
+      - simulation_tests_run4
+      - build_geomodel_athena
+  script:
+      - cd run
+      - RunWorkflowTests_Run4.py --CI -r -w MCReco -e '--maxEvents 5 --inputHITSFile=../../myHITS.pool.root' --no-output-checks
+
+
+###################################################
+###      Geometry dump for debugging
+###################################################
+dumpGeoTest_run2:
+  extends: .run_base
+  script:
+      - python -m DumpGeo.DumpGeoConfig --detDescr ATLAS-R2-2016-01-02-01
+  artifacts:
+    paths:
+      - geometry-ATLAS-R2-2016-01-02-01.db
+    expire_in: 1 day
+
+dumpGeoTest_run3:
+  extends: .run_base
+  script:
+      - python -m DumpGeo.DumpGeoConfig --detDescr ATLAS-R3S-2021-03-02-00
+  artifacts:
+    paths:
+      - geometry-ATLAS-R3S-2021-03-02-00.db
+    expire_in: 1 day
+
+dumpGeoTest_run4:
+  extends: .run_base
+  script:
+      - python -m DumpGeo.DumpGeoConfig --detDescr ATLAS-P2-RUN4-03-00-00
+  artifacts:
+    paths:
+      - geometry-ATLAS-P2-RUN4-03-00-00.db
+    expire_in: 1 day
diff --git a/athena_ci/package_filters.txt b/athena_ci/package_filters.txt
index 896845dcf..b56c38152 100644
--- a/athena_ci/package_filters.txt
+++ b/athena_ci/package_filters.txt
@@ -140,4 +140,3 @@
 + graphics/VP1/VP1Systems/VP1TrackSystems
 + graphics/VP1/VP1Systems/VP1TrackingGeometrySystems
 + graphics/VP1/VP1Utils
-- .*
diff --git a/athena_ci/patch_package_filters.txt b/athena_ci/patch_package_filters.txt
new file mode 100644
index 000000000..331977418
--- /dev/null
+++ b/athena_ci/patch_package_filters.txt
@@ -0,0 +1,6 @@
+# These Athena packages need to be rebuilt 
+# due to patches in the `patches` directory
+
++ InnerDetector/InDetDetDescr/InDetServMatGeoModel
++ InnerDetector/InDetDetDescr/PixelGeoModel
++ DetectorDescription/GeoModel/GeoModelStandalone/GeoExporter
diff --git a/athena_ci/patches/0001-Swap-rotation-signs.patch b/athena_ci/patches/0001-Swap-rotation-signs.patch
new file mode 100644
index 000000000..e8b63c051
--- /dev/null
+++ b/athena_ci/patches/0001-Swap-rotation-signs.patch
@@ -0,0 +1,144 @@
+From 2b0f4de6ceabe19d8a2fa84b9130c277b1e21436 Mon Sep 17 00:00:00 2001
+From: Johannes Junggeburth <johannes.josef.junggeburth@cern.ch>
+Date: Mon, 26 Feb 2024 17:57:04 +0100
+Subject: [PATCH] Swap rotation signs
+
+Fix typo
+---
+ .../src/EndPlateFactory.cxx                    | 18 +++++++++---------
+ .../src/SCT_ServMatFactory.cxx                 |  4 ++--
+ .../src/SquirrelCageFactory.cxx                |  2 +-
+ .../src/GeoPixelDetailedStaveSupport.cxx       |  6 +++---
+ 4 files changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/EndPlateFactory.cxx b/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/EndPlateFactory.cxx
+index 4a91ebacb15..31f02babc9a 100755
+--- a/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/EndPlateFactory.cxx
++++ b/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/EndPlateFactory.cxx
+@@ -95,7 +95,7 @@ void EndPlateFactory::create(GeoPhysVol *mother)
+     GeoTrf::Translate3D servpos1(0.,0., zposEP);
+     GeoTrf::Vector3D servpos2(0.,0.,-zposEP);
+     GeoTransform* xform1 = new GeoTransform(servpos1);
+-    GeoTransform* xform2 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0,M_PI,0),servpos2));
++    GeoTransform* xform2 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0,-M_PI,0),servpos2)); 
+     mother->add(xform1);
+     mother->add(shellPhysInt);
+     mother->add(xform2);
+@@ -120,7 +120,7 @@ void EndPlateFactory::create(GeoPhysVol *mother)
+     GeoTrf::Translate3D servpos3(0.,0., zposEP+zleng+thickShell+zgap+thickShell/2.);
+     GeoTrf::Vector3D servpos4(0.,0.,-zposEP-zleng-thickShell-zgap-thickShell/2.);
+     GeoTransform *xform3 = new GeoTransform(servpos3);
+-    GeoTransform* xform4 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0,M_PI,0),servpos4));
++    GeoTransform* xform4 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0,-M_PI,0),servpos4));
+ 
+     mother->add(xform3);
+     mother->add(shellPhysExt);
+@@ -160,7 +160,7 @@ void EndPlateFactory::create(GeoPhysVol *mother)
+     GeoTrf::Translate3D servpos5(0.,0., zinsert);
+     GeoTrf::Vector3D servpos6(0.,0.,-zinsert);
+     GeoTransform *xform5 = new GeoTransform(servpos5);
+-    GeoTransform* xform6 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0,M_PI,0),servpos6));
++    GeoTransform* xform6 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0,-M_PI,0),servpos6));
+ 
+     mother->add(xform5);
+     mother->add(InsertPhys);
+@@ -200,10 +200,10 @@ void EndPlateFactory::create(GeoPhysVol *mother)
+       double angl= ip*M_PI/6.;
+       GeoTrf::Vector3D ribpos_pos( posX*cos(angl), posX*sin(angl), zposEP+zleng+thickShell+zgap/2.);
+       GeoTrf::Vector3D ribpos_neg( posX*cos(angl), posX*sin(angl),-zposEP-zleng-thickShell-zgap/2.);
+-      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(-angl,0,0),ribpos_pos));
++      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(angl,0,0),ribpos_pos));
+       mother->add(xrib);
+       mother->add(ribShortPhys);
+-      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(-angl,0,0),ribpos_neg));
++      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(angl,0,0),ribpos_neg));
+       mother->add(xrib);
+       mother->add(ribShortPhys);
+     }
+@@ -247,19 +247,19 @@ void EndPlateFactory::create(GeoPhysVol *mother)
+ // 1st part
+       GeoTrf::Vector3D ribpos_pos1( posX1*cos(angl), posX1*sin(angl), zposEP+zleng+thickShell+zgap/2.);
+       GeoTrf::Vector3D ribpos_neg1( posX1*cos(angl), posX1*sin(angl),-zposEP-zleng-thickShell-zgap/2.);
+-      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(-angl,0,0),ribpos_pos1));      
++      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(angl,0,0),ribpos_pos1));      
+       mother->add(xrib);
+       mother->add(ribLong1Phys);
+-      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(-angl,0,0),ribpos_neg1));      
++      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(angl,0,0),ribpos_neg1));      
+       mother->add(xrib);
+       mother->add(ribLong1Phys);
+ // 2nd part
+       GeoTrf::Vector3D ribpos_pos2( posX2*cos(angl), posX2*sin(angl), zposEP+zleng+thickShell+zgap/2.);
+       GeoTrf::Vector3D ribpos_neg2( posX2*cos(angl), posX2*sin(angl),-zposEP-zleng-thickShell-zgap/2.);
+-      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(-angl,0,0),ribpos_pos2));      
++      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(angl,0,0),ribpos_pos2));      
+       mother->add(xrib);
+       mother->add(ribLong2Phys);
+-      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(-angl,0,0),ribpos_neg2));      
++      xrib = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(angl,0,0),ribpos_neg2));      
+       mother->add(xrib);
+       mother->add(ribLong2Phys);
+     }
+diff --git a/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/SCT_ServMatFactory.cxx b/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/SCT_ServMatFactory.cxx
+index d85833983b2..61b92c63352 100755
+--- a/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/SCT_ServMatFactory.cxx
++++ b/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/SCT_ServMatFactory.cxx
+@@ -255,9 +255,9 @@ void SCT_ServMatFactory::create(GeoPhysVol *mother)
+       const GeoLogVol* wingLog = new GeoLogVol(logName,wing,wingMat);
+       GeoVPhysVol* wingPhys    = new GeoPhysVol(wingLog);
+       GeoTransform* wPos1 = new GeoTransform(GeoTrf::Translate3D(0.,0., ZStartW+ZHalfLengthW));
+-      GeoTransform* wPos2 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(M_PI,0,0),GeoTrf::Vector3D(0.,0., ZStartW+ZHalfLengthW)));
++      GeoTransform* wPos2 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(-M_PI,0,0),GeoTrf::Vector3D(0.,0., ZStartW+ZHalfLengthW)));
+       GeoTransform* wPos3 = new GeoTransform(GeoTrf::Translate3D(0.,0.,-ZStartW-ZHalfLengthW));
+-      GeoTransform* wPos4 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(M_PI,0,0),GeoTrf::Vector3D(0.,0.,-ZStartW-ZHalfLengthW)));
++      GeoTransform* wPos4 = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(-M_PI,0,0),GeoTrf::Vector3D(0.,0.,-ZStartW-ZHalfLengthW)));
+       mother->add(wPos1);
+       mother->add(wingPhys);
+       mother->add(wPos2);
+diff --git a/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/SquirrelCageFactory.cxx b/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/SquirrelCageFactory.cxx
+index e01d8bd49a9..ef4a4455adb 100755
+--- a/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/SquirrelCageFactory.cxx
++++ b/InnerDetector/InDetDetDescr/InDetServMatGeoModel/src/SquirrelCageFactory.cxx
+@@ -342,7 +342,7 @@ void SquirrelCageFactory::create(GeoPhysVol *mother)
+     GeoTrf::Translate3D  suppos1(0.,0., zposSupRing+supWid/2.);
+     GeoTrf::Vector3D  suppos2(0.,0.,-zposSupRing-supWid/2.);
+     GeoTransform *sform1  = new GeoTransform(suppos1);
+-    GeoTransform *sform2  = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0,M_PI,0),suppos2));
++    GeoTransform *sform2  = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0,-M_PI,0),suppos2));
+     mother->add(sform1);
+     mother->add(ringPhysSup);
+     mother->add(sform2);
+diff --git a/InnerDetector/InDetDetDescr/PixelGeoModel/src/GeoPixelDetailedStaveSupport.cxx b/InnerDetector/InDetDetDescr/PixelGeoModel/src/GeoPixelDetailedStaveSupport.cxx
+index 8783665d493..ddc30bf9dd4 100644
+--- a/InnerDetector/InDetDetDescr/PixelGeoModel/src/GeoPixelDetailedStaveSupport.cxx
++++ b/InnerDetector/InDetDetDescr/PixelGeoModel/src/GeoPixelDetailedStaveSupport.cxx
+@@ -809,7 +809,7 @@ GeoVPhysVol* GeoPixelDetailedStaveSupport::Build ( ) {
+       
+       // Add flex in 3D model : A component
+       GeoTrf::Vector3D wingflex_posA((flex1x+flex2x+flex3x+flex4x)*0.25,(flex1y+flex2y+flex3y+flex4y)*0.25,(wingZmax-wingZmin)*.5+FlexStaveMiddleGap);
+-      GeoTransform* wingflex_xformA = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0.0,0.0,-fabs(flex_angle)),wingflex_posA));
++      GeoTransform* wingflex_xformA = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0.0,0.0,std::abs(flex_angle)),wingflex_posA));
+       
+       const GeoMaterial* wingflex_material= m_mat_mgr->getMaterial("pix::WingFlexA");
+       GeoLogVol * wingflex_logVol = new GeoLogVol(wingName.str(),wingflex_shape,wingflex_material);
+@@ -821,7 +821,7 @@ GeoVPhysVol* GeoPixelDetailedStaveSupport::Build ( ) {
+       logVolPV->add(wingflex_logVolPV);
+       
+       GeoTrf::Vector3D wingflex_posC((flex1x+flex2x+flex3x+flex4x)*0.25,(flex1y+flex2y+flex3y+flex4y)*0.25,-((wingZmax-wingZmin)*.5+FlexStaveMiddleGap));
+-      GeoTransform* wingflex_xformC = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0.0,0.0,-fabs(flex_angle)),wingflex_posC));
++      GeoTransform* wingflex_xformC = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0.0,0.0,std::abs(flex_angle)),wingflex_posC));
+       logVolPV->add(wingflex_tag);
+       logVolPV->add(wingflex_xformC);
+       logVolPV->add(wingflex_logVolPV);
+@@ -1038,7 +1038,7 @@ GeoVPhysVol* GeoPixelDetailedStaveSupport::Build ( ) {
+   // Add flex in 3D model : A component
+   //  GeoNameTag* cableflex_tag = new GeoNameTag(lname.str());
+   GeoTrf::Vector3D cableflex_pos(EndblockFlexXpos,EndblockFlexYpos,0.);
+-  m_endblockFlexTrf = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0.0,0.0,-fabs(flex_angle)),cableflex_pos));
++  m_endblockFlexTrf = new GeoTransform(GeoTrf::GeoTransformRT(GeoTrf::GeoRotation(0.0,0.0, std::abs(flex_angle)),cableflex_pos));
+   GeoLogVol * cableflex_logVol = new GeoLogVol(lname.str(),cableflex_shape,scaledFlexMaterial);
+   m_endblockFlexPhysVol = new GeoPhysVol(cableflex_logVol);
+ 
+-- 
+2.39.3
+
diff --git a/athena_ci/patches/0001-Test-commit.patch b/athena_ci/patches/0001-Test-commit.patch
deleted file mode 100644
index 18dfdf13f..000000000
--- a/athena_ci/patches/0001-Test-commit.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-From 5b5dbeb5c76eb3b5e631d399858cd5a4d065547d Mon Sep 17 00:00:00 2001
-From: Paul Gessinger <paul.gessinger@cern.ch>
-Date: Wed, 31 Jan 2024 15:37:47 +0100
-Subject: [PATCH] Test commit
-
----
- TileCalorimeter/TileGeoModel/src/TileDetectorFactory.h | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/TileCalorimeter/TileGeoModel/src/TileDetectorFactory.h b/TileCalorimeter/TileGeoModel/src/TileDetectorFactory.h
-index 6c83ed20dae..18da249e4d1 100755
---- a/TileCalorimeter/TileGeoModel/src/TileDetectorFactory.h
-+++ b/TileCalorimeter/TileGeoModel/src/TileDetectorFactory.h
-@@ -20,6 +20,10 @@
- class MsgStream;
- class StoreGateSvc;
- 
-+/*
-+ * I am a useless change for testing
-+ */
-+
- 
- class TileDetectorFactory : public GeoVDetectorFactory
- {
--- 
-2.39.3
-
diff --git a/athena_ci/patches/0002-Remove-the-QApplication-relic-to-fix-segfault-on-Alm.patch b/athena_ci/patches/0002-Remove-the-QApplication-relic-to-fix-segfault-on-Alm.patch
new file mode 100644
index 000000000..94be09c91
--- /dev/null
+++ b/athena_ci/patches/0002-Remove-the-QApplication-relic-to-fix-segfault-on-Alm.patch
@@ -0,0 +1,39 @@
+From 8f1f207ab929105adad81598ced898b5d61fc638 Mon Sep 17 00:00:00 2001
+From: Riccardo Maria Bianchi <riccardo.maria.bianchi@cern.ch>
+Date: Fri, 1 Mar 2024 19:43:43 +0100
+Subject: [PATCH] Remove the QApplication relic to fix segfault on Alma9, it's
+ not needed.
+
+---
+ .../GeoModelStandalone/GeoExporter/src/GeoExporter.cxx    | 8 --------
+ 1 file changed, 8 deletions(-)
+
+diff --git a/DetectorDescription/GeoModel/GeoModelStandalone/GeoExporter/src/GeoExporter.cxx b/DetectorDescription/GeoModel/GeoModelStandalone/GeoExporter/src/GeoExporter.cxx
+index e465bc4bddc..153832f99fa 100755
+--- a/DetectorDescription/GeoModel/GeoModelStandalone/GeoExporter/src/GeoExporter.cxx
++++ b/DetectorDescription/GeoModel/GeoModelStandalone/GeoExporter/src/GeoExporter.cxx
+@@ -35,7 +35,6 @@
+ #include "GeoModelWrite/WriteGeoModel.h"
+ // #include "GeoModelHelpers/defineWorld.h" //TODO: Use this as soon as we have the latest GeoModel in Athena main
+ 
+-#include <QCoreApplication>
+ #include <QtCore/QStringList>
+ #include <QtCore/QFile>
+ #include <QtCore/QFileInfo>
+@@ -145,13 +144,6 @@ void GeoExporter::init()
+   VP1Msg::message("===================================================");
+   VP1Msg::message("");
+ 
+-  int argc=1;
+-  char *argv[2];
+-
+-  QCoreApplication app(argc, argv);
+-  QCoreApplication::setOrganizationName("ATLAS");
+-  QCoreApplication::setApplicationName("GeoExporter");
+-
+   VP1Msg::message("Accessing the ATLAS geometry...");
+   StoreGateSvc* detstore = m_d->detstore;
+  //Get the world volume:
+-- 
+2.41.0
+
-- 
GitLab