diff --git a/Tracker/TrackerDetDescr/TrackerReadoutGeometry/TrackerReadoutGeometry/SiDetectorElement.h b/Tracker/TrackerDetDescr/TrackerReadoutGeometry/TrackerReadoutGeometry/SiDetectorElement.h
index 652add49be92b54bcf1b273d8d1da11f1ad4fd52..3286b43b3f8b66d91ee8fe864cd3218a8301802c 100644
--- a/Tracker/TrackerDetDescr/TrackerReadoutGeometry/TrackerReadoutGeometry/SiDetectorElement.h
+++ b/Tracker/TrackerDetDescr/TrackerReadoutGeometry/TrackerReadoutGeometry/SiDetectorElement.h
@@ -221,6 +221,8 @@ namespace TrackerDD {
     // Position 
     /// Local (simulation/hit frame) to global transform
     virtual const GeoTrf::Transform3D& transformHit() const;
+    /// Local (simulation/hit frame) to module transform
+    virtual const GeoTrf::Transform3D& transformModule() const;
     /// Local (reconstruction frame) to global transform
     virtual const Amg::Transform3D& transform() const override final;
     /**
@@ -340,40 +342,37 @@ namespace TrackerDD {
       
        @name Module Frame 
        Methods to help work with the module frame. 
-       This is mainly of of use in the SCT where the module frame can
-       in general be different from the element frame. It is actully
-       defined as the frame of one of the sides (currently the axial
-       side), but using these methods one does not need to make any
-       assumptions about what the actual frame is.  In the following
-       methods the local element frame is the local reconstruction
-       frame of this element.
+       This is mainly of of use in the SCT where the module frame is
+       different from the element frame. We have removed the ATLAS convention
+       in which the module frame was one of the wafers.
     */
       
     //@{
     
+
     /// Module to global frame transform. 
     /// Includes misalignment. The module frame is defined to be the
-    /// local reconstruction frame of the axial layer in the SCT. For
-    /// the pixel it is the same as the element.
+    /// frame in which the wafers are centered, rotated by +/- stereo angle, and equally offset in depth.
+    /// For the pixel it is the same as the element.
     //const HepGeom::Transform3D & moduleTransform() const;
+    const HepGeom::Transform3D& moduleTransformCLHEP() const;   
     const Amg::Transform3D& moduleTransform() const;
     
     /// Default module to global frame transform, ie with no misalignment. 
     /// The module frame is defined to be the
-    /// local reconstruction frame of the axial layer in the SCT. For
-    /// the pixel it is the same as the element.
+    /// frame in which each wafer is centered, rotated by +/- stereo angle, and offset in depth.
+    /// For the pixel it is the same as the element.
     Amg::Transform3D defModuleTransform() const;
+    /// Default to global transform
+    /// ie with no misalignment. 
+    const HepGeom::Transform3D defModuleTransformCLHEP() const;
       
     
     /// Take a transform of the local element frame and return its equivalent in the module frame.
     //HepGeom::Transform3D localToModuleFrame(const HepGeom::Transform3D & localTransform) const;
     Amg::Transform3D localToModuleFrame(const Amg::Transform3D& localTransform) const;
     
-    /// Transformation from local element to module frame.  This can be
-    /// used to take a local position in the element frame and transform
-    /// it to a position in the module frame. If one is already in the
-    /// module frame it will return the Identity transform.
-    //HepGeom::Transform3D localToModuleTransform() const;
+    /// Transformation from local element to module frame.  
     Amg::Transform3D localToModuleTransform() const;
     
     /// Check if the element and module frame are the same.
@@ -695,6 +694,8 @@ namespace TrackerDD {
 
     mutable Amg::Transform3D m_transform ATLAS_THREAD_SAFE; // Guarded by m_mutex
     mutable HepGeom::Transform3D m_transformCLHEP ATLAS_THREAD_SAFE; // Guarded by m_mutex
+    mutable Amg::Transform3D m_moduleTransform ATLAS_THREAD_SAFE; // Guarded by m_mutex
+    mutable HepGeom::Transform3D m_moduleTransformCLHEP ATLAS_THREAD_SAFE; // Guarded by m_mutex
 
     mutable Amg::Vector3D m_normal ATLAS_THREAD_SAFE; // Guarded by m_mutex
     mutable Amg::Vector3D m_etaAxis ATLAS_THREAD_SAFE; // Guarded by m_mutex
diff --git a/Tracker/TrackerDetDescr/TrackerReadoutGeometry/src/SiDetectorElement.cxx b/Tracker/TrackerDetDescr/TrackerReadoutGeometry/src/SiDetectorElement.cxx
index c9a29684d559305ac76ad06b2b632701df8cdc3c..07a1fadae9b0560bd722ed281f0a01b83d514477 100644
--- a/Tracker/TrackerDetDescr/TrackerReadoutGeometry/src/SiDetectorElement.cxx
+++ b/Tracker/TrackerDetDescr/TrackerReadoutGeometry/src/SiDetectorElement.cxx
@@ -122,6 +122,9 @@ namespace TrackerDD {
   SiDetectorElement::updateCache() const
   {
     const GeoTrf::Transform3D& geoTransform = transformHit();
+    const GeoTrf::Transform3D& geoModuleTransform = transformModule();
+    // ATH_MSG_ALWAYS("Wafer transform: " << geoTransform.translation() << "//" << geoTransform.rotation() );
+    // ATH_MSG_ALWAYS("Module transform: " << geoModuleTransform.translation() << "//" << geoModuleTransform.rotation() );
 
     double radialShift = 0.;
       
@@ -215,6 +218,9 @@ namespace TrackerDD {
     m_transformCLHEP = Amg::EigenTransformToCLHEP(geoTransform) * recoToHitTransformImpl();
     m_transform = Amg::CLHEPTransformToEigen(m_transformCLHEP);
   
+    m_moduleTransformCLHEP = Amg::EigenTransformToCLHEP(geoModuleTransform) * recoToHitTransformImpl();
+    m_moduleTransform = Amg::CLHEPTransformToEigen(m_moduleTransformCLHEP);
+
     // Check that local frame is right-handed. (ie transform has no reflection)
     // This can be done by checking that the determinant is >0.
     if (m_firstTime) { // Only need to check this once.
@@ -286,6 +292,28 @@ namespace TrackerDD {
     return getMaterialGeom()->getAbsoluteTransform();
   }
 
+  const GeoTrf::Transform3D&
+  SiDetectorElement::transformModule() const
+  {
+    PVConstLink parent = getMaterialGeom()->getParent()->getParent();
+    const GeoVFullPhysVol* fullParent = dynamic_cast<const GeoVFullPhysVol*>(&(*parent));
+    if (fullParent == nullptr)
+    {
+      ATH_MSG_FATAL("Unable to reach parent module volume");
+      if (m_geoAlignStore) {
+        const GeoTrf::Transform3D* ptrXf = m_geoAlignStore->getAbsPosition(getMaterialGeom());
+        if (ptrXf) return *ptrXf;
+      }
+      return getMaterialGeom()->getAbsoluteTransform();
+    }
+    // ATH_MSG_ALWAYS("Found full parent named: " << fullParent->getLogVol()->getName() << " with id " << fullParent->getId());
+    if (m_geoAlignStore) {
+      const GeoTrf::Transform3D* ptrXf = m_geoAlignStore->getAbsPosition(fullParent);
+      if (ptrXf) return *ptrXf;
+    }
+    return fullParent->getAbsoluteTransform();
+  }
+
   const Amg::Transform3D&
   SiDetectorElement::transform() const
   {
@@ -377,40 +405,81 @@ namespace TrackerDD {
   const Amg::Transform3D&
   SiDetectorElement::moduleTransform() const
   {
-    return (isModuleFrame()) ? transform() : m_otherSide->transform();
+    if (!m_cacheValid) {
+      std::lock_guard<std::mutex> lock(m_mutex);
+      if (!m_cacheValid) updateCache();
+    }
+
+    return m_moduleTransform;
+  }
+
+  const HepGeom::Transform3D&
+  SiDetectorElement::moduleTransformCLHEP() const
+  {
+    //stuff to get the CLHEP version of the local to global transform.
+    if (!m_cacheValid) {
+      std::lock_guard<std::mutex> lock(m_mutex);
+      if (!m_cacheValid) updateCache();
+    }
+
+    return m_moduleTransformCLHEP;
   }
 
   Amg::Transform3D
   SiDetectorElement::defModuleTransform() const
   {
-    return (isModuleFrame()) ? defTransform() : m_otherSide->defTransform();
+    HepGeom::Transform3D tmpTransform = defModuleTransformCLHEP();
+    return Amg::CLHEPTransformToEigen(tmpTransform);
   }  
 
+  const HepGeom::Transform3D 
+  SiDetectorElement::defModuleTransformCLHEP() const
+  {
+    PVConstLink parent = getMaterialGeom()->getParent()->getParent();
+    const GeoVFullPhysVol* fullParent = dynamic_cast<const GeoVFullPhysVol*>(&(*parent));
+    if (fullParent == nullptr)
+    {
+      ATH_MSG_FATAL("Unable to reach parent module volume");
+      if (m_geoAlignStore) {
+        const GeoTrf::Transform3D* ptrXf = m_geoAlignStore->getDefAbsPosition(getMaterialGeom());
+        if (ptrXf) return Amg::EigenTransformToCLHEP(*ptrXf) * recoToHitTransform();
+      }
+      return Amg::EigenTransformToCLHEP(getMaterialGeom()->getDefAbsoluteTransform()) * recoToHitTransform();
+    }
+    // ATH_MSG_ALWAYS("Found full parent named: " << fullParent->getLogVol()->getName() << " with id " << fullParent->getId());
+    if (m_geoAlignStore) {
+      const GeoTrf::Transform3D* ptrXf = m_geoAlignStore->getDefAbsPosition(fullParent);
+      if (ptrXf) return Amg::EigenTransformToCLHEP(*ptrXf) * recoToHitTransform();
+    }
+    return Amg::EigenTransformToCLHEP(fullParent->getDefAbsoluteTransform()) * recoToHitTransform();
+  }  
+
+
   // Take a transform in the local reconstruction and return it in the module frame
   // For a given transform l in frame A. The equivalent transform in frame B is
   //  B.inverse() * A * l * A.inverse() * B
   // Here A is the local to global transform of the element and B is the local to global
   // transform of the module.
-  // If we are already in the module frame then there is nothing to do, we just return the
-  // transform that is input. Otherwise we use the above formula.
   Amg::Transform3D 
   SiDetectorElement::localToModuleFrame(const Amg::Transform3D& localTransform) const
   {
-    if (isModuleFrame()) {
-      return localTransform;
-    } else {
-      return m_otherSide->transform().inverse() * transform() * localTransform * transform().inverse() * m_otherSide->transform();
-    }
+    return moduleTransform().inverse() * transform() * localTransform * transform().inverse() * moduleTransform();
+    // if (isModuleFrame()) {
+    //   return localTransform;
+    // } else {
+    //   return m_otherSide->transform().inverse() * transform() * localTransform * transform().inverse() * m_otherSide->transform();
+    // }
   }
 
   Amg::Transform3D 
   SiDetectorElement::localToModuleTransform() const
   {
-    if (isModuleFrame()) {
-      return Amg::Transform3D(); // Identity
-    } else {
-      return m_otherSide->transform().inverse() * transform();
-    }
+    return transform().inverse() * moduleTransform();
+    // if (isModuleFrame()) {
+    //   return Amg::Transform3D(); // Identity
+    // } else {
+    //   return m_otherSide->transform().inverse() * transform();
+    // }
   }
 
   bool