diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/ExtendedAlignableTransform.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/ExtendedAlignableTransform.h
new file mode 100755
index 0000000000000000000000000000000000000000..37e427afc36abc4d2449ccd5a255c1ff5afe41f0
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/ExtendedAlignableTransform.h
@@ -0,0 +1,56 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// ExtendedAlignableTransform.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_EXTENDEDALIGNABLETRANSFORM_H
+#define INDETREADOUTGEOMETRY_EXTENDEDALIGNABLETRANSFORM_H
+
+#include "GeoModelKernel/GeoAlignableTransform.h"
+#include "GeoModelKernel/GeoVFullPhysVol.h"
+
+namespace InDetDD {
+
+    /** @class ExtendedAlignableTransform 
+    
+    Class to hold alignable transform plus a pointer to the child volume and
+    optionally a frame volume.
+
+    @author: Grant Gorfine
+    - modified & maintained: Nick Styles & Andreas Salzburger 
+    */
+    
+    class ExtendedAlignableTransform
+    {
+    
+    public:
+    
+      ExtendedAlignableTransform(GeoAlignableTransform * alignableTransform, 
+    			     const GeoVFullPhysVol * child,
+    			     const GeoVFullPhysVol * frame = 0)
+        : m_alignableTransform(alignableTransform),
+          m_child(child),
+          m_frame(frame)
+      {};
+    
+      GeoAlignableTransform * alignableTransform() {return m_alignableTransform;}
+      const GeoVFullPhysVol * child()  {return m_child;}
+      const GeoVFullPhysVol * frame()  {return m_frame;}
+    
+    private:
+      
+      GeoAlignableTransform * m_alignableTransform;
+      const GeoVFullPhysVol * m_child;
+      const GeoVFullPhysVol * m_frame;
+    
+    };
+
+
+} // end namespace 
+
+#endif // InDetDDINDETREADOUTGEOMETRY_EXTENDEDALIGNABLETRANSFORM_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/InDetDD_Defs.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/InDetDD_Defs.h
new file mode 100755
index 0000000000000000000000000000000000000000..8cdbff5313863b5644899906c8ab6e0783819fdb
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/InDetDD_Defs.h
@@ -0,0 +1,20 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// InDetDD_Defs.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_INDETDD_Defs_H
+#define INDETREADOUTGEOMETRY_INDETDD_Defs_H
+
+
+namespace InDetDD {
+  enum FrameType {local, global, other};
+  enum CarrierType {holes, electrons};
+}
+
+#endif // INDETREADOUTGEOMETRY_INDETDD_DEFS_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/InDetDetectorManager.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/InDetDetectorManager.h
new file mode 100755
index 0000000000000000000000000000000000000000..5c97d50cf088137fe3f6edb6edee787f7489a726
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/InDetDetectorManager.h
@@ -0,0 +1,151 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// InDetDectorManager.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_INDETDETECTORMANAGER_H
+#define INDETREADOUTGEOMETRY_INDETDETECTORMANAGER_H
+
+// Amg
+#include "GeoPrimitives/GeoPrimitives.h"
+// GeoModel stuff
+#include "GeoModelKernel/GeoVDetectorManager.h"
+#include "InDetReadoutGeometry/InDetDD_Defs.h"
+#include "InDetReadoutGeometry/Version.h"
+#include "CLHEP/Geometry/Transform3D.h"
+// Message Stream Member
+#include "AthenaKernel/MsgStreamMember.h"
+
+// IOV SVC for alignment:
+#include "AthenaKernel/IIOVSvc.h"
+
+class StoreGateSvc;
+class AlignableTransform;
+class Identifier; 
+class AtlasDetectorID;
+
+#include <string>
+#include <map>
+#include <set>
+
+namespace InDetDD {
+
+    /** @class InDetDetectorManager
+    
+        Virtual base class for all ID detector managers.
+        
+        It implements the processKey() method for alingment
+        which calls the setAlignableTransformDelta() method which
+        is specified in the extended classes. This method supports both,
+        local and global delta's in the frame and translates it to the 
+        underlying GeoModel transform. As GeoModel (CLHEP) and tracking
+        (Amg) use different geo libraries, these are the methods that
+        act as the CLHEP <--> Amg interface
+        
+        @author: Grant Gorfine
+        - modified & maintained: Nick Styles & Andreas Salzburger 
+    */
+    class InDetDetectorManager : public GeoVDetectorManager  {
+    
+    public:
+    
+      // Constructor
+      InDetDetectorManager(StoreGateSvc * detStore, const std::string & name);
+     
+      // Destructor
+      virtual ~InDetDetectorManager();
+    
+      
+      /** Get version information */
+      const Version & getVersion() const; 
+      const std::string & getLayout() const; // eg Initial, Final, TestBeam 
+      void setVersion(const Version & version); 
+    
+      /** Alignment access */
+      void addChannel(const std::string & key, int level, FrameType frame);
+      void addFolder(const std::string & key);
+      void addSpecialFolder(const std::string & key);
+      StatusCode align( IOVSVC_CALLBACK_ARGS ) const;
+    
+      /** Invalidate cache for all detector elements */
+      virtual void invalidateAll() const = 0;
+    
+      /** Update all caches */
+      virtual void updateAll() const = 0;
+    
+      /** Check identifier is for this detector */
+      virtual bool identifierBelongs(const Identifier & id) const = 0;
+    
+      /** Declaring the Message method for further use */
+      MsgStream& msg (MSG::Level lvl) const { return m_msg.get() << lvl; }
+    	
+      /** Declaring the Method providing Verbosity Level */
+      bool msgLvl (MSG::Level lvl) const { return m_msg.get().level() <= lvl; }
+    
+    protected:
+      StoreGateSvc * m_detStore;
+    
+    private:
+      /** @class LevelInfo
+         Private helper class definition.
+         */
+      class LevelInfo {
+
+        private:
+          int m_level;
+          FrameType m_type;
+        
+        public:
+          LevelInfo(): m_level(-1), m_type(InDetDD::global) {};
+          LevelInfo(int level, FrameType frame): m_level(level), m_type(frame) {};
+        
+          int level() const {return m_level;}
+          FrameType frame() const {return m_type;} 
+          bool isGlobalDelta() const {return m_type == InDetDD::global;}
+          bool isLocalDelta() const {return m_type == InDetDD::local;} 
+          bool isValid() const {return (m_level >= 0);}
+        
+      };
+    
+      /** Retrieve level information */
+      const LevelInfo & getLevel(const std::string & key) const;
+      
+      /** Process the alignment container, calls processKey */
+      bool processAlignmentContainer(const std::string & key) const;
+      
+      /** Called by processAlignmentContainer, 
+          applies only one key on the transform Collections */
+      bool processKey(const std::string key, 
+    		  const AlignableTransform* transformCollection) const;
+    
+      /** Set method applying the delta transform (in global or local frame)
+          onto the geoModel transform : CLHEP <--> Amg interface */
+      virtual bool setAlignableTransformDelta(int level, 
+    					                      const Identifier & id, 
+    					                      const Amg::Transform3D & delta,
+    					                      FrameType frame) const = 0;
+    
+      virtual bool processSpecialAlignment(const std::string & key) const;
+      
+      virtual const AtlasDetectorID* getIdHelper() const = 0;
+    
+      //Declaring private message stream member.
+      mutable Athena::MsgStreamMember           m_msg;
+      
+      Version                                   m_version;
+      std::map<std::string, LevelInfo>          m_keys;
+      std::set<std::string>                     m_folders;
+      std::set<std::string>                     m_specialFolders;
+    
+      mutable bool                              m_suppressWarnings;
+    
+    };
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_INDETDETECTORMANAGER_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelDetectorManager.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelDetectorManager.h
new file mode 100755
index 0000000000000000000000000000000000000000..6bc5b6a458eb68cbd460f16ba13edbe104fd2622
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelDetectorManager.h
@@ -0,0 +1,168 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelDectorManager.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef InDetReadoutGeometry_PixelDetectorManager_h
+#define InDetReadoutGeometry_PixelDetectorManager_h 1
+
+#include "GeoModelKernel/GeoVPhysVol.h"
+
+#include "InDetReadoutGeometry/SiDetectorManager.h"
+#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
+#include "InDetReadoutGeometry/InDetDD_Defs.h"
+
+#include "InDetIdentifier/PixelID.h"
+
+#include <map>
+
+class StoreGateSvc;
+class Identifier; 
+class IdentifierHash;
+class GeoAlignableTransform;
+class GeoVFullPhysVol;
+class GeoVPhysVol;
+
+namespace InDetDD {
+
+    class PixelModuleDesign;
+    class SiDetectorElement;
+    class ExtendedAlignableTransform;
+    
+    /** @class PixelDetectorManager
+    
+        Dedicated detector manager extending the functionality of the SiDetectorManager
+        with dedicated pixel information, access.
+        
+        @author: Grant Gorfine
+        - modified and maintained by Nick Styles & Andreas Salzburger
+        */
+    
+    class PixelDetectorManager : public SiDetectorManager  {
+    
+     public:
+      
+      /** Constructor */
+      PixelDetectorManager(StoreGateSvc* detStore);
+    
+      /** Destructor */
+      ~PixelDetectorManager();
+    
+      /** Access to raw geometry: */
+      virtual unsigned int getNumTreeTops() const;
+      virtual PVConstLink getTreeTop(unsigned int i) const;
+    
+      /** Add a Tree top: */
+      void addTreeTop(PVLink);
+    
+      //
+      // Access Readout Elements
+      //
+      /** access to individual elements : via Identifier */
+      virtual SiDetectorElement * getDetectorElement(const Identifier &id) const;
+
+      /** access to individual elements : via IdentifierHash */
+      virtual SiDetectorElement * getDetectorElement(const IdentifierHash &idHash) const;
+
+      /** access to individual elements : via element identification */
+      SiDetectorElement * getDetectorElement(int barrel_endcap,
+                                             int layer_wheel,
+                                             int phi_module, 
+    					                     int eta_module) const;
+    
+      /** access to whole collection via Iterators */
+      virtual const SiDetectorElementCollection * getDetectorElementCollection() const;
+      virtual SiDetectorElementCollection::const_iterator getDetectorElementBegin() const;
+      virtual SiDetectorElementCollection::const_iterator getDetectorElementEnd() const;
+    
+      /** Add elememts */
+      virtual void addDetectorElement(SiDetectorElement * element);
+    
+      /** Add alignable transforms. No access to these, they will be changed by manager: */
+      virtual void addAlignableTransform (int level,
+    				                      const Identifier &id, 
+    				                      GeoAlignableTransform *xf,
+    				                      const GeoVFullPhysVol * child);
+    				                      
+      /** As above but does a dynamic_cast to GeoVFullPhysVol */
+      virtual void addAlignableTransform (int level,
+    				                      const Identifier &id, 
+    				                      GeoAlignableTransform *xf,
+    				                      const GeoVPhysVol * child);
+    
+      // DEPRECATED
+      virtual void addAlignableTransform (int,
+    				                      const Identifier &, 
+    				                      GeoAlignableTransform *) {}; // For backward compatibility
+    
+    
+      /** Initialize the neighbours. This can only be done when all elements are built. */
+      virtual void initNeighbours();
+        
+      /** Methods to query which manager we have */
+      virtual bool isPixel() const {return true;}
+    
+      /** Check identifier is for this detector */
+      virtual bool identifierBelongs(const Identifier & id) const;
+    
+      
+      /** Layers built. Deprecated. Recommend to access via numerology (see SiDetectorManager) 
+          Warning: decodes in "human-readable", e.g. using 3 out of 3 pixel layers yiels 111, the laset two out of 3 in 110, etc.
+         */
+      unsigned int getBarrelLayers() const ;
+
+      /** Layers built. Deprecated. Recommend to access via numerology (see SiDetectorManager) 
+          Warning: decodes in "human-readable", e.g. using 3 out of 3 pixel layers yiels 111, the laset two out of 3 in 110, etc.
+      */
+      unsigned int getEndcapLayers() const;
+    
+      /** Access to module design, Casts to PixelModuleDesign */
+      virtual const PixelModuleDesign * getPixelDesign(int i) const;
+    
+     private:  
+    
+      /** implements the main alignment update for delta transforms in different frames,
+          it translates into the LocalDelta or GlobalDelta function of SiDetectorManager
+      */
+      virtual bool setAlignableTransformDelta(int level, 
+    					                      const Identifier & id, 
+    					                      const Amg::Transform3D & delta,
+    					                      FrameType frame) const;
+      
+    
+      /** prevent copy and assignment */
+      const PixelDetectorManager & operator=(const PixelDetectorManager &right);
+      PixelDetectorManager(const PixelDetectorManager &right);
+    
+    
+      virtual const PixelID  * getIdHelper() const;
+    
+      // data members
+      std::vector<PVLink>                                           m_volume;
+      SiDetectorElementCollection                                   m_elementCollection;
+      typedef std::map<Identifier, ExtendedAlignableTransform *>    AlignableTransformMap;
+      std::vector< AlignableTransformMap >                          m_higherAlignableTransforms;
+      std::vector< ExtendedAlignableTransform *>                    m_alignableTransforms; 
+      const PixelID*                                                m_idHelper;
+      
+    };
+
+} // namespace InDetDD
+
+#ifndef GAUDI_NEUTRAL
+#include "CLIDSvc/CLASS_DEF.h" 
+CLASS_DEF(InDetDD::PixelDetectorManager, 18429566, 1)
+
+#endif
+
+#endif
+
+
+
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelDiodeMap.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelDiodeMap.h
new file mode 100755
index 0000000000000000000000000000000000000000..aa1a63c405d6230efbfdc6782b7a3e701103dfb8
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelDiodeMap.h
@@ -0,0 +1,195 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelDiodeMap.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Pixel Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_PIXELDIODEMAP_H
+#define INDETREADOUTGEOMETRY_PIXELDIODEMAP_H
+
+// STL classes
+#include <vector>
+#include <list>
+
+// Data member classes
+#include "InDetReadoutGeometry/PixelDiodeMatrix.h"
+
+// Input/output classes
+#include "InDetReadoutGeometry/SiCellId.h"
+#include "InDetReadoutGeometry/SiDiodesParameters.h"
+
+namespace InDetDD {
+
+class SiCellId;
+class PixelDiodeMatrix;
+
+     /** @class PixelDiodeMap
+     
+        Class used to describe the diode segmentation of a pixel module
+        - to get the position and size of a PixelDiode object
+        - to get a PixelDiode object containing a space point
+        - to get a PixelDiode object from a PixelModulePosition
+
+        @author: David Calvet
+        - modified Davide Costanzo. Replace PixelModulePosition with SiCellId
+        - modified: Grant Gorfine, Andreas Salzburger
+        */
+
+    class PixelDiodeMap {
+      
+        public:
+        
+          /** Constructor from Diode matrix description */
+          PixelDiodeMap(const PixelDiodeMatrix * diodeMatrix);
+          
+          /** Copy constructor: */
+          PixelDiodeMap(const PixelDiodeMap &map);
+          
+          /** Destructor */
+          ~PixelDiodeMap();
+          
+          /** Assignment operator */
+          PixelDiodeMap &operator=(const PixelDiodeMap &map);
+          
+          ///////////////////////////////////////////////////////////////////
+          // Const methods:
+          ///////////////////////////////////////////////////////////////////
+        
+          /** Get diodes parameters (position and size): */
+          SiDiodesParameters parameters(const SiCellId & diodeId) const;
+        
+          /** cell id for a given local position */
+          SiCellId cellIdOfPosition(const Amg::Vector2D & localPosition) const;
+        
+          /** Check if cellId is within range */
+          SiCellId cellIdInRange(const SiCellId & cellId) const;
+        
+          /** Get the neighbouring PixelDiodes of a given PixelDiode:
+             Cell for which the neighbours must be found
+             List of cells which are neighbours of the given one */
+          void neighboursOfCell(const SiCellId & cellId,
+        			std::vector<SiCellId> &neighbours) const;
+        
+          /** Compute the intersection length of two diodes:
+              return: the intersection length when the two diodes are projected on one
+              of the two axis, or 0 in case of no intersection or problem
+              nput: the two diodes for which the intersection length is computed */
+          double intersectionLength(const SiCellId &diode1, const SiCellId &diode2) const;
+        
+          // Global sensor size:
+          double leftColumn() const;
+          double rightColumn() const;
+          double leftRow() const;
+          double rightRow() const;
+          
+          double width() const;
+          double length() const;
+        
+          // Number of cells in each direction.
+          int phiDiodes() const;
+          int etaDiodes() const;
+        
+          // Total number of diodes:
+          int diodes() const;
+        
+          ///////////////////////////////////////////////////////////////////
+          // Non-const methods:
+          ///////////////////////////////////////////////////////////////////
+          /** Set general layout flag. This can be set to true to allow handling
+              of more complex layouts where cells are not lined up with each other 
+              such as bricking. Probably never will be needed.  */
+          void setGeneralLayout() {m_generalLayout = true;}
+        
+          ///////////////////////////////////////////////////////////////////
+          // Private methods:
+          ///////////////////////////////////////////////////////////////////
+        private:
+        
+          /** Compute the intersection length along one direction:
+               return 0 if no intersection
+               x1,x2 are the centers
+               dx1,dx2 are the full lengths */
+          double intersectionLength1D(const double x1,const double dx1,
+        			      const double x2,const double dx2) const;
+          
+          /** Slower method. Called by neighboursOfCell if m_generalLayout set. */
+          void neighboursOfCellGeneral(const SiCellId & cellId,
+        			                   std::vector<SiCellId> &neighbours) const;
+            
+          /** Slower method. Called by intersectionLength if m_generalLayout set. */
+          double intersectionLengthGeneral(const SiCellId &diode1,
+        				   const SiCellId &diode2) const;
+            
+        
+          ///////////////////////////////////////////////////////////////////
+          // Private data:
+          ///////////////////////////////////////////////////////////////////
+        private:
+          const PixelDiodeMatrix * m_matrix;    //!< diode matrix
+          bool m_generalLayout;                 //!< Flag set to allow for dealing wth more general layouts.
+    };
+    
+    ///////////////////////////////////////////////////////////////////
+    // Inline methods:
+    ///////////////////////////////////////////////////////////////////
+    
+    inline double PixelDiodeMap::length() const
+    {
+      return m_matrix->etaWidth();
+    }
+    
+    inline double PixelDiodeMap::width() const
+    {
+      return m_matrix->phiWidth();  
+    }
+    
+    inline double PixelDiodeMap::leftColumn() const
+    {
+      return -0.5*length();
+    }
+    
+    inline double PixelDiodeMap::rightColumn() const
+    {
+      return 0.5*length();  
+    }
+    
+    inline double PixelDiodeMap::leftRow() const
+    {
+      return -0.5*width();
+    }
+    
+    inline double PixelDiodeMap::rightRow() const
+    {
+      return 0.5*width();
+    }
+    
+    inline int PixelDiodeMap::diodes() const
+    {
+      return phiDiodes() * etaDiodes();
+    }
+    
+    inline int PixelDiodeMap::phiDiodes() const
+    {
+      return m_matrix->phiCells();
+    }
+    
+    inline int PixelDiodeMap::etaDiodes() const
+    {
+      return m_matrix->etaCells();
+    }
+    
+    inline SiCellId PixelDiodeMap::cellIdInRange(const SiCellId & cellId) const
+    {
+      if (!cellId.isValid() || 
+          cellId.phiIndex() <0 || cellId.phiIndex() >= phiDiodes() ||
+          cellId.etaIndex() <0 || cellId.etaIndex() >= etaDiodes()) return SiCellId(); // Invalid
+      return cellId; 
+    }
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_PIXELDIODEMAP_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelDiodeMatrix.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelDiodeMatrix.h
new file mode 100755
index 0000000000000000000000000000000000000000..35190f3655b9c0bab6c733b8ef997c356e9b6e7d
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelDiodeMatrix.h
@@ -0,0 +1,181 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelDiodeMatrix.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_PIXELDIODEMATRIX_H
+#define INDETREADOUTGEOMETRY_PIXELDIODEMATRIX_H
+
+#include "InDetReadoutGeometry/SiCellId.h"
+#include "GeoModelKernel/RCBase.h"
+#include "TrkDetElementBase/TrkDetElementBase.h"
+
+namespace InDetDD {
+
+   /** @class PixelDiodeMatrix
+   
+    Class  used to describe the segmentation of the pixel and allow for conversion between cell id and position.
+     
+    The class PixelDiodeMatrix represents what it calls a cell. In the context
+    of this class a cell can either be just a simple cell as one would normally
+    think of a pixel cell (eg a 50x400um or 50x600um cell) or it can be a
+    container of multiple cells. To allow for different size cells and layout,
+    it contains a lower cell, an upper cell and multiple middle
+    cells. The middle cells are all the same (so all have the same size), but
+    the upper and lower cells can be different and can have different size or be left out
+    if they are not needed. The direction of replication is also specified (eta
+    or phi direction). The size of the cells in the direction orthoganal to the
+    replication direction must all be the same (there is no check for this though).
+    
+    To help understand the structure and its use, consider the current pixel
+    geometry. The pixel module has two cell sizes short and long cells. These
+    are refered to as normal and big bellow.  The long cells are in the region
+    at the edge of the the FE chips in order to cover the gap between FE chips.
+    
+    The assembly of this structure is done when building the sensitive detector
+    in GeoModel in the class GeoPixelSiCrystal.
+    
+     - normalCell (short pixel cell) 50x400um
+     - bigCell    (long pixel cell): 50x600um 
+    
+     - singleChipRow (represents one row associated to a FE)
+       - Size: phiWidth = 50um, etaWidth = 600*2+400*16) um = 7.6 CLHEP::mm 
+       - upper cell: bigCell
+       - middle cells: 16 x normalCell
+       - lower cell: bigcell
+       - direction: eta
+     
+     - singleRow (represents a row of cells covering the full length of the 
+       module)
+       - Size: phiWidth = 50um, etaWidth = 8 * (600*2+400*16) um = 60.8 CLHEP::mm
+       - upper cell: none
+       - middle cells: 8 x singleChipRow
+       - lower cell: none
+       - direction: eta
+    
+     - fullMatrix (represents the full module)
+       - Size: phiWidth = 50 * 328 um = 16.4 CLHEP::mm, etaWidth = 60.8 CLHEP::mm
+       - upper cell: none
+       - middle cells: 328 x singleRow
+       - lower cell: non
+       - direction: phi
+    
+    Each cell knows its total size and total number of child cells in the phi and eta
+    direction. This is determined by totaling up these quantities
+    when the object is constructed.
+    
+    The structure allows for efficient navigation from cell number to 
+    position and vice-versa. There are two main methods which allow for this navigation:
+    cellIdOfPosition() (from cell id to position) and positionOfCell() (from position to cell id).
+    
+    As it is assumed that child cells fill up completely its parent, there is
+    no range check in these methods. The methods are called from PixelDiodeMap
+    where it first checks that is within range of the top level cell (refered to
+    as the top level matrix).
+    
+    See the description of these methods for more details.
+    
+    @image html pixeldiodematrix.gif
+
+    @author Grant Gorfine
+    - modified & maintained: Nick Styles, Andreas Salzburger
+    **/
+    
+    class PixelDiodeMatrix: public RCBase {
+      
+    public:
+      
+      enum Direction {phiDir, etaDir};
+      
+      /// Constructor for just a single cell.
+      PixelDiodeMatrix(double phiWidth, double etaWidth);
+      
+      /** Constructor with multiple matrices.
+          There may be zero or one lower matrix (pointer can be 0).
+          Multiple (numCells) middle matrics (must pass a non zero pointer).
+          There may be zero or one upper matrix (pointer can be 0).
+          These must all have the same width and cells in the non replicating direction. */
+      PixelDiodeMatrix(Direction direction,  // phi or eta
+    		          const PixelDiodeMatrix * lowerCell,
+    		          const PixelDiodeMatrix * middleCells,
+    		          int numCells,
+    		          const PixelDiodeMatrix * upperCells);
+      
+      /// Destructor
+      ~PixelDiodeMatrix();
+      
+      /** Return cell Id corresponding to a relative position within the matrix.
+          The cellId is modified and returns the id relative to the passed cellId.
+          That is, it adds the relative cellId to the cellId passed to the function. 
+          A pointer to the correspond cell is returned. This can be used to get the
+          size of the cell. */
+      const PixelDiodeMatrix * cellIdOfPosition(const Amg::Vector2D & position, SiCellId & cellId) const;
+      
+      /** Return position correspong to cell with relative id withing the matrix.
+          Returns the relative position added to the position passed in.
+          A pointer to the correspond cell is returned. This can be used to get the
+          size of the cell. */
+      const PixelDiodeMatrix * positionOfCell(const SiCellId & cellId, Amg::Vector2D & position) const;
+      
+      /** Width in phi (x) direction.*/
+      double phiWidth() const;
+      
+      /** Width in eta (y) direction. */
+      double etaWidth() const;
+      
+      /** Number of cells in phi (x) direction. */
+      int phiCells() const;
+      
+      /** Number of cells in eta (y) direction. */
+      int etaCells() const;
+      
+      /** Query wether the matrix is just a single cell. Mainly for internal use. */
+      bool singleCell() const;
+      
+    private:
+      double        m_phiWidth;
+      double        m_etaWidth;
+      int           m_phiCells;    
+      int           m_etaCells;
+      Direction     m_direction;
+      int m_numCells; // number of MiddleCells along m_direction direction.
+      const PixelDiodeMatrix * m_lowerCell;
+      const PixelDiodeMatrix * m_middleCells;
+      const PixelDiodeMatrix * m_upperCell;
+      bool m_singleCell;
+    
+    };
+    
+    inline double PixelDiodeMatrix::phiWidth() const
+    { 
+      return m_phiWidth;
+    }
+    
+    inline double PixelDiodeMatrix::etaWidth() const
+    { 
+      return m_etaWidth;
+    }
+    
+    inline int PixelDiodeMatrix::phiCells() const
+    { 
+      return m_phiCells;
+    }
+    
+    inline int PixelDiodeMatrix::etaCells() const
+    { 
+      return m_etaCells;
+    }
+    
+    inline bool PixelDiodeMatrix::singleCell() const
+    {
+      return m_singleCell;
+    }
+
+} // end namespace
+
+#endif //INDETREADOUTGEOMETRY_PIXELDIODEMATRIX_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelModuleDesign.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelModuleDesign.h
new file mode 100755
index 0000000000000000000000000000000000000000..e9c1274098be6a6ea3cc4ae187813b44b0e9e069
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelModuleDesign.h
@@ -0,0 +1,341 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelModuleDesign.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Pixel Detector software
+///////////////////////////////////////////////////////////////////
+
+
+#ifndef INDETREADOUTGEOMETRY_PIXELMODULEDESIGN_H
+#define INDETREADOUTGEOMETRY_PIXELMODULEDESIGN_H
+
+// Base class
+#include "InDetReadoutGeometry/SiDetectorDesign.h"
+
+// Data member classes
+#include "InDetReadoutGeometry/PixelDiodeMap.h"
+#include "InDetReadoutGeometry/PixelReadoutScheme.h"
+
+// Other includes
+#include "InDetIdentifier/PixelID.h"
+
+namespace Trk{
+ class RectangleBounds;
+ class SurfaceBounds;
+}
+
+namespace InDetDD {
+
+    class PixelDiodeMatrix;
+    
+    /** @class PixelModuleDesign
+     Class used to describe the design of a module
+      (diode segmentation and readout scheme)
+      
+      - to get the PixelReadoutCell connected to a PixelDiode
+      - to get the list of PixelDiodes connected to a PixelReadoutCell
+      
+      @author Alessandro Fornaini
+      - modified: Grant Gorfine, Nick Styles, Andreas Salzburger
+    */
+    class PixelModuleDesign : public SiDetectorDesign {
+      
+      ///////////////////////////////////////////////////////////////////
+      // Public methods:
+      ///////////////////////////////////////////////////////////////////
+    public:
+    
+      ///////////////////////////////////////////////////////////////////
+      // Constructors/destructor:
+      ///////////////////////////////////////////////////////////////////
+      
+      /** Constructor with parameters:
+           local axis corresponding to eta direction
+           local axis corresponding to phi direction
+           local axis corresponding to depth direction
+           thickness of silicon sensor
+           number of circuits in one circuit column
+           number of circuits in one circuit row
+           number of cell columns per circuit
+           number of cell rows per circuit
+           number of diode columns connected to one circuit
+           number of diode rows connected to one circuit */
+      
+      PixelModuleDesign(const double thickness,
+			const int circuitsPerColumn,
+			const int circuitsPerRow,
+			const int cellColumnsPerCircuit,
+			const int cellRowsPerCircuit,
+			const int diodeColumnsPerCircuit,
+			const int diodeRowsPerCircuit,
+			const PixelDiodeMatrix * matrix,
+			InDetDD::CarrierType carrierType,
+			int readoutSide = -1,
+			bool is3D=false);
+    
+      // Destructor:
+      virtual ~PixelModuleDesign();
+      
+      ///////////////////////////////////////////////////////////////////
+      // Const methods:
+      ///////////////////////////////////////////////////////////////////
+    
+      /** Returns distance to nearest detector active edge 
+       +ve = inside
+       -ve = outside */
+      virtual void distanceToDetectorEdge(const SiLocalPosition & localPosition, 
+    				      double & etaDist, double & phiDist) const;
+    
+      /** readout or diode id -> position, size */
+      virtual SiDiodesParameters parameters(const SiCellId & cellId) const;
+      virtual SiLocalPosition localPositionOfCell(const SiCellId & cellId) const;
+    
+      /** readout id -> id of connected diodes */
+      virtual int numberOfConnectedCells(const SiReadoutCellId & readoutId) const;
+      virtual SiCellId connectedCell(const SiReadoutCellId & readoutId, int number) const;
+    
+      /** If cell is ganged return the other cell, otherwise return an invalid id. */
+      virtual SiCellId gangedCell(const SiCellId & cellId) const;
+    
+      /** diode id -> readout id */
+      virtual SiReadoutCellId readoutIdOfCell(const SiCellId & cellId) const;
+    
+      /** position -> id */
+      virtual SiReadoutCellId readoutIdOfPosition(const SiLocalPosition & localPos) const;
+      virtual SiCellId cellIdOfPosition(const SiLocalPosition & localPos) const;
+    
+      /** Check if cell is in range. Returns the original cellId if it is in range, otherwise it returns an invalid id. */
+      virtual SiCellId cellIdInRange(const SiCellId & cellId) const;
+    
+      /** Helper method for stereo angle computation */
+      virtual HepGeom::Vector3D<double> phiMeasureSegment(const SiLocalPosition&) const;
+    
+      /** Special method for SCT (irrelevant here): */
+      virtual std::pair<SiLocalPosition,SiLocalPosition> endsOfStrip(const SiLocalPosition &position) const;
+    
+      /** Given row and column index of a diode, return position of diode center
+         ALTERNATIVE/PREFERED way is to use localPositionOfCell(const SiCellId & cellId) or 
+         rawLocalPositionOfCell method in SiDetectorElement.
+         DEPRECATED */
+       SiLocalPosition positionFromColumnRow(const int column, const int row) const;
+      
+      /** Get the neighbouring diodes of a given diode:
+          Cell for which the neighbours must be found
+          List of cells which are neighbours of the given one */
+      virtual void neighboursOfCell(const SiCellId & cellId,
+    				std::vector<SiCellId> &neighbours) const;
+        
+      /** Compute the intersection length of two diodes:
+          return: the intersection length when the two diodes are projected on one
+           of the two axis, or 0 in case of no intersection or problem
+          input: the two diodes for which the intersection length is computed */
+      double intersectionLength(const SiCellId &diode1, const SiCellId &diode2) const;
+    
+      /** Global sensor size: */
+      double sensorLeftColumn() const;
+      double sensorRightColumn() const;
+      double sensorLeftRow() const;
+      double sensorRightRow() const;
+    
+      /** Total number of diodes: */
+      int numberOfDiodes() const;
+    
+      /** Total number of circuits:*/
+      int numberOfCircuits() const;
+    
+      /** Number of cell columns per circuit:*/
+      int columnsPerCircuit() const;
+    
+      /** Number of cell rows per circuit:*/
+      int rowsPerCircuit() const;
+    
+      /** Number of cell columns per module:*/
+      int columns() const;
+    
+      /** Number of cell rows per module:*/
+      int rows() const;
+    
+      /** Method to calculate length of a module*/
+      virtual double length() const;
+     
+      /** Method to calculate average width of a module*/
+      virtual double width() const;
+     
+      /** Method to calculate minimum width of a module*/
+      virtual double minWidth() const;
+     
+      /** Method to calculate maximum width of a module*/
+      virtual double maxWidth() const;
+    
+      /** Pitch in phi direction*/
+      virtual double phiPitch() const;
+    
+      /** Pitch in phi direction*/
+      virtual double phiPitch(const SiLocalPosition & localPosition) const;
+    
+      /** Pitch in eta direction*/
+      virtual double etaPitch() const;
+    
+      /** Method to calculate eta width from a column range*/
+      double widthFromColumnRange(const int colMin, const int colMax) const;
+    
+      /** Method to calculate phi width from a row range*/
+      double widthFromRowRange(const int rowMin, const int rowMax) const;
+    
+      /** Test if near bond gap within tolerances
+         Only relevant for SCT. Always returns false for pixels.*/
+      virtual bool nearBondGap(const SiLocalPosition & localPosition, double etaTol) const;
+    
+      /** Return true if hit local direction is the same as readout direction.*/
+      virtual bool swapHitPhiReadoutDirection() const;
+      virtual bool swapHitEtaReadoutDirection() const;
+    
+      /** Element boundary*/
+      virtual const Trk::SurfaceBounds & bounds() const; 
+    
+      virtual bool is3D() const;
+      
+      ///////////////////////////////////////////////////////////////////
+      // Non-const methods:
+      ///////////////////////////////////////////////////////////////////
+    
+    
+      /** Add a new multiple connection for rows:
+         lower diode row for which the connection scheme is given
+         vector containing, for each diode, the readout cell row number 
+         to which the corresponding diode is connected */
+      void addMultipleRowConnection(const int lowerRow,
+    				const std::vector<int> &connections);
+    
+      /** Indicate that it is a more complex layout where cells are not 
+         lined up with each other. Eg bricking. Probably never will be needed. */
+      void setGeneralLayout();
+    
+      ///////////////////////////////////////////////////////////////////
+      // Private methods:
+      ///////////////////////////////////////////////////////////////////
+    private:
+    
+      PixelModuleDesign();
+    
+      // Copy constructor:
+      PixelModuleDesign(const PixelModuleDesign &design);
+      
+      // Assignment operator:
+      PixelModuleDesign &operator=(const PixelModuleDesign &design);
+     
+      
+      ///////////////////////////////////////////////////////////////////
+      // Private data:
+      ///////////////////////////////////////////////////////////////////
+    private:
+      PixelDiodeMap m_diodeMap;
+      PixelReadoutScheme m_readoutScheme;
+      mutable Trk::RectangleBounds * m_bounds;
+      bool m_is3D;
+    
+    };
+    
+    ///////////////////////////////////////////////////////////////////
+    // Inline methods:
+    ///////////////////////////////////////////////////////////////////
+    
+    inline void PixelModuleDesign::addMultipleRowConnection(const int lowerRow,
+    							const std::vector<int> &connections)
+    {
+      m_readoutScheme.addMultipleRowConnection(lowerRow,connections);
+    }
+    
+    inline double PixelModuleDesign::sensorLeftColumn() const
+    {
+      return m_diodeMap.leftColumn();
+    }
+    
+    inline double PixelModuleDesign::sensorRightColumn() const
+    {
+      return m_diodeMap.rightColumn();
+    }
+    
+    inline double PixelModuleDesign::sensorLeftRow() const
+    {
+      return m_diodeMap.leftRow();
+    }
+    
+    inline double PixelModuleDesign::sensorRightRow() const
+    {
+      return m_diodeMap.rightRow();
+    }
+    
+    inline int PixelModuleDesign::numberOfDiodes() const
+    {
+      return m_diodeMap.diodes();
+    }
+    
+    inline int PixelModuleDesign::numberOfCircuits() const
+    {
+      return m_readoutScheme.numberOfCircuits();
+    }
+    
+    inline int PixelModuleDesign::columnsPerCircuit() const
+    {
+      return m_readoutScheme.columnsPerCircuit();
+    }
+    
+    inline int PixelModuleDesign::rowsPerCircuit() const
+    {
+      return m_readoutScheme.rowsPerCircuit();
+    }
+    
+    inline int PixelModuleDesign::columns() const
+    {
+      return m_readoutScheme.columns();
+    }
+    
+    inline int PixelModuleDesign::rows() const
+    {
+      return m_readoutScheme.rows();
+    }
+    
+    inline bool PixelModuleDesign::nearBondGap(const SiLocalPosition &, double) const
+    {
+      // No bond gap in pixel module
+      return false;
+    }
+    
+    inline bool PixelModuleDesign::swapHitPhiReadoutDirection() const
+    {
+      return true;
+    }
+    
+    inline bool PixelModuleDesign::swapHitEtaReadoutDirection() const
+    {
+      return true;
+    }
+    
+    
+    inline void PixelModuleDesign::neighboursOfCell(const SiCellId & cellId,
+    						std::vector<SiCellId> &neighbours) const
+    {
+      return m_diodeMap.neighboursOfCell(cellId, neighbours);
+    }
+    
+    inline double PixelModuleDesign::intersectionLength(const SiCellId &diode1,
+    						    const SiCellId &diode2) const
+    {
+      return m_diodeMap.intersectionLength(diode1, diode2);
+    }  
+
+
+    
+    inline bool PixelModuleDesign::is3D() const 
+      { 
+	return m_is3D; 
+      } 
+
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_PIXELMODULEDESIGN_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelMultipleConnection1D.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelMultipleConnection1D.h
new file mode 100755
index 0000000000000000000000000000000000000000..9c5c49abf46b598223ab2ccfa31c2b34d370dc4b
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelMultipleConnection1D.h
@@ -0,0 +1,128 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelMultipleConnection1D.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Pixel Detector software
+///////////////////////////////////////////////////////////////////
+
+
+#ifndef INDETREADOUTGEOMETRY_PIXELMULTIPLECONNECTION1D_H
+#define INDETREADOUTGEOMETRY_PIXELMULTIPLECONNECTION1D_H
+
+#include <vector>
+
+namespace InDetDD {
+
+    /** @class PixelMultipleConnection1D
+
+         Class used to handle connection of multiple diodes to the same readout cell
+
+         @author: David Calvet
+         @modifed: Grant Gorfine, Andreas Salzburger
+      */
+
+    class PixelMultipleConnection1D {
+  
+      ///////////////////////////////////////////////////////////////////
+      // Public methods:
+      ///////////////////////////////////////////////////////////////////
+      public:
+
+        PixelMultipleConnection1D();
+
+      /** Constructor with parameters:
+          lower diode index for which the connection scheme is given
+          vector containing, for each diode, the readout cell number to which
+          the corresponding diode is connected */
+        PixelMultipleConnection1D(const int lowerIndex, const std::vector<int> &connections);
+
+
+        void set(const int lowerIndex, const std::vector<int> &connections);
+ 
+  
+        ///////////////////////////////////////////////////////////////////
+        // Const methods:
+        ///////////////////////////////////////////////////////////////////
+
+        /** Check if the readout cell is in the range; Also for index of gangedCell. */
+        bool outsideReadout(const int index) const;
+
+        /** Check if the diode is in the range: */
+        bool outsideDiode(const int cell) const;
+
+        /** Return the number of diodes that are connected to this readout cell, Must check outsideReadout first. */
+        int numberOfConnectedCells(const int index) const;
+
+        /** Return the diode index corresponding the this readout. 
+            number 0 will return the primary cell (ie diode index = readout cell index)
+            Must check outsideReadout first.*/
+        int connectedCell(const int index, unsigned int number) const;
+
+        /** Return readout cell id of this diode, Must check outsideDiode first. */
+        int readoutOfDiode(const int index) const;
+
+        /** If the diode is gnaged return the other diode. If the diode is not ganged return the same diode.
+            Must check outsideReadout first. */
+        int gangedCell(const int index) const;
+  
+        ///////////////////////////////////////////////////////////////////
+        // Private data:
+        ///////////////////////////////////////////////////////////////////
+      private:
+        int m_lowerDiode;              //!< lower diode index to which it applies
+        int m_upperDiode;              //!< upper diode index to which it applies
+        int m_lowerReadout;            //!< lower cell to which it applies
+        int m_upperReadout;            //!< upper cell to which it applies
+        std::vector< std::vector<int> > m_readoutToDiode;  //!< connection table readout -> diodes
+        std::vector<int> m_diodeToReadout;            //!< connection table diode -> readout
+        std::vector<int> m_diodeGanged;              //!< connection table diode -> other diode.
+
+        ///////////////////////////////////////////////////////////////////
+        // Private methods:
+        ///////////////////////////////////////////////////////////////////
+        void debugPrintout();
+
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+
+inline bool PixelMultipleConnection1D::outsideReadout(const int readout) const
+{
+  return (readout<m_lowerReadout || readout>m_upperReadout);
+}
+
+
+inline bool PixelMultipleConnection1D::outsideDiode(const int diode) const
+{
+  return (diode<m_lowerDiode || diode>m_upperDiode);
+}
+
+
+inline int PixelMultipleConnection1D::numberOfConnectedCells(const int index) const
+{
+  return m_readoutToDiode[index - m_lowerReadout].size();
+}
+
+inline int  PixelMultipleConnection1D::connectedCell(const int index, unsigned int number) const
+{
+  return m_readoutToDiode[index - m_lowerReadout][number];
+}
+
+inline int PixelMultipleConnection1D::readoutOfDiode(const int index) const
+{
+  return m_diodeToReadout[index - m_lowerDiode];
+}
+
+inline int PixelMultipleConnection1D::gangedCell(const int index) const
+{
+  return m_diodeGanged[index - m_lowerReadout];
+}
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_PIXELMULTIPLECONNECTION1D_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelReadoutScheme.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelReadoutScheme.h
new file mode 100755
index 0000000000000000000000000000000000000000..fb5762dd199fcfee98bdf338b24213e2dd6f39cc
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/PixelReadoutScheme.h
@@ -0,0 +1,157 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelReadoutScheme.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Pixel Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_PIXELREADOUTSCHEME_H
+#define INDETREADOUTGEOMETRY_PIXELREADOUTSCHEME_H
+
+// Data member classes
+#include "InDetReadoutGeometry/PixelMultipleConnection1D.h"
+
+// Input and output classes
+#include "InDetReadoutGeometry/SiReadoutCellId.h"
+#include "InDetReadoutGeometry/SiCellId.h"
+
+namespace InDetDD {
+
+  /** @class PixelReadoutScheme
+
+      Class used to describe the connection scheme of a diode matrix
+      to a set of readout circuits
+      - to get the readout cell connected to a diode
+      - to get the list of diodes connected to a readout cell
+
+      @author David Calvet
+      - modified on 5/10/04 Davide Costanzo. Replace PixelModulePosition with SiCellId
+      - modified: Grant Gorfine, Andreas Salzburger
+    */
+
+  class PixelReadoutScheme {
+  
+     ///////////////////////////////////////////////////////////////////
+     // Public methods:
+     ///////////////////////////////////////////////////////////////////
+    public:
+
+      ///////////////////////////////////////////////////////////////////
+      // Constructors/destructor:
+      ///////////////////////////////////////////////////////////////////
+  
+      /** Constructor with parameters:
+       
+         number of circuits in one circuit column
+         number of circuits in one circuit row
+         number of cell columns per circuit
+         number of cell rows per circuit
+         number of diode columns connected to one circuit
+         number of diode rows connected to one circuit */
+         PixelReadoutScheme(const int circuitsPerColumn,const int circuitsPerRow,
+                            const int cellColumnsPerCircuit,
+                            const int cellRowsPerCircuit,
+                            const int diodeColumnsPerCircuit,
+                            const int diodeRowsPerCircuit);
+  
+        /** Destructor: */
+         ~PixelReadoutScheme();
+  
+       ///////////////////////////////////////////////////////////////////
+       // Const methods:
+       ///////////////////////////////////////////////////////////////////
+
+        /** total number of circuits: */
+        int numberOfCircuits() const;
+
+        /** number of cell columns per circuit: */
+        int columnsPerCircuit() const;
+
+        /** number of cell rows per circuit:*/
+        int rowsPerCircuit() const;
+
+        /** number of cell columns per module:*/
+        int columns() const;
+
+        /** number of cell rows per module:*/
+        int rows() const;
+
+        /** number of cells connected to this readout.*/
+        int numberOfConnectedCells(const SiReadoutCellId & readoutId) const;
+
+        /** Cell ids of cell connected to this readout.*/
+        SiCellId connectedCell(const SiReadoutCellId & readoutId, unsigned int number) const;
+
+        /** Readout id of this diode.*/
+        SiReadoutCellId readoutIdOfCell(const SiCellId & cellId) const;
+
+        /** If cell is ganged return the other cell, otherwise return an invalid id.*/
+       SiCellId gangedCell(const SiCellId & cellId) const;
+
+     ///////////////////////////////////////////////////////////////////
+     // Non-const methods:
+     ///////////////////////////////////////////////////////////////////
+
+      /** Add a new multiple connection for rows:
+          lower diode row for which the connection scheme is given
+          vector containing, for each diode, the readout cell row number 
+           to which the corresponding diode is connected */
+      void addMultipleRowConnection(const int lowerRow, const std::vector<int> &connections);
+
+     ///////////////////////////////////////////////////////////////////
+     // Private methods:
+     ///////////////////////////////////////////////////////////////////
+    private:
+
+      PixelReadoutScheme();
+  
+     ///////////////////////////////////////////////////////////////////
+     // Private data:
+     ///////////////////////////////////////////////////////////////////
+   private:
+     PixelMultipleConnection1D m_rowConnections; //!< multiple connections for rows
+     int m_numberOfCircuits; //!< total number of circuits
+     int m_columnsPerCircuit; //!< number of cell columns per circuit
+     int m_rowsPerCircuit; //!< number of cell rows per circuit
+     int m_columns; //!< Number of columns
+     int m_rows; //!< Number of rows
+
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline PixelReadoutScheme::~PixelReadoutScheme()
+{}
+
+inline int PixelReadoutScheme::numberOfCircuits() const
+{
+  return m_numberOfCircuits;
+}
+
+inline int PixelReadoutScheme::columnsPerCircuit() const
+{
+  return m_columnsPerCircuit;
+}
+
+inline int PixelReadoutScheme::rowsPerCircuit() const 
+{
+  return m_rowsPerCircuit;
+}
+
+inline int PixelReadoutScheme::columns() const
+{
+  return m_columns;
+}
+
+inline int PixelReadoutScheme::rows() const 
+{
+  return m_rows;
+}
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_PIXELREADOUTSCHEME_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_BarrelModuleSideDesign.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_BarrelModuleSideDesign.h
new file mode 100755
index 0000000000000000000000000000000000000000..6e34388ff54fcb3ca5761b6493eb7f44f93e2fa8
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_BarrelModuleSideDesign.h
@@ -0,0 +1,224 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_BarrelModuleSideDesign.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SCT_BARRELMODULESIDEDESIGN_H
+#define INDETREADOUTGEOMETRY_SCT_BARRELMODULESIDEDESIGN_H
+
+// Base class
+#include "InDetReadoutGeometry/SCT_ModuleSideDesign.h"
+
+namespace Trk{
+ class RectangleBounds;
+ class SurfaceBounds;
+}
+
+namespace InDetDD {
+
+  class SiDiodesParameters;
+
+   /** @class SCT_BarrelModuleSideDesign
+
+      Barrel module design description for the SCT.
+
+      @author Szymon Gadomski, Alessandro Fornaini
+      - modified: Grant Gorfine, Andreas Salzburger
+   */
+
+  class SCT_BarrelModuleSideDesign : public SCT_ModuleSideDesign {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+    public:
+
+      /** Copy constructor:*/
+      SCT_BarrelModuleSideDesign(const SCT_BarrelModuleSideDesign &design);
+
+      /** Constructor with parameters:
+          strip pitch, 80 um in barrel SCT
+          strip length
+          geom position on G4 volume, care needed
+          geom position on G4 volume, care needed
+          includes detector edge and gap between decetors*/
+      SCT_BarrelModuleSideDesign(const double thickness,
+                             const int crystals,
+			     const int diodes,
+			     const int cells,
+			     const int shift,
+			     const bool swapStripReadout,
+			     InDetDD::CarrierType carrierType,
+			     const double stripPitch,
+			     const double stripLength,
+			     const double xEtaStripPatternCentre,
+			     const double xPhiStripPatternCentre,
+			     const double totalDeadLength,
+			     int readoutSide = -1);
+
+      /** Destructor: */
+      ~SCT_BarrelModuleSideDesign();
+
+      /** Assignment operator: */
+      SCT_BarrelModuleSideDesign &operator=(const SCT_BarrelModuleSideDesign &design);
+
+      ///////////////////////////////////////////////////////////////////
+      // Const methods:
+      ///////////////////////////////////////////////////////////////////
+
+      /** strip pitch */
+      virtual double stripPitch() const;
+
+      /** strip length */
+      double stripLength() const;
+
+      /** centre of the strip pattern in eta */
+      double etaStripPatternCentre() const;
+
+      /** centre of the strip pattern in phi*/
+      double phiStripPatternCentre() const;
+
+     /** Returns distance to nearest detector active edge 
+         +ve = inside
+         -ve = outside */
+      virtual void distanceToDetectorEdge(const SiLocalPosition & localPosition, double & etaDist, double & phiDist) const;
+
+      /** Test if near bond gap within tolerances */
+      virtual bool nearBondGap(const SiLocalPosition & localPosition, double etaTol) const;
+
+      /** check if the position is in active area */
+      virtual bool inActiveArea(const SiLocalPosition &chargePos, bool checkBondGap = true) const;
+
+      /** distance to the nearest diode in units of pitch, from 0.0 to 0.5, 
+          this method should be fast as it is called for every surface charge
+          in the SCT_SurfaceChargesGenerator
+           an active area check, done in the Generator anyway, is removed here*/
+      virtual double scaledDistanceToNearestDiode(const SiLocalPosition &chargePos) const;
+  
+      /** give the strip pitch (dependence on position needed for forward)  */
+      virtual double stripPitch(const SiLocalPosition & chargePos) const;
+
+      /** readout or diode id -> position, size */
+      virtual SiDiodesParameters parameters(const SiCellId & cellId) const;
+      virtual SiLocalPosition localPositionOfCell(const SiCellId & cellId) const;
+      virtual SiLocalPosition localPositionOfCluster(const SiCellId & cellId, int clusterSize) const;
+
+      /** position -> id */
+      virtual SiCellId cellIdOfPosition(const SiLocalPosition & localPos) const;
+    
+      /** this method returns the ends of the strip */
+      virtual std::pair<SiLocalPosition,SiLocalPosition> endsOfStrip(const SiLocalPosition &position) const;
+
+      /** method for stereo angle computation - returns a vector parallel to the strip being hit */
+      virtual HepGeom::Vector3D<double> phiMeasureSegment(const SiLocalPosition & ) const;
+
+      /** Method to calculate length of a module*/
+      virtual double length() const;
+
+      /** Method to calculate average width of a module */
+      virtual double width() const;
+
+      /** Method to calculate minimum width of a module */
+      virtual double minWidth() const;
+
+      /** Method to calculate maximum width of a module */
+      virtual double maxWidth() const;
+
+      /** give length of dead area */
+      virtual double deadAreaLength() const;
+
+      /** give upper boundary of dead area */
+      virtual double deadAreaUpperBoundary() const;
+
+      /** give lower boundary of dead area */
+      virtual double deadAreaLowerBoundary() const;
+  
+      /** Pitch in phi direction */
+      virtual double phiPitch() const;
+
+      /* Pitch in phi direction */
+      virtual double phiPitch(const SiLocalPosition & localPosition) const;
+
+      /** Pitch in eta direction */
+      virtual double etaPitch() const;
+
+      /** Return the surface bounds */
+      virtual const Trk::SurfaceBounds & bounds() const; 
+
+  private:
+
+      SCT_BarrelModuleSideDesign();
+
+      ///////////////////////////////////////////////////////////////////
+      // Private data:
+      ///////////////////////////////////////////////////////////////////
+
+  private:
+      double m_stripPitch; //!< strip pitch, 80 um in barrel SCT
+      double m_stripLength; //!< strip length
+      double m_xEtaStripPatternCentre; //!< geom position on G4 volume, care needed
+      double m_xPhiStripPatternCentre; //!< geom position on G4 volume, care needed
+      double m_totalDeadLength; //!< includes detector edge and gap between decetors
+      double m_xPhiAbsSize; //!< size in xPhi/2 for active area
+      double m_xEtaAbsSizeLow, m_xEtaAbsSizeHigh; //!< active area in xEta
+      Trk::RectangleBounds * m_bounds; //!< surface bound description
+  };
+
+  ///////////////////////////////////////////////////////////////////
+  // Inline methods:
+  ///////////////////////////////////////////////////////////////////
+  inline double SCT_BarrelModuleSideDesign::stripPitch() const
+  {
+    return m_stripPitch;
+  }
+
+  // this method is non trivial in forward, but in barrel it can
+  // be an inline function
+  inline double SCT_BarrelModuleSideDesign::stripPitch(const SiLocalPosition &) const
+  {
+    return m_stripPitch;
+  }
+
+
+  inline double SCT_BarrelModuleSideDesign::stripLength() const
+  {
+    return m_stripLength;
+  }
+
+  inline double SCT_BarrelModuleSideDesign::etaStripPatternCentre() const
+  {
+    return m_xEtaStripPatternCentre;
+  }
+
+  inline double SCT_BarrelModuleSideDesign::phiStripPatternCentre() const
+  {
+    return  m_xPhiStripPatternCentre;
+  }
+
+  // Same as stripPitch
+  inline double SCT_BarrelModuleSideDesign::phiPitch(const SiLocalPosition &) const
+  {
+    return m_stripPitch;
+  }
+
+  // Same as stripPitch
+  inline double SCT_BarrelModuleSideDesign::phiPitch() const
+  {
+    return m_stripPitch;
+  }
+
+  // Same as active length
+  inline double SCT_BarrelModuleSideDesign::etaPitch() const
+  {
+    return length();
+  }
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SCT_BARRELMODULESIDEDESIGN_H
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_DetectorManager.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_DetectorManager.h
new file mode 100755
index 0000000000000000000000000000000000000000..925a40cc14c66de81b8ebb5023294fa7ada5aa19
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_DetectorManager.h
@@ -0,0 +1,143 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_DetectorManager.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SCT_DETECTORMANAGER_H
+#define INDETREADOUTGEOMETRY_SCT_DETECTORMANAGER_H
+
+#include "GeoPrimitives/GeoPrimitives.h"
+
+#include "GeoModelKernel/GeoVPhysVol.h"
+
+#include "InDetReadoutGeometry/SiDetectorManager.h"
+#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
+#include "InDetReadoutGeometry/InDetDD_Defs.h"
+
+#include "InDetIdentifier/SCT_ID.h"
+  
+class StoreGateSvc;
+class Identifier; 
+class IdentifierHash;
+class GeoAlignableTransform;
+class GeoVFullPhysVol;
+class GeoVPhysVol;
+
+namespace InDetDD {
+
+  class SiDetectorElement;
+  class ExtendedAlignableTransform;
+  class SCT_ModuleSideDesign;
+
+  /** @class SCT_DetectorManager
+  
+      Dedicated detector manager extending the functionality of the SiDetectorManager
+      with dedicated SCT information, access.
+      
+      @author: Grant Gorfine
+      - modified and maintained by Nick Styles & Andreas Salzburger
+      */
+      
+  class SCT_DetectorManager : public SiDetectorManager  {
+
+    public:
+    
+      // Constructor
+      SCT_DetectorManager( StoreGateSvc* detStore );
+     
+      // Destructor
+      virtual ~SCT_DetectorManager();
+     
+      /** Access Raw Geometry */
+      virtual unsigned int getNumTreeTops()           const;                  
+      virtual PVConstLink  getTreeTop(unsigned int i) const;
+      /** Add tree top */
+      void addTreeTop(PVLink); 
+    
+    
+      //
+      // Access Readout Elements
+      //
+    
+      /** access to individual elements via Identifier */
+      virtual SiDetectorElement * getDetectorElement(const Identifier &id) const;
+
+      /** access to individual elements via IdentifierHash */
+      virtual SiDetectorElement * getDetectorElement(const IdentifierHash &idHash) const;
+      
+      /** access to individual elements via module numbering schema */
+      SiDetectorElement * getDetectorElement(int barrel_endcap, int layer_wheel, int phi_module, int eta_module, int side) const;
+    
+      /** access to whole collectiom via iterators */
+      virtual const SiDetectorElementCollection * getDetectorElementCollection() const;
+      virtual SiDetectorElementCollection::const_iterator getDetectorElementBegin() const;
+      virtual SiDetectorElementCollection::const_iterator getDetectorElementEnd() const;
+    
+      /** Add elememts during construction */
+      virtual void addDetectorElement(SiDetectorElement * element);
+    
+      /** Add alignable transforms. No access to these, they will be changed by manager: */
+      virtual void addAlignableTransform (int level,
+    				                      const Identifier &id, 
+    				                      GeoAlignableTransform *xf,
+    				                      const GeoVFullPhysVol * child);
+      
+      /**  As above but does a dynamic_cast to GeoVFullPhysVol */
+      virtual void addAlignableTransform (int level,
+    				                      const Identifier &id, 
+    				                      GeoAlignableTransform *xf,
+    				                      const GeoVPhysVol * child); 
+    
+      // DEPRECATED
+      virtual void addAlignableTransform (int, const Identifier &, GeoAlignableTransform *) {}; // For backward compatibility
+    
+      /** Initialize the neighbours. This can only be done when all elements are built. */
+      virtual void initNeighbours();
+        
+      /** Methods to query which manager we have */
+      virtual bool isPixel() const {return false;}
+    
+      /** Check identifier is for this detector */
+      virtual bool identifierBelongs(const Identifier & id) const;
+    
+      /** Access to module design, casts to SCT_ModuleSideDesign */
+      const SCT_ModuleSideDesign * getSCT_Design(int i) const;
+    
+    private:  
+      /** implements the main alignment update for delta transforms in different frames,
+          it translates into the LocalDelta or GlobalDelta function of SiDetectorManager
+      */
+      virtual bool setAlignableTransformDelta(int level, 
+    					  const Identifier & id, 
+    					  const Amg::Transform3D & delta,
+    					  FrameType frame) const;
+      
+      /** Prevent copy and assignment */
+      const SCT_DetectorManager & operator=(const SCT_DetectorManager &right);
+      SCT_DetectorManager(const SCT_DetectorManager &right); 
+    
+      virtual const SCT_ID  * getIdHelper() const;
+       
+      // Private member data
+      std::vector<PVLink>                                           m_volume;  
+      SiDetectorElementCollection                                   m_elementCollection;
+      typedef std::map<Identifier, ExtendedAlignableTransform *>    AlignableTransformMap;
+      std::vector< AlignableTransformMap >                          m_higherAlignableTransforms;
+      std::vector< ExtendedAlignableTransform *>                    m_alignableTransforms; 
+      std::vector< ExtendedAlignableTransform *>                    m_moduleAlignableTransforms; 
+      const SCT_ID*                                                 m_idHelper;
+    };
+
+} // namespace InDetDD
+
+#ifndef GAUDI_NEUTRAL
+#include "CLIDSvc/CLASS_DEF.h" 
+CLASS_DEF(InDetDD::SCT_DetectorManager, 72488296, 1) 
+#endif
+
+#endif // INDETREADOUTGEOMETRY_SCT_DETECTORMANAGER_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardFrameTransformation.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardFrameTransformation.h
new file mode 100755
index 0000000000000000000000000000000000000000..c0781b019f093b6f4006a4d9d8a3daf698a8bdeb
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardFrameTransformation.h
@@ -0,0 +1,108 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ForwardFrameTransformation.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SCT_FORWARDFRAMETRANSFORMATION_H
+#define INDETREADOUTGEOMETRY_SCT_FORWARDFRAMETRANSFORMATION_H
+
+namespace InDetDD {
+
+class SCT_ForwardPolarPosition;
+class SiLocalPosition;
+
+   
+  /** @class SCT_ForwardFrameTransformation
+
+      Class that connect cartesian and pokar coordinates
+
+      @author: Grant Gorfine
+      - modified & maintained : Andreas Salzburger */
+
+  class SCT_ForwardFrameTransformation {
+
+    ///////////////////////////////////////////////////////////////////
+    // Public methods:
+    ///////////////////////////////////////////////////////////////////
+    public:
+
+      /** Copy constructor: */
+      SCT_ForwardFrameTransformation(const SCT_ForwardFrameTransformation &frame);
+
+      /** Constructor with parameters:
+          eta coordinate of module center
+          phi coordinate of module center
+          r from module center to beam */
+      SCT_ForwardFrameTransformation(const double etaCenter,const double phiCenter,
+                                 const double radius);
+
+      /** Destructor: */
+      ~SCT_ForwardFrameTransformation();
+
+      /** Assignment operator: */
+      SCT_ForwardFrameTransformation &operator=(const SCT_ForwardFrameTransformation &frame);
+
+      ///////////////////////////////////////////////////////////////////
+      // Const methods:
+      ///////////////////////////////////////////////////////////////////
+
+      /** eta coordinate of module center: */
+      double etaCenter() const;
+
+      /** phi coordinate of modulecenter: */
+      double phiCenter() const;
+
+      /** r from module center to beam:*/
+      double radius() const;
+
+      /** create a SCT_ForwardPolarPosition from a SiLocalPosition */
+      SCT_ForwardPolarPosition polarFromCartesian(const SiLocalPosition& cartesian) const;
+  
+      /** create a SiLocalPosition from a SCT_ForwardPolarPosition */
+      SiLocalPosition cartesianFromPolar(const SCT_ForwardPolarPosition& polar) const;
+ 
+      ///////////////////////////////////////////////////////////////////
+      // Private methods:
+      ///////////////////////////////////////////////////////////////////
+   private:
+
+      SCT_ForwardFrameTransformation();
+
+      ///////////////////////////////////////////////////////////////////
+      // Private data:
+      ///////////////////////////////////////////////////////////////////
+  private:
+    double m_etaCenter; //!< eta coordinate of module center
+    double m_phiCenter; //!< phi coordinate of module center
+    double m_radius; //!< r from module center to beam
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SCT_ForwardFrameTransformation::~SCT_ForwardFrameTransformation()
+{}
+
+inline double SCT_ForwardFrameTransformation::etaCenter() const
+{
+  return m_etaCenter;
+}
+
+inline double SCT_ForwardFrameTransformation::phiCenter() const
+{
+  return m_phiCenter;
+}
+
+inline double SCT_ForwardFrameTransformation::radius() const
+{
+  return m_radius;
+}
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SCT_FORWARDFRAMETRANSFORMATION_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardModuleSideDesign.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardModuleSideDesign.h
new file mode 100755
index 0000000000000000000000000000000000000000..bce84103d2422cfd475cdb9f40bb1f3e6ce9a4b4
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardModuleSideDesign.h
@@ -0,0 +1,214 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ForwardModuleSideDesign.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SCT_FORWARDMODULESIDEDESIGN_H
+#define INDETREADOUTGEOMETRY_SCT_FORWARDMODULESIDEDESIGN_H
+
+// Base class
+#include "InDetReadoutGeometry/SCT_ModuleSideDesign.h"
+
+//Data member classes
+#include "InDetReadoutGeometry/SCT_ForwardFrameTransformation.h"
+#include "InDetReadoutGeometry/SCT_ForwardModuleSideGeometry.h"
+
+namespace Trk{
+ class TrapezoidBounds;
+ class SurfaceBounds;
+}
+
+
+namespace InDetDD {
+
+  /** 
+  @class SCT_ForwardModuleSideDesign
+
+   Design descriptor for forward modules in the SCT,
+   carries the bounds, and readout information.
+
+  @author Grant Gorfine
+  - modified & maintained: Nick Styles, Andreas Salzburger
+  */
+
+  class SCT_ForwardModuleSideDesign : public SCT_ModuleSideDesign {
+
+  public:
+
+     /** Constructor with parameters:
+         local axis corresponding to eta direction
+         local axis corresponding to phi direction
+         local axis corresponding to depth direction
+         thickness of silicon sensor
+         number of crystals within module side
+         number of diodes within crystal
+         number of cells within module side
+         index of diode connected to cell with index 0
+         r from inner crystal center to beam
+         inner crystal half height
+         r from outer crystal (if present) center to beam
+         outer crystal (if present) half height
+         strip step in angle (same for both crystals)
+         eta coordinate of crystal center
+        phi coordinate of crystal center */
+      SCT_ForwardModuleSideDesign(const double thickness,
+			      const int crystals,const int diodes,
+			      const int cells,const int shift,
+			      const bool swapStripReadout,
+			      InDetDD::CarrierType carrierType,
+			      const double radius1,const double halfHeight1,
+			      const double radius2,const double halfHeight2,
+			      const double step,
+			      const double etaCenter,const double phiCenter,
+			      int readoutSide = -1);
+
+      /** Destructor: */
+      virtual ~SCT_ForwardModuleSideDesign();
+
+      ///////////////////////////////////////////////////////////////////
+      // Const methods:
+      ///////////////////////////////////////////////////////////////////
+
+      /** Returns distance to nearest detector active edge 
+          +ve = inside
+          -ve = outside */
+      virtual void distanceToDetectorEdge(const SiLocalPosition & localPosition, 
+      				      double & etaDist, double & phiDist) const;
+
+      /** Test if near bond gap within tolerances */
+      virtual bool nearBondGap(const SiLocalPosition & localPosition, double etaTol) const;
+ 
+      /** check if the position is in active area */
+      virtual bool inActiveArea(const SiLocalPosition &chargePos, bool checkBondGap = true) const;
+
+      /** give distance to the nearest diode in units of pitch, from 0.0 to 0.5, 
+           this method should be fast as it is called for every surface charge
+           in the SCT_SurfaceChargesGenerator */
+      virtual double scaledDistanceToNearestDiode(const SiLocalPosition &chargePos) const;
+  
+      /** give the strip pitch (dependence on position needed for forward) */
+      virtual double stripPitch(const SiLocalPosition & chargePos) const;
+
+      /** give the strip pitch (For Forward returns pitch at center) */
+      virtual double stripPitch() const;
+
+      /** readout or diode id -> position, size */
+      virtual SiDiodesParameters parameters(const SiCellId & cellId) const;
+      virtual SiLocalPosition localPositionOfCell(const SiCellId & cellId) const;
+      virtual SiLocalPosition localPositionOfCluster(const SiCellId & cellId, int clusterSize) const;
+
+      /** position -> id */
+      virtual SiCellId cellIdOfPosition(const SiLocalPosition & localPos) const;
+
+      /** this method returns the ends of the strip */
+      virtual std::pair<SiLocalPosition,SiLocalPosition> endsOfStrip(const SiLocalPosition &position) const;
+  
+      /** method for stereo angle computation - returns a vector parallel to the strip being hit */
+      virtual HepGeom::Vector3D<double> phiMeasureSegment(const SiLocalPosition &position) const;
+
+      /** Nominal center radius of double wafer. */
+      double radius() const;
+
+      /** Method to calculate length of a module */
+      virtual double length() const;
+
+      /** Method to calculate average width of a module */
+      virtual double width() const;
+
+      /** Method to calculate minimum width of a module */
+      virtual double minWidth() const;
+
+      /** Method to calculate maximum width of a module */
+      virtual double maxWidth() const;
+  
+      /** give length of dead area */
+      virtual double deadAreaLength() const;
+  
+      /** give upper boundary of dead area */
+      virtual double deadAreaUpperBoundary() const;
+  
+      /** give lower boundary of dead area */
+      virtual double deadAreaLowerBoundary() const;
+ 
+      /** Pitch in phi direction */
+      virtual double phiPitch() const;
+
+      /** Pitch in phi direction */
+      virtual double phiPitch(const SiLocalPosition & localPosition) const;
+
+      /** Pitch in eta direction */
+      virtual double etaPitch() const;
+
+      /** Angular pitch */
+      double angularPitch() const;
+
+      /** Shape of element */
+      virtual DetectorShape shape() const;
+
+      /** Element boundary */
+      virtual const Trk::SurfaceBounds & bounds() const; 
+
+    private:
+
+       /** Forbidden default constructor */
+       SCT_ForwardModuleSideDesign();
+  
+       /** Copy constructor: */
+       SCT_ForwardModuleSideDesign(const SCT_ForwardModuleSideDesign &design);
+
+       /** Assignment operator: */
+       SCT_ForwardModuleSideDesign &operator=(const SCT_ForwardModuleSideDesign &design);
+
+        ///////////////////////////////////////////////////////////////////
+        // Private data:
+        ///////////////////////////////////////////////////////////////////
+
+    private:
+       SCT_ForwardModuleSideGeometry m_geometry; //!< geometry of module side
+       SCT_ForwardFrameTransformation m_frame; //!< polar / cartesian frame transformation
+       Trk::TrapezoidBounds * m_bounds;
+    };
+    
+  
+  ///////////////////////////////////////////////////////////////////
+  // Inline methods:
+  ///////////////////////////////////////////////////////////////////
+  
+  
+  inline double SCT_ForwardModuleSideDesign::radius() const
+  {
+    return m_geometry.radius();
+  }
+  
+  // Same as stripPitch
+  inline double SCT_ForwardModuleSideDesign::phiPitch(const SiLocalPosition & localPosition) const
+  {
+    return stripPitch(localPosition);
+  }
+  
+  // Same as stripPitch
+  inline double SCT_ForwardModuleSideDesign::phiPitch() const
+  {
+    return stripPitch();
+  }
+  
+  // Same as active length
+  inline double SCT_ForwardModuleSideDesign::etaPitch() const
+  {
+    return length();
+  }
+  
+  // Same as active length
+  inline double SCT_ForwardModuleSideDesign::angularPitch() const
+  {
+    return m_geometry.angularPitch();
+  }
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SCT_FORWARDMODULESIDEDESIGN_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardModuleSideGeometry.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardModuleSideGeometry.h
new file mode 100755
index 0000000000000000000000000000000000000000..50a75064e9511041c4f5a84e8314b6f988e2455b
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardModuleSideGeometry.h
@@ -0,0 +1,211 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ForwardModuleSideGeometry.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SCT_FORWARDMODULESIDEGEOMETRY_H
+#define INDETREADOUTGEOMETRY_SCT_FORWARDMODULESIDEGEOMETRY_H
+
+#include "InDetReadoutGeometry/SiLocalPosition.h"
+#include "InDetReadoutGeometry/SCT_ForwardPolarPosition.h"
+
+namespace InDetDD {
+
+  /**
+     @class SCT_ForwardModuleSideGeometry
+     
+     Geometry descriptor holding strig number,
+     crystel inner and outer half length & radius.
+     
+     @author Grant Gorfine
+     
+   */
+
+  class SCT_ForwardModuleSideGeometry {
+
+      ///////////////////////////////////////////////////////////////////
+      // Public methods:
+      ///////////////////////////////////////////////////////////////////
+    public:
+
+      /** Constructor with parameters:
+         r from inner crystal center to beam
+         inner crystal half height
+         r from outer crystal (if present) center to beam
+         outer crystal (if present) half height
+         number of strips (same for both crystals)
+         strip step in angle (same for both crystals)
+         number of crystals per module side */
+
+      SCT_ForwardModuleSideGeometry(const double radius1, const double halfHeight1,
+                                    const double radius2, const double halfHeight2,
+                                    const int strips, const double step, 
+                                    const int nCrystals);
+
+      /** Destructor: */
+      ~SCT_ForwardModuleSideGeometry();
+
+      ///////////////////////////////////////////////////////////////////
+      // Const methods:
+      ///////////////////////////////////////////////////////////////////
+
+      /** Nominal center radius of double wafer. */
+      double radius() const;
+
+      /** r from inner crystal center to beam:*/
+      double radius1() const;
+
+      /** inner crystal half height: */
+      double halfHeight1() const;
+
+      /** r from outer crystal (if present) center to beam: */
+      double radius2() const;
+
+      /** outer crystal (if present) half height: */
+      double halfHeight2() const;
+
+      /** number of strips (same for both crystals): */
+      int strips() const;
+
+      /** strip step in angle (same for both crystals): */
+      double step() const;
+      double angularPitch() const;
+
+      /** number of crystals per module side */
+      int nCrystals() const;
+ 
+      void distanceToDetectorEdge(const SiLocalPosition & localPosition,
+ 			      const SCT_ForwardPolarPosition &polarPos,
+			      double & etaDist, double & phiDist) const;
+  
+      /** Test if near bond gap within tolerances */
+      bool nearBondGap(const SiLocalPosition & localPosition, double etaTol) const;
+ 
+      /** check if position is in active area */
+      bool inActiveArea(const SiLocalPosition & chargePosition, bool checkBondGap = true) const;
+
+      /** DEPRECATED */
+      bool inActiveArea(const SCT_ForwardPolarPosition &polarPos) const;
+  
+      /** give the strip pitch (dependence on position needed for forward)  */
+      double stripPitch(const SCT_ForwardPolarPosition &polarPos) const;
+  
+      /** give distance to the nearest diode in units of pitch, from 0.0 to 0.5, 
+          this method should be fast as it is called for every surface charge
+          in the SCT_SurfaceChargesGenerator */
+      double scaledDistanceToNearestDiode(const SCT_ForwardPolarPosition& polarPos) const;
+ 
+      /** Method to calculate length of a module*/
+      double length() const;
+
+      /** Method to calculate average width of a module*/
+      double width() const;
+
+      /** Method to calculate minimum width of a module*/
+      double minWidth() const;
+
+      /** Method to calculate maximum width of a module */
+      double maxWidth() const;
+ 
+      /** give length of dead area */
+      double deadAreaLength() const;
+
+      /** give upper boundary of dead area */
+      double deadAreaUpperBoundary() const;
+
+      /** give lower boundary of dead area */
+      double deadAreaLowerBoundary() const;
+ 
+       ///////////////////////////////////////////////////////////////////
+       // Private methods:
+       ///////////////////////////////////////////////////////////////////
+    private:
+
+       SCT_ForwardModuleSideGeometry();
+
+       ///////////////////////////////////////////////////////////////////
+       // Private data:
+       ///////////////////////////////////////////////////////////////////
+    private:
+      double m_radius; //!< r from nominal element center to beam
+      double m_radius1; //!< r from inner crystal center to beam
+      double m_halfHeight1; //!< inner crystal half height
+      double m_radius2; //!< r from outer crystal (if present) center to beam
+      double m_halfHeight2; //!< outer crystal (if present) half height
+      int m_strips; //!< number of strips (same for both crystals) 
+      double m_step; //!< strip step in angle (same for both crystals)
+      int m_nCrystals; //!< number of crystals per module side
+      double m_leftSide; //!< left border of module in angle
+      double m_rightSide; //!< right border of module in angle
+      double m_upperSide1; //!< upper side of crystal 1 
+      double m_lowerSide1; //!< lower side of crystal 1 
+      double m_upperSide2; //!< upper side of crystal 2 
+      double m_lowerSide2; //!< lower side of crystal 2 
+
+      double m_halfLength; //!< top = +halfLength, bot = -halfLength  
+      double m_deadRegionUpper;   //!< relative to center of detector.
+      double m_deadRegionLower;   //!< relative to center of detector.
+      double m_tangent;  //!< tan(theta) at edge = (halfWidth) / (radius) 
+
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SCT_ForwardModuleSideGeometry::~SCT_ForwardModuleSideGeometry()
+{}
+
+inline double SCT_ForwardModuleSideGeometry::radius1() const
+{
+  return m_radius1;
+}
+
+inline double SCT_ForwardModuleSideGeometry::radius() const
+{
+  return m_radius;
+}
+
+inline double SCT_ForwardModuleSideGeometry::halfHeight1() const
+{
+  return m_halfHeight1;
+}
+
+inline double SCT_ForwardModuleSideGeometry::radius2() const
+{
+  return m_radius2;
+}
+
+inline double SCT_ForwardModuleSideGeometry::halfHeight2() const
+{
+  return m_halfHeight2;
+}
+
+inline int SCT_ForwardModuleSideGeometry::strips() const
+{
+  return m_strips;
+}
+
+inline double SCT_ForwardModuleSideGeometry::step() const
+{
+  return m_step;
+}
+
+inline double SCT_ForwardModuleSideGeometry::angularPitch() const
+{
+  return m_step;
+}
+
+inline int SCT_ForwardModuleSideGeometry::nCrystals() const
+{
+  return m_nCrystals;
+}
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SCT_FORWARDMODULESIDEGEOMETRY_H
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardPolarPosition.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardPolarPosition.h
new file mode 100755
index 0000000000000000000000000000000000000000..a3d72d88f67b0417fdf978a165d75399688e670a
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ForwardPolarPosition.h
@@ -0,0 +1,88 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ForwardPolarPosition.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SCT_FORWARDPOLARPOSITION_H
+#define INDETREADOUTGEOMETRY_SCT_FORWARDPOLARPOSITION_H
+
+#include <string>
+
+namespace InDetDD {
+
+  /** @class SCT_ForwardPolarPosition 
+  
+      2D position in polar coordinates for the polar frame in
+      the SCT endcaps.
+  
+      @author Grant Gorfine
+    */
+  class SCT_ForwardPolarPosition {
+  
+  public:
+  
+    // Implicit constructor
+    SCT_ForwardPolarPosition();
+  
+    // Copy constructor:
+    SCT_ForwardPolarPosition(const SCT_ForwardPolarPosition &polar);
+  
+    /** Constructor with parameters:
+        r coordinate of point
+       theta coordinate of point */
+    SCT_ForwardPolarPosition(const double r,const double theta);
+  
+    // Destructor:
+    virtual ~SCT_ForwardPolarPosition();
+  
+    // Assignment operator:
+    SCT_ForwardPolarPosition &operator=(const SCT_ForwardPolarPosition &polar);
+  
+    ///////////////////////////////////////////////////////////////////
+    // Const methods:
+    ///////////////////////////////////////////////////////////////////
+  
+    /** r coordinate of point: */
+    double r() const;
+  
+    /** theta coordinate of point: */
+    double theta() const;
+  
+    //Comparison operator
+    virtual bool operator==(const SCT_ForwardPolarPosition &polar) const;
+   
+    //Print method:
+    virtual std::string print() const;
+
+    ///////////////////////////////////////////////////////////////////
+    // Private data:
+    ///////////////////////////////////////////////////////////////////
+  private:
+    double m_r; // r coordinate of point
+    double m_theta; // theta coordinate of point
+  };
+  
+  ///////////////////////////////////////////////////////////////////
+  // Inline methods:
+  ///////////////////////////////////////////////////////////////////
+  
+  inline double SCT_ForwardPolarPosition::r() const
+  {
+    return m_r;
+  }
+  
+  inline double SCT_ForwardPolarPosition::theta() const
+  {
+    return m_theta;
+  }
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SCT_FORWARDPOLARPOSITION_H
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ModuleSideDesign.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ModuleSideDesign.h
new file mode 100755
index 0000000000000000000000000000000000000000..84681b1dbe8afd83ff3535a59254e5faee8c5618
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ModuleSideDesign.h
@@ -0,0 +1,227 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ModuleSideDesign.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+
+#ifndef INDETREADOUTGEOMETRY_SCT_MODULESIDEDESIGN_H
+#define INDETREADOUTGEOMETRY_SCT_MODULESIDEDESIGN_H
+
+// Base class
+#include "InDetReadoutGeometry/SiDetectorDesign.h"
+
+// Data member class
+#include "InDetReadoutGeometry/SCT_ReadoutScheme.h"
+
+// Other includes
+#include "InDetIdentifier/SCT_ID.h"
+
+namespace InDetDD {
+
+  /** @class SCT_ModuleSideDesign
+  
+     Base class for the SCT module side design,
+     extended by the Forward and Barrel module design   
+
+      @author Alessandro Fornaini, Grant Gorfine
+  */
+  
+  class SCT_ModuleSideDesign : public SiDetectorDesign {
+    
+    public:
+    
+      /** Constructor with parameters:
+         local axis corresponding to eta direction
+         local axis corresponding to phi direction
+         local axis corresponding to depth direction
+         thickness of silicon sensor
+         number of crystals within module side
+         number of diodes within crystal
+         number of cells within module side
+         index of diode connected to cell with index 0 */
+      SCT_ModuleSideDesign(const double thickness,
+    		       const bool phiSymmetric,
+    		       const bool etaSymmetric,
+    		       const bool depthSymmetric,
+    		       const int crystals,
+    		       const int diodes,
+    		       const int cells,
+    		       const int shift,
+    		       const bool swapStripReadout,
+    		       InDetDD::CarrierType carrierType,
+    		       int readoutSide);
+      
+      /** Destructor: */
+      virtual ~SCT_ModuleSideDesign();
+    
+      /** readout id -> id of connected diodes
+          Not particularly useful for the SCT but implemented to keep a uniform interface. */
+      virtual int numberOfConnectedCells(const SiReadoutCellId & readoutId) const;
+      virtual SiCellId connectedCell(const SiReadoutCellId & readoutId, int number) const;
+     
+      /** If cell is ganged return the other cell, otherwise return an invalid id.
+          Not particularly useful for the SCT but implemented to keep a uniform interface.
+          For SCT always returns an invalid id. */
+      virtual SiCellId gangedCell(const SiCellId & cellId) const;
+    
+      /** diode id -> readout id */
+      virtual SiReadoutCellId readoutIdOfCell(const SiCellId & cellId) const;
+    
+      /** position -> id */
+      virtual SiReadoutCellId readoutIdOfPosition(const SiLocalPosition & localPos) const;
+    
+      /** id -> position */
+      virtual SiLocalPosition localPositionOfCell(const SiCellId & cellId) const = 0;
+      virtual SiLocalPosition localPositionOfCluster(const SiCellId & cellId, int cluserSize) const = 0;
+    
+      /** Check if cell is in range. Returns the original cellId if it is in range, otherwise it returns an invalid id. */
+      virtual SiCellId cellIdInRange(const SiCellId & cellId) const;
+    
+      /** Get the neighbouring diodes of a given diode:
+          Cell for which the neighbours must be found
+           List of cells which are neighbours of the given one */
+      virtual void neighboursOfCell(const SiCellId & cellId,
+    				std::vector<SiCellId> &neighbours) const;
+        
+      /** check if the position is in active area */
+      virtual bool inActiveArea(const SiLocalPosition &chargePos, bool checkBondGap = true) const = 0;
+    
+      /** give distance to the nearest diode in units of pitch, from 0.0 to 0.5, 
+         this method should be fast as it is called for every surface charge
+         in the SCT_SurfaceChargesGenerator */
+      virtual double scaledDistanceToNearestDiode(const SiLocalPosition &chargePos) const = 0;
+      
+      /** give the strip pitch (dependence on position needed for forward)  */
+      virtual double stripPitch(const SiLocalPosition & chargePos) const = 0;
+    
+      /** give the strip pitch (For Forward returns pitch at center) */
+      virtual double stripPitch() const = 0;
+    
+      /** give the ends of strips */
+      virtual std::pair<SiLocalPosition,SiLocalPosition> 
+                        endsOfStrip(const SiLocalPosition &position) const = 0;
+     
+      /** gives position of strip center
+         ALTERNATIVE/PREFERED way is to use localPositionOfCell(const SiCellId & cellId) or 
+         rawLocalPositionOfCell method in SiDetectorElement.
+         DEPRECATED */
+      virtual SiLocalPosition positionFromStrip(const int stripNumber) const;
+    
+      /** give length of dead area */
+      virtual double deadAreaLength() const = 0;
+    
+      /** give upper boundary of dead area */
+      virtual double deadAreaUpperBoundary() const = 0;
+    
+      /** give lower boundary of dead area */
+      virtual double deadAreaLowerBoundary() const = 0;
+                          
+      /** number of crystals within module side: */
+      int crystals() const;
+    
+      /** number of strips within crystal: */
+      int diodes() const;
+    
+      /** number of readout stips within module side: */
+      int cells() const;
+    
+      /** number of edge strips before first readout strip. */
+      int shift() const;
+    
+      /** Return true if hit local direction is the same as readout direction. */
+      virtual bool swapHitPhiReadoutDirection() const;
+      virtual bool swapHitEtaReadoutDirection() const;
+
+    private:
+    
+      SCT_ModuleSideDesign();
+    
+      // Copy constructor:
+      SCT_ModuleSideDesign(const SCT_ModuleSideDesign &design);
+    
+      // Assignment operator:
+      SCT_ModuleSideDesign &operator=(const SCT_ModuleSideDesign &design);
+    
+    
+      ///////////////////////////////////////////////////////////////////
+      // Private data:
+      ///////////////////////////////////////////////////////////////////
+    private:
+      SCT_ReadoutScheme m_scheme; //!< connection between diodes and readout cells
+      bool m_swapStripReadout;    //!< Flag to indicate if readout direction is opposite 
+                                  //!< to hit local phi direction 
+    
+    
+    };
+    
+    ///////////////////////////////////////////////////////////////////
+    // Inline methods:
+    ///////////////////////////////////////////////////////////////////
+    inline int SCT_ModuleSideDesign::crystals() const
+    {
+        return m_scheme.crystals();
+    }
+    
+    inline int SCT_ModuleSideDesign::diodes() const
+    {
+        return m_scheme.diodes();
+    }
+    
+    inline int SCT_ModuleSideDesign::cells() const
+    {
+        return m_scheme.cells();
+    }
+    
+    inline int SCT_ModuleSideDesign::shift() const
+    {
+        return m_scheme.shift();
+    }
+    
+    
+    inline int SCT_ModuleSideDesign::numberOfConnectedCells(const SiReadoutCellId & readoutId) const
+    {
+      return m_scheme.numberOfConnectedCells(readoutId);
+    }
+    
+    inline SiCellId SCT_ModuleSideDesign::connectedCell(const SiReadoutCellId & readoutId, int number) const
+    {
+      return m_scheme.connectedCell(readoutId, number);
+    } 
+    
+    inline SiCellId SCT_ModuleSideDesign::gangedCell(const SiCellId &) const
+    {
+      // No ganged cells in SCT so always return invalid id.
+      return SiCellId();
+    }
+    
+    inline SiReadoutCellId SCT_ModuleSideDesign::readoutIdOfCell(const SiCellId & cellId) const
+    {
+      return m_scheme.readoutIdOfCell(cellId);
+    }
+    
+    inline SiReadoutCellId SCT_ModuleSideDesign::readoutIdOfPosition(const SiLocalPosition & localPos) const
+    {
+      // Get the cellId then convert it to a readoutId.
+      // NEED to think about active area and bond gap check
+      return readoutIdOfCell(cellIdOfPosition(localPos));
+    }
+    
+    inline bool SCT_ModuleSideDesign::swapHitPhiReadoutDirection() const
+    {
+      return m_swapStripReadout;
+    }
+    
+    inline bool SCT_ModuleSideDesign::swapHitEtaReadoutDirection() const
+    {
+      return false;
+    }
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SCT_MODULESIDEDESIGN_H
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ReadoutScheme.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ReadoutScheme.h
new file mode 100755
index 0000000000000000000000000000000000000000..132a750f01eff5039cf89b2acb1729622a45010b
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SCT_ReadoutScheme.h
@@ -0,0 +1,142 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ReadoutScheme.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SCT_READOUTSCHEME_H
+#define INDETREADOUTGEOMETRY_SCT_READOUTSCHEME_H
+
+#include "InDetReadoutGeometry/SiCellId.h"
+#include "InDetReadoutGeometry/SiReadoutCellId.h"
+
+#include <list>
+
+namespace InDetDD {
+
+    /** @class SCT_ReadoutScheme
+    
+        Definition of the readout scheme in the SCT detector describing,
+        number of sides, cells, crystals per module.
+    
+        @author Alessandro Fornaini, Grant Gorfine
+    */
+    
+    class SCT_ReadoutScheme {
+    
+        ///////////////////////////////////////////////////////////////////
+        // Public methods:
+        ///////////////////////////////////////////////////////////////////
+      public:
+      
+        // Copy constructor:
+        SCT_ReadoutScheme(const SCT_ReadoutScheme &scheme);
+      
+        // Constructor with parameters:
+        //   number of crystals within module side
+        //   number of diodes within crystal
+        //   number of cells within module side
+        //   index of diode connected to cell with index 0
+        SCT_ReadoutScheme(const int crystals,const int diodes,
+      		    const int cells,const int shift);
+      
+        // Destructor:
+        ~SCT_ReadoutScheme();
+      
+        // Assignment operator:
+        SCT_ReadoutScheme &operator=(const SCT_ReadoutScheme &scheme);
+      
+        ///////////////////////////////////////////////////////////////////
+        // Const methods:
+        ///////////////////////////////////////////////////////////////////
+      
+        // number of crystals within module side:
+        int crystals() const;
+      
+        // number of diodes within crystal:
+        int diodes() const;
+      
+        // number of cells within module side:
+        int cells() const;
+      
+        // index of diode connected to cell with index 0:
+        int shift() const;
+      
+        // readout id -> id of connected diodes
+        int numberOfConnectedCells(const SiReadoutCellId & readoutId) const;
+        SiCellId connectedCell(const SiReadoutCellId & readoutId, int number) const;
+       
+        // diode id -> readout id
+        SiReadoutCellId readoutIdOfCell(const SiCellId & cellId) const;
+      
+      
+      
+        ///////////////////////////////////////////////////////////////////
+        // Non-const methods:
+        ///////////////////////////////////////////////////////////////////
+      
+        ///////////////////////////////////////////////////////////////////
+        // Private methods:
+        ///////////////////////////////////////////////////////////////////
+      private:
+      
+        SCT_ReadoutScheme();
+      
+        ///////////////////////////////////////////////////////////////////
+        // Private data:
+        ///////////////////////////////////////////////////////////////////
+      private:
+        int m_crystals; // number of crystals within module side
+        int m_diodes; // number of diodes within crystal
+        int m_cells; // number of cells within module side
+        int m_shift; // index of diode connected to cell with index 0
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SCT_ReadoutScheme::~SCT_ReadoutScheme()
+{}
+
+inline int SCT_ReadoutScheme::crystals() const
+{
+  return m_crystals;
+}
+
+inline int SCT_ReadoutScheme::diodes() const
+{
+  return m_diodes;
+}
+
+inline int SCT_ReadoutScheme::cells() const
+{
+  return m_cells;
+}
+
+inline int SCT_ReadoutScheme::shift() const
+{
+  return m_shift;
+}
+
+inline int SCT_ReadoutScheme::numberOfConnectedCells(const SiReadoutCellId & readoutId) const
+{
+  // Assume an in range readout id is used. No checks are made.
+  // Always 1 to 1 correspondence in SCT 
+  return (readoutId.isValid()) ? 1 : 0;
+}
+
+
+inline SiCellId SCT_ReadoutScheme::connectedCell(const SiReadoutCellId & readoutId, int) const
+{
+  // Assume a valid readout id is used.
+  // Always 1 to 1 correspondence in SCT 
+  return readoutId; // Allowed to convert a SiReadoutCellId to a SiCellId.
+}
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SCT_READOUTSCHEME_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiCellId.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiCellId.h
new file mode 100755
index 0000000000000000000000000000000000000000..29648bfd6a858677789fd80d2cb5fa4b86b10157
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiCellId.h
@@ -0,0 +1,168 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiCellId.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SICELLID_H
+#define INDETREADOUTGEOMETRY_SICELLID_H
+
+#include <iostream>
+
+namespace InDetDD {
+
+  /**  @class SiCellId
+    
+    Identifier for the strip or pixel cell.
+    Just the strip number for SCT or phi_index, eta_index for pixel.
+    Packs the numbers in an int.
+    Supports negative indices and is initialized in an invalid state 
+    when using the default constructor.
+
+    @author Grant Gorfine 
+  */
+
+  class SiCellId {
+
+  ///////////////////////////////////////////////////////////////////
+  // Public methods:
+  ///////////////////////////////////////////////////////////////////
+    public:
+
+  /// Constructor. Set in invalid state. 
+  SiCellId(); 
+  /// Construct with strip number. 
+  SiCellId(int strip);
+  /// Construct with phi, eta index. 
+  SiCellId(int phiIndex, int etaIndex);
+
+  ///////////////////////////////////////////////////////////////////
+  // Const methods:
+  ///////////////////////////////////////////////////////////////////
+
+  // Get the indices
+  // NB. phiIndex() and strip() are equivalent.
+  /// Get eta index.
+  int etaIndex() const;
+  /// Get phi index. Equivalent to strip().
+  int phiIndex() const;
+  /// Get strip number. Equivalent to phiIndex().
+  int strip() const;
+
+  /// Test if its in a valid state
+  bool isValid() const;
+
+  /// Test equality.
+  bool operator==(const SiCellId & other) const;
+  /// Test inequality.
+  bool operator!=(const SiCellId & other) const;
+  
+  /// Operator for sorting
+  bool operator<(const SiCellId & other) const;
+
+  unsigned int word() const { return m_word; } 
+  
+private:
+  unsigned int m_word;
+
+  // Masks and shift values.
+  // bits 0 - 15  : phi_index
+  // bits 16 - 30 : eta_index
+  // bit  31      : valid flag
+  enum MaskAndShiftConstants {
+    PHI_MASK  = 0x0000ffff,
+    PHI_NEG   = 0x00008000, //  (PHI_MASK >> 1 + 1)
+    ETA_MASK  = 0x00007fff,
+    ETA_SHIFT = 16,
+    ETA_NEG   = 0x40000000, // ((ETA_MASK >> 1 + 1) << ETA_SHIFT) 
+    VALID     = 0x80000000
+  };
+
+};
+
+} // namespace InDetDD
+
+
+// Global 
+std::ostream & operator << (std::ostream & os, const InDetDD::SiCellId & cellId);
+
+
+
+namespace InDetDD {
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SiCellId::SiCellId()
+{
+  // set in invalid state
+  // This sets the invalid bit plus set phi and eta index to there most negative value
+  m_word = VALID | ETA_NEG | PHI_NEG ;
+}
+
+inline SiCellId::SiCellId(int phiIndex, int etaIndex)
+{
+  // The negative check is not really necessary if negative numbers are represented as twos complement but
+  // I don't think that assumption is guaranteed to be portable.
+  if (phiIndex < 0) phiIndex = PHI_MASK + phiIndex + 1; // For negative number store as two's complement
+  if (etaIndex < 0) etaIndex = ETA_MASK + etaIndex + 1;
+  m_word = (phiIndex  & PHI_MASK) | ((etaIndex & ETA_MASK) << ETA_SHIFT);
+}
+
+inline SiCellId::SiCellId(int strip)
+{
+  if (strip < 0) strip = PHI_MASK + strip + 1;
+  m_word = strip & PHI_MASK;
+}
+
+inline int SiCellId::etaIndex() const
+{
+  if (m_word & ETA_NEG) { // Negative index
+    return ((m_word >> ETA_SHIFT) & ETA_MASK) - ETA_MASK - 1;
+  } 
+  return (m_word >> ETA_SHIFT) & ETA_MASK;
+}
+
+inline int SiCellId::phiIndex() const
+{
+  if (m_word & PHI_NEG) { // Negative index
+    return (m_word & PHI_MASK) - PHI_MASK - 1;
+  } 
+  return (m_word & PHI_MASK);
+
+}
+
+inline int SiCellId::strip() const
+{
+  return phiIndex();
+}
+
+inline bool SiCellId::isValid() const
+{
+  return !(m_word & VALID);
+}
+
+inline bool SiCellId::operator==(const SiCellId & other) const
+{
+  return (m_word == other.m_word);
+} 
+
+inline bool SiCellId::operator!=(const SiCellId & other) const
+{
+  return (m_word != other.m_word);
+} 
+
+inline bool SiCellId::operator<(const SiCellId & other) const
+{
+  return (m_word < other.m_word);
+} 
+
+
+} // namespace InDetDD
+
+
+#endif // INDETREADOUTGEOMETRY_SICELLID_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiCommonItems.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiCommonItems.h
new file mode 100755
index 0000000000000000000000000000000000000000..4999443b4792eb5c6cc27ef1a972c043bd7e426e
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiCommonItems.h
@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiCommonItems.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SICOMMONITEMS_H
+#define INDETREADOUTGEOMETRY_SICOMMONITEMS_H
+
+class AtlasDetectorID;
+
+// Message Stream Member
+#include "AthenaKernel/MsgStreamMember.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "CLHEP/Geometry/Transform3D.h"
+#include "GeoModelKernel/RCBase.h"
+#include "InDetCondServices/ISiLorentzAngleSvc.h"
+
+namespace InDetDD {
+
+    /** @class SiCommonItems
+    
+        Helper class to concentrate common items, such as the pointer to the IdHelper,
+        the lorentzAngle service or the information about the solenoidal frame.
+        
+        To be used for Pixel and SCT.
+        
+        @author: Grant Gorfine
+        mondified & maintained: Nick Styles, Andreas Salzburger
+        */
+
+    class SiCommonItems: public RCBase 
+    {
+    
+        public:
+        
+          SiCommonItems(const AtlasDetectorID* const idHelper);
+          
+          const AtlasDetectorID* getIdHelper() const;
+          const HepGeom::Transform3D & solenoidFrame() const;
+          void setSolenoidFrame(const HepGeom::Transform3D & transform) const; 
+          void setLorentzAngleSvc(const ServiceHandle<ISiLorentzAngleSvc> & lorentzAngleSvc);
+          ISiLorentzAngleSvc * lorentzAngleSvc() const;
+        
+          //Declaring the Message method for further use
+          MsgStream& msg (MSG::Level lvl) const { return m_msg.get() << lvl; }
+        
+          //Declaring the Method providing Verbosity Level
+          bool msgLvl (MSG::Level lvl) const { return m_msg.get().level() <= lvl; }
+        
+        private:
+        
+          //Declaring private message stream member.
+          mutable Athena::MsgStreamMember m_msg;
+          
+          const AtlasDetectorID* m_idHelper; 
+          mutable HepGeom::Transform3D m_solenoidFrame;
+          ServiceHandle<ISiLorentzAngleSvc> m_lorentzAngleSvcHandle;
+          mutable ISiLorentzAngleSvc * m_lorentzAngleSvc;
+          mutable bool m_lorentzAngleSvcInit;
+        
+    };
+    
+    
+    inline const AtlasDetectorID* SiCommonItems::getIdHelper() const
+    {
+      return m_idHelper;
+    }
+    
+    
+    inline const HepGeom::Transform3D & SiCommonItems::solenoidFrame() const
+    {
+      return m_solenoidFrame;
+    }
+    
+    
+
+} // End namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SICOMMONITEMSS_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorDesign.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorDesign.h
new file mode 100755
index 0000000000000000000000000000000000000000..9b9e698b4ce099f29b663b2b479671a3bda4d824
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorDesign.h
@@ -0,0 +1,308 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDetectorDesign.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SIDETECTORDESIGN_H
+#define INDETREADOUTGEOMETRY_SIDETECTORDESIGN_H
+
+// Input/output classes
+#include "InDetReadoutGeometry/SiDiodesParameters.h"
+#include "InDetReadoutGeometry/InDetDD_Defs.h"
+#include "CLHEP/Geometry/Point3D.h"
+#include "CLHEP/Geometry/Vector3D.h"
+#include "AtlasDetDescr/AtlasDetectorID.h"
+#include "GeoModelKernel/RCBase.h"
+#include "InDetDD_Defs.h"
+
+#include <list>
+#include <vector>
+
+
+class Identifier;
+
+namespace Trk{
+ class SurfaceBounds;
+}
+
+namespace InDetDD {
+
+    class SiReadoutCellId;
+    class SiCellId;
+    class SiDiode;
+    class SiReadoutCell;
+    class SiLocalPosition;
+    class SiIntersect;
+    
+    enum DetectorShape {Box=0,Trapezoid,Other};
+    
+    /** @class SiDetectorDesign
+    
+       Base class for the detector design classes for Pixel and SCT.
+       These hold the local description of the detector elements which are
+       shared by a number of detector elements.
+
+        @author A. Calvet, Grant Gorfine
+    */
+    
+    class SiDetectorDesign: public RCBase {
+    
+        public:
+          enum Axis {xAxis=0,yAxis,zAxis};
+        
+        
+          ///////////////////////////////////////////////////////////////////
+          // Public methods:
+          ///////////////////////////////////////////////////////////////////
+        public:
+        
+          /** Constructor
+               @param thickness: Thickness of sensor
+               @param phiSymmetric, etaSymmetric, depthSymmetric: Flag to indicate if 
+                element is symmetric about these axes. ie for rectangular sensor they 
+                are all true, for trapezoidal sensor etaSymmetric
+                is false. They can also be used to force element not to swap directions.
+               @param carrierType: Carrier type that drifts to readout 
+                (ie electrons for pixels and holes for SCT)
+                @param readoutSide: Readout side, +ve = positive Depth Side, -ve = negative Depth Side */
+          SiDetectorDesign(double thickness, 
+        		   bool phiSymmetric,
+        		   bool etaSymmetric,
+        		   bool depthSymmetric,
+        		   InDetDD::CarrierType carrierType,
+        		   int readoutSide);
+        
+        
+          /** Destructor: */
+          virtual ~SiDetectorDesign();
+        
+          ///////////////////////////////////////////////////////////////////
+          // Const methods:
+          ///////////////////////////////////////////////////////////////////
+        
+          /** Test if point is in the active part of the detector with specified tolerances */
+          SiIntersect inDetector(const SiLocalPosition & localPosition, double phiTol, double etaTol) const;
+        
+          /** Test if near bond gap within tolerances, only relevant for SCT. */
+          virtual bool nearBondGap(const SiLocalPosition & localPosition, double etaTol) const = 0;
+        
+          /** local axis corresponding to eta direction: */
+          Axis etaAxis() const;
+        
+          /** local axis corresponding to phi direction: */
+          Axis phiAxis() const;
+        
+          /** local axis corresponding to depth direction: */
+          Axis depthAxis() const;
+        
+          bool phiSymmetric() const;
+          bool etaSymmetric() const;
+          bool depthSymmetric() const;
+        
+          /** ReadoutSide. +1 = postive depth side, -1 = negative depth side. */
+          int readoutSide() const;
+        
+          /** Override default symmetries to prevent swapping of axes.
+            NB. Flags can be changed from true to false but not false to true. */
+          void setSymmetry(bool phiSymmetric, bool etaSymmetric, bool depthSymmetric);
+        
+        	
+          ///////////////////////////////////////////////////////////////////
+          // Pure virtual methods:
+          ///////////////////////////////////////////////////////////////////
+        
+          /** Returns distance to nearest detector active edge 
+            +ve = inside
+            -ve = outside */
+          virtual void distanceToDetectorEdge(const SiLocalPosition & localPosition, 
+        				      double & etaDist, double & phiDist) const = 0;
+          
+        
+        
+          /** Helper method for stereo angle computation, DEPRECATED */
+          virtual HepGeom::Vector3D<double> phiMeasureSegment(const SiLocalPosition &position) const =0;
+        
+          /** Special method for SCT to retrieve the two ends of a "strip" */
+          virtual std::pair<SiLocalPosition,SiLocalPosition> endsOfStrip(const SiLocalPosition &position) const =0;
+        
+          /** Method to calculate length of a module */
+          virtual double length() const =0;
+        
+          /** Method to calculate average width of a module */
+          virtual double width() const = 0;
+        
+          /** Method to calculate minimum width of a module */
+          virtual double minWidth() const = 0;
+        
+          /** Method to calculate maximum width of a module */
+          virtual double maxWidth() const = 0;
+        
+          /** Method which returns thickness of the silicon wafer */
+          double thickness() const;
+        
+          /** Pitch in phi direction */
+          virtual double phiPitch() const = 0;
+        
+          /** Pitch in phi direction */
+          virtual double phiPitch(const SiLocalPosition & localPosition) const = 0;
+        
+          //** Pitch in eta direction */
+          virtual double etaPitch() const = 0;
+        
+          /** Return carrier type (ie electrons or holes) */
+          InDetDD::CarrierType carrierType() const;
+        
+          /** Return true if hit local direction is the same as readout direction. */
+          virtual bool swapHitPhiReadoutDirection() const = 0;
+          virtual bool swapHitEtaReadoutDirection() const = 0;
+        
+          /** Shape of element */
+          virtual DetectorShape shape() const;
+        
+          /**  Element boundary */
+          virtual const Trk::SurfaceBounds & bounds() const = 0; 
+        
+        
+          ///////////////////////////////////////////////////////////
+          //
+          // The following will replace existing methods but are not all implemented yet
+          //
+         
+          /** readout or diode id -> position, size */
+          virtual SiDiodesParameters parameters(const SiCellId & cellId) const = 0;
+          
+          /** readout or diode id -> position. */
+          virtual SiLocalPosition localPositionOfCell(const SiCellId & cellId) const = 0;
+        
+          /** number of connected cells. Generally 1 except for ganged pixels which will be 2. */
+          virtual int numberOfConnectedCells(const SiReadoutCellId & readoutId) const = 0;
+          
+          /** readout id -> id of connected diodes.
+             parameter number = 0 will refer to the primary diode and in general the
+             cell number will be the same.
+             NB. SiCellId cellId = connectedCell(readoutId, 0) will in general be equivalent to
+                 SiCellId cellId = readoutId */
+          virtual SiCellId connectedCell(const SiReadoutCellId & readoutId, int number) const = 0;
+        
+          /** If cell is ganged return the id of the other cell which shares the readout
+              for this cell, otherwise return an invalid id. */
+          virtual SiCellId gangedCell(const SiCellId & cellId) const = 0;
+        
+          /** diode id -> readout id
+              NB assignment of a SiReadoutCellId to a SiCellId is allowed so you are can 
+              pass SiReadoutCellId variables to functions expecting a SiCellId.  */
+          virtual SiReadoutCellId readoutIdOfCell(const SiCellId & cellId) const = 0;
+        
+          /** position -> id */
+          virtual SiReadoutCellId readoutIdOfPosition(const SiLocalPosition & localPos) const = 0;
+
+          /** position -> id */
+          virtual SiCellId cellIdOfPosition(const SiLocalPosition & localPos) const = 0;
+        
+          /** Get the neighbouring diodes of a given diode:
+               Cell for which the neighbours must be found
+             List of cells which are neighbours of the given one */
+          virtual void neighboursOfCell(const SiCellId & cellId,
+        				std::vector<SiCellId> &neighbours) const = 0;
+        
+          /** Check if cell is in range. Returns the original cellId if it is in range, otherwise it returns an invalid id. */
+          virtual SiCellId cellIdInRange(const SiCellId & cellId) const = 0;
+        
+          
+          ///////////////////////////////////////////////////////////////////
+          // Private methods:
+          ///////////////////////////////////////////////////////////////////
+        private:
+        
+          SiDetectorDesign();
+        
+          ///////////////////////////////////////////////////////////////////
+          // Private data:
+          ///////////////////////////////////////////////////////////////////
+        private:
+          Axis m_etaAxis; //!< local axis corresponding to eta direction
+          Axis m_phiAxis; //!< local axis corresponding to phi direction
+          Axis m_depthAxis; //!< local axis corresponding to depth direction
+          double m_thickness; //!< thickness of silicon sensor
+          InDetDD::CarrierType m_carrierType; //!< carrier type that drifts towards readout
+                                                        //!< (ie holes fro SCT and electrons for pixel)
+          bool m_phiSymmetric;
+          bool m_etaSymmetric;
+          bool m_depthSymmetric;
+        
+          bool m_readoutSidePosDepth; //!< Control which side readout is on.
+                                      //!< true = positive Depth Side, false = negative Depth Side
+        
+          // Disallow Copy and assignment;
+          SiDetectorDesign(const SiDetectorDesign &design);
+          SiDetectorDesign &operator=(const SiDetectorDesign &design);
+        
+    };
+    
+    ///////////////////////////////////////////////////////////////////
+    // Inline methods:
+    ///////////////////////////////////////////////////////////////////
+    inline SiDetectorDesign::Axis SiDetectorDesign::etaAxis() const
+    {
+      return m_etaAxis;
+    }
+    
+    inline SiDetectorDesign::Axis SiDetectorDesign::phiAxis() const
+    {
+      return m_phiAxis;
+    }
+    
+    inline SiDetectorDesign::Axis SiDetectorDesign::depthAxis() const
+    {
+      return m_depthAxis;
+    }
+    
+    inline double SiDetectorDesign::thickness() const
+    {
+      return m_thickness;
+    }
+     
+    inline InDetDD::CarrierType SiDetectorDesign::carrierType() const
+    {
+      return m_carrierType;
+    }
+    
+    inline bool SiDetectorDesign::phiSymmetric() const
+    {
+      return m_phiSymmetric;
+    }
+    
+    inline bool SiDetectorDesign::etaSymmetric() const
+    {
+      return m_etaSymmetric;
+    }
+    
+    inline bool SiDetectorDesign::depthSymmetric() const
+    {
+      return m_depthSymmetric;
+    }
+    
+    inline int SiDetectorDesign::readoutSide() const
+    {
+      return (m_readoutSidePosDepth) ? +1 : -1;
+    }
+    
+    
+      
+}  // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SIDETECTORDESIGN_H
+
+
+
+
+
+
+
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorElement.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorElement.h
new file mode 100755
index 0000000000000000000000000000000000000000..887a5afb9ffcca192d5da73225b96a1bd3daa633
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorElement.h
@@ -0,0 +1,980 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDetectorElement.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SIDETECTORELEMENT_H
+#define INDETREADOUTGEOMETRY_SIDETECTORELEMENT_H
+
+// Base class.
+#include "TrkDetElementBase/TrkDetElementBase.h"
+
+// Data member classes
+#include "Identifier/Identifier.h"
+#include "Identifier/IdentifierHash.h"
+#include "InDetReadoutGeometry/SiDetectorDesign.h"
+#include "InDetReadoutGeometry/SiLocalPosition.h"
+#include "TrkEventPrimitives/ParamDefs.h"
+#include "InDetReadoutGeometry/SiIntersect.h"
+#include "InDetReadoutGeometry/SiCommonItems.h"
+#include "InDetReadoutGeometry/SiCellId.h"
+#include "InDetReadoutGeometry/InDetDD_Defs.h"
+#include "CLHEP/Geometry/Point3D.h"
+#include "GeoPrimitives/CLHEPtoEigenConverter.h"
+
+class AtlasDetectorID;
+class GeoVFullPhysVol;
+
+namespace Trk{
+ class Surface;
+ class SurfaceBounds;
+}
+
+namespace InDetDD {
+
+    class SiReadoutCellId;
+
+  /**
+  
+   @class SiDetectorElement
+  
+   Class to hold geometrical description of a silicon detector element. 
+   A detector element is a module in the pixels and one side of a module in the SCT.
+   This class is shared between the Pixel and SCT detector since there is a lot of commonality.
+    
+   @par Coordinate Frames.
+  
+   The following coordinate frames are used in these elements.
+  
+    - Global frame:\n
+         Currently global frame in G4/GeoModel. Probably eventually
+         will be global frame most suitable for reconstruction 
+         (eg solenoid axis).
+  
+    - Local hit frame:\n 
+         Local frame for hits. It is the same as local frame in G4 and GeoModel. 
+         I also refer to this as the local simulation frame. 
+         By convention elements are orientated such that:
+            - hitDepth = local x
+            - hitPhi   = local y
+            - hitEta   = local z
+            . 
+         Directions of these correspond to the physical wafer. Consequently hitDepth and hitPhi axes go in 
+         different directions depending on the orientation of the module.
+         The readout side is determined from design()->readoutSide(). 
+  
+   - Local reconstruction frame:\n 
+            - distPhi  = local x
+            - distEta  = local y  
+            - distDepth = local z
+            .
+         The directions of the axes are defined as
+            - distPhi in direction of increasing phi
+            - distEta in direction of increasing z in barrel and increasing r in endcap.
+            - distDepth (normal) choosen to give right-handed coordinate. 
+               =>  away from intersection point for barrel, decreasing z for endcap
+     
+   @par Overview of Methods 
+  
+   Methods are grouped into the the following categories
+  
+      -  Identification
+      -  Navigation
+      -  Transformation/Orientation
+      -  Module Frame
+      -  Element Extent
+      -  Design methods
+      -  Intersection Tests
+      -  Lorentz Correction
+      -  Readout cell id
+      -  Miscellaneous
+      -  Cache handling.
+  
+  
+   @author Grant Gorfine
+   - modified & maintained: Nick Styles, Andreas Salzburger
+   
+  */  
+
+  class SiDetectorElement : public Trk::TrkDetElementBase {
+
+      ///////////////////////////////////////////////////////////////////
+      // Public methods:
+      ///////////////////////////////////////////////////////////////////
+    public:
+    
+      enum Axis {xAxis=0, yAxis, zAxis};
+      enum SiliconAxis {hitDepth = xAxis, hitPhi = yAxis, hitEta = zAxis};
+    
+      /// Constructor:
+      SiDetectorElement(const Identifier &id, 
+    		    const SiDetectorDesign *design,
+    		    const GeoVFullPhysVol *geophysvol,
+    		    SiCommonItems * commonItems);
+    
+      /// Destructor:
+      virtual ~SiDetectorElement();
+    
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Identification
+      /// Methods to identify the element and identifier manipulation.
+      // 
+      ///////////////////////////////////////////////////////////////////
+    
+      //@{
+    
+      /// identifier of this detector element:
+      virtual Identifier identify() const;
+    
+      /// identifier hash
+      virtual IdentifierHash identifyHash() const;
+    
+      /// Returns the id helper
+      const AtlasDetectorID* getIdHelper() const;
+    
+      bool isPixel() const;
+      bool isSCT() const;
+      bool isBarrel() const;
+      bool isEndcap() const;
+      bool isBlayer() const;
+      bool isInnermostPixelLayer() const;
+      bool isNextToInnermostPixelLayer() const;
+      bool isDBM() const;
+
+      // Identfier <-> SiCellId (ie strip number or pixel eta_index,phi_index)
+    
+      /// Identfier from SiCellId (ie strip number or pixel eta_index,phi_index)
+      Identifier identifierFromCellId(const SiCellId & cellId) const;
+    
+      /// SiCellId from Identifier
+      SiCellId   cellIdFromIdentifier(const Identifier & identifier) const;
+      
+      //@}
+    
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Navigation
+      /// Methods to access neighbours. 
+      //
+      ///////////////////////////////////////////////////////////////////
+    
+      //@{
+      const SiDetectorElement * nextInEta() const;
+      const SiDetectorElement * prevInEta() const;
+      const SiDetectorElement * nextInPhi() const;
+      const SiDetectorElement * prevInPhi() const;
+      const SiDetectorElement * otherSide() const; // Useful for SCT only
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Transformation/Orientation
+      //
+      ///////////////////////////////////////////////////////////////////
+    
+      //@{
+      // Position 
+      /// Local (simulation/hit frame) to global transform
+      virtual const HepGeom::Transform3D & transformHit() const; 
+      /// Local (reconstruction frame) to global transform
+      const Amg::Transform3D & transform() const; 
+      /// Default Local (reconstruction frame) to global transform
+      /// ie with no misalignment. 
+      const HepGeom::Transform3D defTransformCLHEP() const; 
+      const Amg::Transform3D defTransform() const; 
+      /// Center in global coordinates
+      const Amg::Vector3D & center() const; 
+    
+      const HepGeom::Transform3D & transformCLHEP() const;
+    
+      /// Simulation/Hit local frame to reconstruction local frame. 2D.
+      //  TODO: Will change order of parameters at some point.
+      Amg::Vector2D hitLocalToLocal(double xEta, double xPhi) const;
+      /// Same as previuos method but 3D.
+      HepGeom::Point3D<double> hitLocalToLocal3D(const HepGeom::Point3D<double> & hitPosition) const; 
+    
+      /// Transform to go from local reconstruction frame to local hit frame.
+      const HepGeom::Transform3D recoToHitTransform() const;
+    
+      /// Directions of hit depth,phi,eta axes relative to reconstruction local position
+      /// axes (LocalPosition). Returns +/-1.
+      double hitDepthDirection() const;
+      /// See previous method.
+      double hitPhiDirection() const;
+      /// See previous method.
+      double hitEtaDirection() const;
+    
+      // To determine if readout direction between online and offline needs swapping, see methods
+      // swapPhiReadoutDirection() and swapEtaReadoutDirection() below in "Readout Cell id" section
+    
+    
+      // Orientation. 
+      // Directions.
+      //  phiAxis - in same direction as increasing phi and identifier phi_index/strip. 
+      //            NB. This requires some flipping of axes with repsect to the hits.  
+      //  etaAxis - in direction of increasing z in the barrel and increasing r in the endcap. 
+      //  normal  - choosen to give right-handed coordinate frame (x=normal,y=phiAxis,z=etaAxis)
+      //            NB. This requires some flipping of axes with repsect to the hits.  
+      
+      /// Get reconstruction local phi axes in global frame. 
+      /// In same direction as increasing phi and identifier phi_index/strip. 
+      const Amg::Vector3D & phiAxis() const;
+      const HepGeom::Vector3D<double> & phiAxisCLHEP() const;
+      /// Get reconstruction local eta axes in global frame. 
+      /// In direction of increasing z in the barrel and increasing r in the endcap. 
+      const Amg::Vector3D & etaAxis() const;
+      const HepGeom::Vector3D<double> & etaAxisCLHEP() const;
+      /// Get reconstruction local normal axes in global frame. Choosen to give right-handed coordinate frame.
+      const Amg::Vector3D & normal() const;
+     
+      /// transform a hit local position into a global position:
+      HepGeom::Point3D<double> globalPositionHit(const HepGeom::Point3D<double> &simulationLocalPos) const;
+      Amg::Vector3D globalPositionHit(const Amg::Vector3D &simulationLocalPos) const;
+      
+      /// transform a reconstruction local position into a global position:
+      HepGeom::Point3D<double> globalPosition(const HepGeom::Point3D<double> &localPos) const;
+      Amg::Vector3D globalPosition(const Amg::Vector3D &localPos) const;
+
+      /// as in previous method but for 2D local position
+      HepGeom::Point3D<double> globalPositionCLHEP(const Amg::Vector2D &localPos) const;
+      
+      Amg::Vector3D globalPosition(const Amg::Vector2D &localPos) const;
+    
+      /// transform a global position into a 2D local position (reconstruction frame)
+      Amg::Vector2D localPosition(const HepGeom::Point3D<double> & globalPosition) const;
+
+      Amg::Vector2D localPosition(const Amg::Vector3D& globalPosition) const;
+    
+      /// Compute sin(tilt angle) at a given position:
+      /// at center
+      double sinTilt() const; // At center
+      /// at given local position
+      double sinTilt(const Amg::Vector2D &localPos) const;
+      /// at given global position
+      double sinTilt(const HepGeom::Point3D<double> &globalPosition) const;
+    
+      /// Compute sin(stereo angle) at a given position: at center
+      double sinStereo() const; // At center
+      /// at given local position
+      double sinStereo(const Amg::Vector2D &localPos) const;
+      /// at given global position
+      double sinStereo(const HepGeom::Point3D<double> &globalPosition) const;
+    
+      /// Check if it is the stereo side (useful for SCT) 
+      bool isStereo() const;
+    
+      /// Angle of strip in local frame with respect to the etaAxis. 
+      /// Zero for all elements except trapezoidal detectors (ie SCT forward modules).
+      double sinStereoLocal(const Amg::Vector2D &localPos) const;
+      /// See previous method
+      double sinStereoLocal(const HepGeom::Point3D<double> &globalPos) const;
+    
+      /// Element Surface
+      virtual const Trk::Surface & surface() const;
+    
+      //@}
+    
+    
+      /**
+      
+      @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.
+      */
+      
+      //@{
+    
+      /// 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.
+      //const HepGeom::Transform3D & moduleTransform() 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.
+      Amg::Transform3D defModuleTransform() 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;
+      Amg::Transform3D localToModuleTransform() const;
+    
+      /// Check if the element and module frame are the same.
+      bool isModuleFrame() const;
+    
+    
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Element Extent
+      /// Methods to get extent of element in r,phi and z.  
+      ///////////////////////////////////////////////////////////////////
+    
+      //@{
+      // Extent in r,z and phi
+      double rMin() const;
+      double rMax() const;
+      double zMin() const;
+      double zMax() const;
+      double phiMin() const;
+      double phiMax() const;
+    
+      /// Method for building up region of interest table.
+      /// Get eta/phi extent for the element. Returns min/max eta and phi
+      /// and r (for barrel) or z (for endcap) Takes as input the vertex
+      /// spread in z (-deltaZ to +deltaZ)
+      void getEtaPhiRegion(double deltaZ, 
+    		       double &etaMin, double &etaMax, 
+    		       double &phiMin, double &phiMax, 
+    		       double &rz) const;
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Design methods
+      //
+      ///////////////////////////////////////////////////////////////////
+      //@{
+    
+      /// access to the local description:
+      const SiDetectorDesign &design() const;
+    
+      // Methods from design
+      double width() const; // Width in phi direction. For the SCT endcap it returns the average width. 
+      double minWidth() const; // Min, max width. Needed for the SCT endcap. 
+      double maxWidth() const; 
+      double length() const; // Length in eta direction (z - barrel, r - endcap)
+      double thickness() const;
+    
+      InDetDD::CarrierType carrierType() const; // carrier type for readout. ie holes for SCT 
+                                                // and electrons for pixels.
+      virtual const Trk::SurfaceBounds & bounds() const;
+    
+      // Pitch 
+      //
+      // NOTE: phiPitch is ambiguous for the Forward SCT where it varies along the strip.
+      //       etaPitch is ambiguous for the pixel which has long pixels between FE chips.
+      //
+      // For these cases:
+      //
+      // phiPitch:  For SCT Forward returns pitch at center.
+      // etaPitch:  For pixel returns average pitch. (Active_length/number_of_cells)
+      //
+      // All return pitch in distance units. 
+      //
+      double etaPitch() const; 
+      double phiPitch() const; 
+      double phiPitch(const Amg::Vector2D &) const; // Useful for SCT Forward.
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Intersection Tests
+      //
+      ///////////////////////////////////////////////////////////////////
+    
+      //@{
+      // Test if near bond gap within tolerances
+      bool nearBondGap(Amg::Vector2D localPosition, double etaTol) const;
+      bool nearBondGap(HepGeom::Point3D<double> globalPosition, double etaTol) const;
+    
+      // Test that it is in the active region
+      // Intersect has 3 states
+      // bool SiIntersect::in() const // definitely in
+      // bool SiIntersect::out() const // definitely out
+      // bool SiIntersect::nearBoundary() const // near a boundary within the tolerances 
+      // bool SiIntersect::mayIntersect() const // in() OR nearBoundary()
+      SiIntersect inDetector(const Amg::Vector2D & localPosition, double phiTol, double etaTol) const;
+      SiIntersect inDetector(const HepGeom::Point3D<double> & globalPosition, double phiTol, double etaTol) const;
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Lorentz Correction
+      //
+      ///////////////////////////////////////////////////////////////////
+      //@{
+    
+      /// tan(Lorentz angle). Component in phi direction (hit frame)
+      double getTanLorentzAnglePhi() const; 
+    
+      /// Same as getTanLorentzAnglePhi()
+      double getTanLorentzAngle() const; 
+    
+      /// tan(Lorentz angle). Component in eta direction (hit frame)
+      double getTanLorentzAngleEta() const; 
+    
+      /// Lorentz shift in distPhi (reconstruction local frame)
+      double getLorentzCorrection() const; 
+    
+      /// Correct a local position (reconstruction frame) for the Lorentz angle:
+      /// Users generally shouldn't need to call this as localPositionOfCell() returns the Lorentz corrected position.
+      Amg::Vector2D correctLocalPosition(const Amg::Vector2D &position) const;
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Readout cell id
+      /// Cell id's are the strip number in SCT and phi_index,eta_index in the pixel
+      /// as defined in the offline identifier. Their direction runs in the distPhi, distEta
+      /// direction in the Reconstruction local frame. 
+      ///
+      /// For methods taking a SiCellId (basically phi,eta index for pixel or strip for SCT) you
+      /// can do the following fro example:
+      ///   - For pixel\n 
+      ///      localPositionOfCell(SiCellId(phi_index,eta_index));\n
+      ///   - For SCT\n
+      ///      localPositionOfCell(SiCellId(strip));\n
+      //
+      ///////////////////////////////////////////////////////////////////
+      //@{
+    
+      /// Determine if readout direction between online and offline needs swapping.
+      /// Returns true if online and offline numbers run in opposite directions.
+      /// For strip/phi_index
+      bool swapPhiReadoutDirection() const;
+      /// For eta_index (only relevant for pixel)
+      bool swapEtaReadoutDirection() const;
+    
+      /// Full identifier of the cell for a given position:
+      /// assumes a raw local position (no Lorentz shift)
+      Identifier identifierOfPosition(const Amg::Vector2D &localPos) const;
+      /// As in previous method but returns SiCellId 
+      SiCellId cellIdOfPosition(const Amg::Vector2D &localPos) const;
+    
+    
+      /// Returns position (center) of cell. These are corrected for the Lorentz shift
+      Amg::Vector2D localPositionOfCell(const SiCellId & cellId) const;
+      /// As above
+      Amg::Vector2D localPositionOfCell(const Identifier & id) const;
+    
+      /// Returns position (center) of cell. These are the raw positions *NOT* corrected for the Lorentz shift
+      Amg::Vector2D rawLocalPositionOfCell(const SiCellId & cellId) const;
+      /// As above
+      Amg::Vector2D rawLocalPositionOfCell(const Identifier & id) const;
+    
+      /// Test if readout cell has more than one diode associated with it.
+      /// Number of cells sharing the same readout as this cell.
+      /// ie generally 1 except for ganged pixels which will be 2.
+      int numberOfConnectedCells(const SiCellId cellId) const;
+      /// Get the cell ids sharing the readout for this cell.
+      /// number = 0 will return the primary readout cell id.
+      SiCellId connectedCell(const SiCellId cellId, int number) const;
+    
+      /// If cell is ganged return the id of the other cell which shares the readout
+      /// for this cell, otherwise return an invalid id.
+      /// This is a more convenient (and slightly faster) alternative than 
+      /// using the above two methods.
+      /// Only relevant for pixel. For SCT always returns an invalid ID.
+      SiCellId gangedCell(const SiCellId & cellId) const;
+    
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Miscellaneous
+      //
+      ///////////////////////////////////////////////////////////////////
+      //@{
+      /// Special method for SCT to retrieve the two ends of a "strip"
+      /// Returned coordinates are in global frame.
+      //std::pair<HepGeom::Point3D<double>,HepGeom::Point3D<double> > endsOfStrip(const Amg::Vector2D &position) const;
+      std::pair<Amg::Vector3D,Amg::Vector3D > endsOfStrip(const Amg::Vector2D &position) const;
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Cache handling.
+      //
+      ///////////////////////////////////////////////////////////////////
+      //@{.
+      //   - Methods to handle invalidating and updating caches. The cached values include values that are affected by alignment
+      //     Surface are only created on demand.  The method updateAllCaches also creates the surfaces as well as calling updateCache.
+      //     Conditions cache contains Lorentz angle related quantities.
+     
+      /// Signal that cached values are no longer valid.
+      /// Invalidate general cache
+      void invalidate() const; 
+    
+      /// invalidate conditions cache
+      void invalidateConditions() const; 
+    
+      /// Recalculate all cached values. 
+      void updateCache() const; 
+    
+      /// Recalculate subset of cached values.
+      void updateConditionsCache() const; 
+    
+      /// Update all caches including surfaces.
+      void updateAllCaches() const;
+    
+    
+    
+    
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      //
+      /// @name Methods to satisfy TrkDetElementBase interface
+      //
+      ///////////////////////////////////////////////////////////////////
+      //{@
+      virtual const Amg::Transform3D & transform(const Identifier&) const {return transform();}
+      virtual const Trk::Surface& surface (const Identifier&) const {return surface();}
+      virtual const Amg::Vector3D& center (const Identifier&) const {return center();}
+      virtual const Amg::Vector3D& normal (const Identifier&) const {return normal();}
+      virtual const Trk::SurfaceBounds & bounds(const Identifier&) const {return bounds();}
+      //@}
+    
+      //////////////////////////////////////////////////////////////////////////////////////
+      //////////////////////////////////////////////////////////////////////////////////////
+    
+    public:
+    
+    
+      ///////////////////////////////////////////////////////////////////
+      /// @name Non-const methods:
+      /// These are not needed by most clients.
+      ///////////////////////////////////////////////////////////////////
+      //@{
+      // Set neighbours. 
+    
+      void setNextInEta(const SiDetectorElement *);
+      void setPrevInEta(const SiDetectorElement *);
+      void setNextInPhi(const SiDetectorElement *);
+      void setPrevInPhi(const SiDetectorElement *);
+      void setOtherSide(const SiDetectorElement *); // For SCT only
+    
+      //@}
+    
+      ///////////////////////////////////////////////////////////////////
+      // Private methods:
+      ///////////////////////////////////////////////////////////////////
+    
+    private:
+    
+      // Common code for constructors.
+      void commonConstructor();
+    
+    
+      // Calculate extent in r,z and phi. The values are cached and there
+      // are rMin(), rMax etc methods.
+      void getExtent(double &rMin, double &rMax, 
+    		 double &zMin, double &zMax, 
+    		 double &phiMin, double &phiMax) const; 
+    
+      // Return the four corners of an element in local coordinates.
+      // Pass it an array of length 4.
+      // This function is used by getEtaPhiRegion()
+      void getCorners(HepGeom::Point3D<double> *corners) const;
+    
+      // Get eta and phi coresponding to a point in local coordinates. 
+      // Requires as input the vertex spread. Returns etaMin, etaMax, and phi.
+      // This function is used by getEtaPhiRegion()
+      void getEtaPhiPoint(const HepGeom::Point3D<double> & point, double deltaZ, 
+    		      double &etaMin, double &etaMax, double &phi) const;
+    
+      
+      //Declaring the Message method for further use
+      MsgStream& msg (MSG::Level lvl) const { return m_commonItems->msg(lvl);}
+    
+      //Declaring the Method providing Verbosity Level
+      bool msgLvl (MSG::Level lvl) const { return m_commonItems->msgLvl(lvl);}
+    
+    
+      ///////////////////////////////////////////////////////////////////
+      // Private methods:
+      ///////////////////////////////////////////////////////////////////
+    private:
+    
+      // Don't allow copying.
+      SiDetectorElement();
+      SiDetectorElement(const SiDetectorElement&);
+      SiDetectorElement &operator=(const SiDetectorElement&);
+    
+    
+    
+      ///////////////////////////////////////////////////////////////////
+      // Protected data:
+      ///////////////////////////////////////////////////////////////////
+    protected:
+    
+      Identifier m_id; // identifier of this detector element
+      IdentifierHash m_idHash; // hash id
+      const SiDetectorDesign *m_design; // local description of this detector element
+      //const AtlasDetectorID* m_idHelper; // id helper
+      SiCommonItems * m_commonItems;
+    
+      const SiDetectorElement * m_nextInEta;
+      const SiDetectorElement * m_prevInEta;
+      const SiDetectorElement * m_nextInPhi;
+      const SiDetectorElement * m_prevInPhi;
+      const SiDetectorElement * m_otherSide;
+    
+      bool m_isPixel;
+      bool m_isBarrel;
+      bool m_isDBM;
+      
+      //
+      // Cached values.
+      //
+    
+      // Directions of axes. These are true if the hit/simulation and reconstruction local frames are
+      // in the same direction and false if they are opposite.
+      mutable bool m_depthDirection; // Direction of depth axis. 
+                             // Also direction of readout implant (n+ for pixel, p+ for SCT).
+      mutable bool m_phiDirection;     //
+      mutable bool m_etaDirection;     //
+    
+      mutable bool m_cacheValid; // Alignment associated quatities.
+      mutable bool m_conditionsCacheValid; // Lorentz angle related values.
+      mutable bool m_firstTime;
+      mutable bool m_isStereo;
+    
+      mutable Amg::Transform3D m_transform; 
+      mutable HepGeom::Transform3D m_transformCLHEP; 
+    
+    
+      mutable Amg::Vector3D m_normal;
+      mutable HepGeom::Vector3D<double> m_normalCLHEP;
+      mutable Amg::Vector3D m_etaAxis;
+      mutable Amg::Vector3D m_phiAxis;
+      mutable HepGeom::Vector3D<double> m_etaAxisCLHEP;
+      mutable HepGeom::Vector3D<double> m_phiAxisCLHEP;
+      mutable Amg::Vector3D m_center;
+      mutable HepGeom::Vector3D<double> m_centerCLHEP;
+    
+      mutable double m_minZ;
+      mutable double m_maxZ;
+      mutable double m_minR;
+      mutable double m_maxR;
+      mutable double m_minPhi;
+      mutable double m_maxPhi;
+    
+      mutable double m_tanLorentzAnglePhi;
+      mutable double m_tanLorentzAngleEta;
+      mutable double m_lorentzCorrection; 
+      
+      mutable Trk::Surface * m_surface;
+
+    };
+    
+    ///////////////////////////////////////////////////////////////////
+    // Inline methods:
+    ///////////////////////////////////////////////////////////////////
+    
+    inline bool SiDetectorElement::isEndcap() const
+    {
+      return (!isBarrel()&&!isDBM());
+    }
+    
+    
+    inline HepGeom::Point3D<double> SiDetectorElement::globalPositionHit(const HepGeom::Point3D<double> &localPos) const
+    {
+      return transformHit()*localPos;
+    }
+    
+    inline Amg::Vector3D SiDetectorElement::globalPosition(const Amg::Vector2D &localPos) const
+    {
+      if (!m_cacheValid) updateCache();
+      return m_center + localPos[Trk::distEta] * m_etaAxis + localPos[Trk::distPhi] * m_phiAxis;
+      
+    }
+
+    inline Amg::Vector3D SiDetectorElement::globalPositionHit(const Amg::Vector3D &localPos) const
+    {
+      return Amg::CLHEPTransformToEigen(transformHit()) * localPos;
+    }
+    
+     inline HepGeom::Point3D<double> SiDetectorElement::globalPositionCLHEP(const Amg::Vector2D &localPos) const
+    {
+      if (!m_cacheValid) updateCache();
+      return m_centerCLHEP + localPos[Trk::distEta] * m_etaAxisCLHEP + localPos[Trk::distPhi] * m_phiAxisCLHEP;
+      
+    }
+     //here
+     inline Amg::Vector3D SiDetectorElement::globalPosition(const Amg::Vector3D &localPos) const
+    {
+      return transform() * localPos;
+    }
+    
+     inline HepGeom::Point3D<double> SiDetectorElement::globalPosition(const HepGeom::Point3D<double> &localPos) const
+    {
+      return transformCLHEP() * localPos;
+    }
+    
+    inline Amg::Vector2D SiDetectorElement::localPosition(const HepGeom::Point3D<double> & globalPosition) const
+    {
+      if (!m_cacheValid) updateCache();
+      HepGeom::Vector3D<double> relativePos = globalPosition - m_centerCLHEP;
+      return Amg::Vector2D(relativePos.dot(m_phiAxisCLHEP), relativePos.dot(m_etaAxisCLHEP));
+    }
+
+    inline Amg::Vector2D SiDetectorElement::localPosition(const Amg::Vector3D & globalPosition) const{
+      if (!m_cacheValid) updateCache();
+      Amg::Vector3D relativePos = globalPosition - m_center;
+      return Amg::Vector2D(relativePos.dot(m_phiAxis), relativePos.dot(m_etaAxis));
+}
+
+    inline const SiDetectorDesign &SiDetectorElement::design() const
+    {
+      return *m_design;
+    }
+    
+    inline const AtlasDetectorID* SiDetectorElement::getIdHelper() const
+    {
+      return m_commonItems->getIdHelper();
+    }
+    
+    inline Identifier SiDetectorElement::identify() const
+    {
+      return m_id;
+    }
+    
+    inline IdentifierHash SiDetectorElement::identifyHash() const
+    {
+      return m_idHash;
+    }
+    
+    
+    inline double SiDetectorElement::hitDepthDirection() const
+    {
+      if (!m_cacheValid) updateCache();
+      return (m_depthDirection) ? 1. : -1.;
+    }
+    
+    inline double SiDetectorElement::hitPhiDirection() const
+    {
+      if (!m_cacheValid) updateCache();
+      return (m_phiDirection) ? 1. : -1.;
+    }
+    
+    inline double SiDetectorElement::hitEtaDirection() const
+    {
+      if (!m_cacheValid) updateCache();
+      return (m_etaDirection) ? 1. : -1.;
+    }
+    
+    inline InDetDD::CarrierType SiDetectorElement::carrierType() const
+    {
+      return m_design->carrierType();
+    }
+    
+    inline SiCellId SiDetectorElement::gangedCell(const SiCellId & cellId) const
+    {
+      return m_design->gangedCell(cellId);
+    }
+    
+    inline void SiDetectorElement::invalidate() const
+    {
+      m_cacheValid = false;
+      // Conditions cache invalidation is done by SiLorentzAngleSvc.
+    }
+    
+    inline void SiDetectorElement::invalidateConditions() const
+    {
+      m_conditionsCacheValid = false;
+    }
+    
+    inline void SiDetectorElement::updateAllCaches() const
+    {
+      if (!m_cacheValid) updateCache();
+      if (!m_conditionsCacheValid) updateConditionsCache();
+      if (!m_surface) surface();
+    }
+    
+    
+    inline double SiDetectorElement::rMin() const 
+    {
+      if (!m_cacheValid) updateCache();
+      return m_minR;
+    }
+    
+    inline double SiDetectorElement::rMax() const 
+    {
+      if (!m_cacheValid) updateCache();
+      return m_maxR;
+    }
+    
+    inline double SiDetectorElement::zMin() const 
+    {
+      if (!m_cacheValid) updateCache();
+      return m_minZ;
+    }
+    
+    inline double SiDetectorElement::zMax() const 
+    {
+      if (!m_cacheValid) updateCache();
+      return m_maxZ;
+    }
+    
+    inline double SiDetectorElement::phiMin() const 
+    {
+      if (!m_cacheValid) updateCache();
+      return m_minPhi;
+    }
+    
+    inline double SiDetectorElement::phiMax() const 
+    {
+      if (!m_cacheValid) updateCache();
+      return m_maxPhi;
+    }
+    
+    inline double SiDetectorElement::width() const
+    {
+      return m_design->width();
+    }
+    
+    inline double SiDetectorElement::minWidth() const
+    {
+      return m_design->minWidth();
+    }
+    
+    inline double SiDetectorElement::maxWidth() const
+    {
+      return m_design->maxWidth();
+    }
+    
+    inline double SiDetectorElement::length() const
+    {
+      return m_design->length();
+    }
+    
+    inline double SiDetectorElement::thickness() const
+    {
+      return m_design->thickness();
+    }
+    
+    inline double SiDetectorElement::etaPitch() const
+    {
+      return m_design->etaPitch();
+    }
+    
+    inline double SiDetectorElement::phiPitch() const
+    {
+      return m_design->phiPitch();
+    }
+    
+    inline double SiDetectorElement::phiPitch(const Amg::Vector2D & localPosition) const
+    {
+      return m_design->phiPitch(localPosition);
+    }
+    
+    inline const SiDetectorElement * SiDetectorElement::nextInEta() const
+    {
+      return m_nextInEta;
+    }
+    
+    inline const SiDetectorElement * SiDetectorElement::prevInEta() const
+    {
+      return m_prevInEta;
+    }
+    
+    inline const SiDetectorElement * SiDetectorElement::nextInPhi() const
+    {
+      return m_nextInPhi;
+    }
+    
+    inline const SiDetectorElement * SiDetectorElement::prevInPhi() const
+    {
+      return m_prevInPhi;
+    }
+    
+    inline const SiDetectorElement * SiDetectorElement::otherSide() const
+    {
+      return m_otherSide;
+    }
+    
+    inline void SiDetectorElement::setNextInEta(const SiDetectorElement * element)
+    {
+      m_nextInEta = element;
+    }
+    
+    inline void SiDetectorElement::setPrevInEta(const SiDetectorElement * element)
+    {
+      m_prevInEta = element;
+    }
+    
+    inline void SiDetectorElement::setNextInPhi(const SiDetectorElement * element)
+    {
+      m_nextInPhi = element;
+    }
+    
+    inline void SiDetectorElement::setPrevInPhi(const SiDetectorElement * element)
+    {
+      m_prevInPhi = element;
+    }
+    
+    inline void SiDetectorElement::setOtherSide(const SiDetectorElement * element) // For SCT only
+    {
+      m_otherSide = element;
+    }
+    
+    inline bool SiDetectorElement::swapPhiReadoutDirection() const
+    {
+      // equivalent to (m_design->swapHitPhiReadoutDirection() xor !m_phiDirection)
+      return ((!m_design->swapHitPhiReadoutDirection() && !m_phiDirection)
+    	  || (m_design->swapHitPhiReadoutDirection() && m_phiDirection));
+    }
+    
+    inline bool SiDetectorElement::swapEtaReadoutDirection() const
+    {
+      // equivalent to (m_design->swapHitEtaReadoutDirection() xor !m_etaDirection)
+      return ((!m_design->swapHitEtaReadoutDirection() && !m_etaDirection)
+    	  || (m_design->swapHitEtaReadoutDirection() && m_etaDirection));
+    }
+    
+    inline double SiDetectorElement::getTanLorentzAnglePhi() const
+    {
+      if (!m_conditionsCacheValid) updateConditionsCache();
+      return m_tanLorentzAnglePhi;
+    }
+    
+    // Same as getTanLorentzAnglePhi()
+    inline double SiDetectorElement::getTanLorentzAngle() const
+    {
+      if (!m_conditionsCacheValid) updateConditionsCache();
+      return m_tanLorentzAnglePhi;
+    }
+    
+    inline double SiDetectorElement::getTanLorentzAngleEta() const
+    {
+      if (!m_conditionsCacheValid) updateConditionsCache();
+      return m_tanLorentzAngleEta;
+    }
+    
+    inline double SiDetectorElement::getLorentzCorrection() const
+    {
+      if (!m_conditionsCacheValid) updateConditionsCache();
+      return m_lorentzCorrection;
+    }
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SIDETECTORELEMENT_H
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorElementCollection.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorElementCollection.h
new file mode 100755
index 0000000000000000000000000000000000000000..a4fbe702d932e408e0a5c05c4b4a49fe9f1a9c0f
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorElementCollection.h
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDetectorElementCollection.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+
+#ifndef INDETREADOUTGEOMETRY_SIDETECTORELEMENTCOLLECTION_H
+#define INDETREADOUTGEOMETRY_SIDETECTORELEMENTCOLLECTION_H
+
+#include <vector>
+
+namespace InDetDD {
+
+    class SiDetectorElement;
+
+    /** @class SiDetectorElementCollection
+      
+       Class to hold the SiDetectorElement objects to be put in the detector store
+
+       @author Grant Gorfine
+    */
+
+    class SiDetectorElementCollection : public std::vector<SiDetectorElement *>
+{};
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SIDETECTORELEMENTCOLLECTION_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorManager.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorManager.h
new file mode 100755
index 0000000000000000000000000000000000000000..5cb5a74228eceee024355fd5c4999d2b7f675791
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDetectorManager.h
@@ -0,0 +1,162 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDetectorManager.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SIDETECTORMANAGER_H
+#define INDETREADOUTGEOMETRY_SIDETECTORMANAGER_H
+
+#include "InDetReadoutGeometry/InDetDetectorManager.h"
+
+#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
+#include "InDetReadoutGeometry/InDetDD_Defs.h"
+#include "InDetReadoutGeometry/SiNumerology.h"
+
+// Amg stuff
+#include "GeoPrimitives/GeoPrimitives.h"
+
+// IOV SVC for alignment:
+#include "AthenaKernel/IIOVSvc.h"
+
+#include "CLHEP/Geometry/Transform3D.h"
+
+#include <string>
+#include <map>
+  
+class StoreGateSvc;
+class Identifier; 
+class IdentifierHash;
+class AtlasDetectorID;
+class GeoAlignableTransform;
+
+namespace InDetDD {
+
+class SiDetectorElement;
+class SiDetectorDesign;
+class ExtendedAlignableTransform;
+class SiNumerology;
+
+  /** @class SiDetectorManager
+  
+        Base class for Pixel and SCT Detector managers.
+        
+        The Detector manager has methods to retrieve the Identifier
+        helper and methods to retrieve the detector elements.  It also
+        manages the alignment with methods to register the call backs
+        and infrastructure to associate the alignment transforms with
+        the appropriate alignable transform in GeoModel.
+        There is also access to the layout (Initial, Final, TestBeam) and
+        and version information.
+  
+       @author: Grant Gorfine
+       - modified and maintained by Nick Styles & Andreas Salzburger 
+       */
+
+    class SiDetectorManager : public InDetDetectorManager  {
+    
+    
+    public:
+    
+      // Constructor
+      SiDetectorManager(StoreGateSvc * detStore, const std::string & name);
+     
+      // Destructor
+      virtual ~SiDetectorManager() {};
+    
+    
+      //
+      // Access Readout Elements
+      //
+    
+      /** access to individual elements using Identifier or IdentiferHash */
+      virtual SiDetectorElement * getDetectorElement(const Identifier &id) const = 0;
+      virtual SiDetectorElement * getDetectorElement(const IdentifierHash &idHash) const = 0;
+    
+      /** access to whole collectiom */
+      virtual const SiDetectorElementCollection * getDetectorElementCollection() const = 0;
+      virtual SiDetectorElementCollection::const_iterator getDetectorElementBegin() const = 0;
+      virtual SiDetectorElementCollection::const_iterator getDetectorElementEnd() const = 0;
+    
+    
+      /** Add elememts */
+      virtual void addDetectorElement(SiDetectorElement * element) = 0;
+    
+      /** Initialize the neighbours. This can only be done when all elements are built */
+      virtual void initNeighbours() = 0;
+    
+      /** Get tag used in dictionary */
+      const std::string & tag() const; 
+    
+      /** Methods to query which manager we have */
+      virtual bool isPixel() const = 0;
+      bool isSCT() const {return !isPixel();}
+     
+      /** Add alignable transforms. No access to these, they will be changed by manager: */
+      virtual void addAlignableTransform (int level, const Identifier &id, GeoAlignableTransform *xf) = 0;
+      void addKey(const std::string & key, int level); // DEPRECATED - kept for compatibilty with Lisbon CondDB
+      void addKey(const std::string & key, int level, bool globalDelta); // DEPRECATED - kept for compatibilty with Lisbon CondDB
+      void addKey(const std::string & key, int level, FrameType frame); // DEPRECATED use addChannel
+    
+      // Call back for alignment updates:
+      // DEPRECATED - now registered in Tool.
+      StatusCode alignmentCallback( IOVSVC_CALLBACK_ARGS );
+    
+      /** Invalidate cache for all detector elements */
+      virtual void invalidateAll() const;
+    
+      /** Update all caches */
+      virtual void updateAll() const;
+    
+      
+      /** Helper method to set delta transform from a global delta - Amg interface*/
+      bool setAlignableTransformGlobalDelta(ExtendedAlignableTransform * extXF, 
+    					const Amg::Transform3D & delta) const;
+    
+      /** Helper method to set delta transform from a local delta - Amg interface */
+      bool setAlignableTransformLocalDelta(ExtendedAlignableTransform * extXF, 
+    				       const Amg::Transform3D & localToGlobalXF,
+    				       const Amg::Transform3D & delta) const;
+    
+      /** Access to module design */
+      void addDesign(const SiDetectorDesign *);
+      int numDesigns() const;
+      const SiDetectorDesign * getDesign(int i) const;
+    
+      /** Access Numerology */
+      const SiNumerology & numerology() const {return m_numerology;}
+      SiNumerology & numerology() {return m_numerology;}
+    
+    private:
+      //** Prevent copy and assignment */
+      const SiDetectorManager & operator=(const SiDetectorManager &right);
+      SiDetectorManager(const SiDetectorManager &right); 
+    
+      /** This method is called by the InDetDetectorManager */
+      virtual bool setAlignableTransformDelta(int level, 
+    					  const Identifier & id, 
+    					  const Amg::Transform3D & delta,
+    					  FrameType frame) const = 0;
+    
+    
+    
+      std::string                               m_tag;
+      SiNumerology                              m_numerology;
+      std::vector< const SiDetectorDesign *>    m_designs;
+    
+    };
+
+
+} // namespace InDetDD
+
+#ifndef GAUDI_NEUTRAL
+#include "CLIDSvc/CLASS_DEF.h"
+
+CLASS_DEF(InDetDD::SiDetectorManager, 1441401, 1)
+#endif
+
+#endif // INDETREADOUTGEOMETRY_SIDETECTORMANAGER_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDiodesParameters.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDiodesParameters.h
new file mode 100755
index 0000000000000000000000000000000000000000..6460550ca07f9e284549ceb161a7d58a007ce9b7
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiDiodesParameters.h
@@ -0,0 +1,148 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDiodesParameters.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SIDIODESPARAMETERS_H
+#define INDETREADOUTGEOMETRY_SIDIODESPARAMETERS_H
+
+// Data members classes
+#include "InDetReadoutGeometry/SiLocalPosition.h"
+
+namespace InDetDD {
+   
+   /** @class SiDiodesParameters 
+   Class to handle the position of the centre and the width of a
+   diode or a cluster of diodes
+   Version 1.1 15/08/2001 David Calvet
+   */
+
+  class SiDiodesParameters {
+
+    ///////////////////////////////////////////////////////////////////
+    // Public methods:
+    ///////////////////////////////////////////////////////////////////
+    public:
+
+      /** Implicit constructor: */
+      SiDiodesParameters();
+
+      /** Copy constructor: */
+      SiDiodesParameters(const SiDiodesParameters &parameters);
+
+      /** Constructor with parameters:
+          position of the diodes centre
+          width of the diodes */
+      SiDiodesParameters(const SiLocalPosition &centre,
+    		     const SiLocalPosition &width);
+
+      /** Destructor: */
+      ~SiDiodesParameters();
+
+      /** Assignment operator: */
+      SiDiodesParameters &operator=(const SiDiodesParameters &parameters);
+
+      ///////////////////////////////////////////////////////////////////
+      // Const methods:
+      ///////////////////////////////////////////////////////////////////
+
+      /** position of the diodes centre: */
+      SiLocalPosition centre() const;
+
+      /** width of the diodes: */
+      SiLocalPosition width() const;
+      SiLocalPosition halfWidth() const;
+
+      /** boundaries of the diodes: */
+      double xEtaMin() const;
+      double xEtaMax() const;
+      double xPhiMin() const;
+      double xPhiMax() const;
+      double xDepthMin() const;
+      double xDepthMax() const;
+
+      ///////////////////////////////////////////////////////////////////
+      // Non-const methods:
+      ///////////////////////////////////////////////////////////////////
+
+      void centre(const SiLocalPosition &centre);
+
+      void width(const SiLocalPosition &width);
+
+      ///////////////////////////////////////////////////////////////////
+      // Private data:
+      ///////////////////////////////////////////////////////////////////
+    private:
+      SiLocalPosition m_centre; //!< position of the diodes centre
+      SiLocalPosition m_width; //!< width of the diodes
+  };
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SiDiodesParameters::~SiDiodesParameters()
+{}
+
+inline SiLocalPosition SiDiodesParameters::centre() const
+{
+  return m_centre;
+}
+
+inline SiLocalPosition SiDiodesParameters::width() const
+{
+  return m_width;
+}
+
+inline SiLocalPosition SiDiodesParameters::halfWidth() const
+{
+  return m_width/2;
+}
+
+inline double SiDiodesParameters::xEtaMin() const
+{
+  return m_centre.xEta()-m_width.xEta()/2;
+}
+
+inline double SiDiodesParameters::xEtaMax() const
+{
+  return m_centre.xEta()+m_width.xEta()/2;
+}
+
+inline double SiDiodesParameters::xPhiMin() const
+{
+  return m_centre.xPhi()-m_width.xPhi()/2;
+}
+
+inline double SiDiodesParameters::xPhiMax() const
+{
+  return m_centre.xPhi()+m_width.xPhi()/2;
+}
+
+inline double SiDiodesParameters::xDepthMin() const
+{
+  return m_centre.xDepth()-m_width.xDepth()/2;
+}
+
+inline double SiDiodesParameters::xDepthMax() const
+{
+  return m_centre.xDepth()+m_width.xDepth()/2;
+}
+
+inline void SiDiodesParameters::centre(const SiLocalPosition &centre)
+{
+  m_centre=centre;
+}
+
+inline void SiDiodesParameters::width(const SiLocalPosition &width)
+{
+  m_width=width;
+}
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SIDIODESPARAMETERS_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiIntersect.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiIntersect.h
new file mode 100755
index 0000000000000000000000000000000000000000..4cabb39b818cc3c33927166d215660e18dbb469b
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiIntersect.h
@@ -0,0 +1,94 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+//   SiIntersect.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SIINTERSECT_H
+#define INDETREADOUTGEOMETRY_SIINTERSECT_H
+
+namespace InDetDD {
+
+  /** @class SiIntersect
+ 
+      class to run intersection tests
+
+      @author Grant Gorfine
+  */
+
+  class SiIntersect {
+
+    public:
+
+      enum IntersectState {OUT = 0, BOUNDARY = 1, IN = 2};
+
+      SiIntersect(IntersectState state = OUT);
+
+      bool in() const; // Definitely in
+      bool out() const; // Definitely out
+      bool nearBoundary() const; // Near boundary within tolerences
+      bool mayIntersect() const; // in() || nearBoundary()
+      operator bool() const; // Equivalent to mayIntersect().
+
+      void setIn();
+      void setOut();
+      void setNearBoundary();
+
+    private:
+      IntersectState m_state;
+
+  };
+
+inline SiIntersect::SiIntersect(IntersectState state) 
+  : m_state(state)
+{}
+
+inline bool SiIntersect::in() const 
+{
+  return (m_state == IN);
+}
+
+inline bool SiIntersect::out() const 
+{
+  return (m_state == OUT);
+}
+
+inline bool SiIntersect::nearBoundary() const 
+{
+  return (m_state == BOUNDARY);
+}
+
+
+inline bool SiIntersect::mayIntersect() const 
+{
+  return (m_state == BOUNDARY || m_state == IN);
+}
+
+inline SiIntersect::operator bool() const 
+{
+  return mayIntersect();
+}
+
+inline void SiIntersect::setIn()
+{
+  m_state = IN;
+}
+
+inline void SiIntersect::setOut()
+{
+  m_state = OUT;
+}
+
+inline void SiIntersect::setNearBoundary()
+{
+  m_state = BOUNDARY;
+}
+
+} // namespace InDetDD
+
+#endif  //INDETREADOUTGEOMETRY_SIINTERSECT_H
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiLocalPosition.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiLocalPosition.h
new file mode 100755
index 0000000000000000000000000000000000000000..df4d9c7b13b0c7dfe46faa0a24d58ac0cfd0b66f
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiLocalPosition.h
@@ -0,0 +1,185 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiLocalPosition.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SILOCALPOSITION_H
+#define INDETREADOUTGEOMETRY_SILOCALPOSITION_H
+
+#include "GeoPrimitives/GeoPrimitives.h"
+#include "TrkEventPrimitives/ParamDefs.h"
+
+namespace Trk {
+  enum ExtraLocalPosParam {distDepth = 2}; // These will be defined in Trk soon.
+}
+
+namespace InDetDD {
+
+    /** @class SiLocalPosition
+    Class to represent a position in the natural frame of a silicon sensor, for Pixel and SCT
+    For Pixel: eta=column, phi=row
+
+    Version 2.1 01/08/2001 David Calvet
+    */
+
+  class SiLocalPosition {
+
+
+    ///////////////////////////////////////////////////////////////////
+    // Public methods:
+    ///////////////////////////////////////////////////////////////////
+  public:
+
+    /** Implicit constructor: */
+    SiLocalPosition();
+
+    /** Copy constructor: */
+    SiLocalPosition(const SiLocalPosition &position);
+
+    /** This allows one to pass a Amg::Vector2D  to a SiLocalPosition */
+    SiLocalPosition(const Amg::Vector2D &position);
+
+    /** Constructor with parameters:
+        position along eta direction
+        position along phi direction
+        position along depth direction (default is 0) */
+    SiLocalPosition(const double xEta,const double xPhi,
+  		  const double xDepth=0);
+
+    /** Destructor: */
+    ~SiLocalPosition();
+
+    /** Assignment operator: */
+    SiLocalPosition &operator=(const SiLocalPosition &position);
+
+    ///////////////////////////////////////////////////////////////////
+    // Const methods:
+    ///////////////////////////////////////////////////////////////////
+
+    /** position along eta direction:*/
+    double xEta() const;
+
+    /** position along phi direction:*/
+    double xPhi() const;
+
+    /** position along depth direction: */
+    double xDepth() const;
+
+    /** positions for Pixel: */
+    double xColumn() const;
+    double xRow() const;
+
+    ///////////////////////////////////////////////////////////////////
+    // Non-const methods:
+    ///////////////////////////////////////////////////////////////////
+
+    void xEta(const double xEta);
+
+    void xPhi(const double xPhi);
+
+    void xDepth(const double xDepth);
+
+    // for Pixel:
+    void xColumn(const double xColumn);
+    void xRow(const double xRow);
+
+    // addition of positions:
+    SiLocalPosition &operator+=(const SiLocalPosition &position);
+  
+    // so we can go from SiLocalPosition to Trk::LocalPosition
+    operator Amg::Vector2D(void) const;
+
+
+    // scaling:
+    SiLocalPosition &operator*=(const double factor);
+    SiLocalPosition &operator/=(const double factor);
+
+    ///////////////////////////////////////////////////////////////////
+    // Private data:
+    ///////////////////////////////////////////////////////////////////
+
+  private:
+    double m_xEta; //!< position along eta direction
+    double m_xPhi; //!< position along phi direction
+    double m_xDepth; //!< position along depth direction
+  };
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+inline SiLocalPosition::~SiLocalPosition()
+{}
+
+inline double SiLocalPosition::xEta() const
+{
+  return m_xEta;
+}
+
+inline double SiLocalPosition::xPhi() const
+{
+  return m_xPhi;
+}
+
+inline double SiLocalPosition::xDepth() const
+{
+  return m_xDepth;
+}
+
+inline double SiLocalPosition::xColumn() const
+{
+  return m_xEta;
+}
+
+inline double SiLocalPosition::xRow() const
+{
+  return m_xPhi;
+}
+
+inline void SiLocalPosition::xEta(const double xEta)
+{
+  m_xEta=xEta;
+}
+
+inline void SiLocalPosition::xPhi(const double xPhi)
+{
+  m_xPhi=xPhi;
+}
+
+inline void SiLocalPosition::xDepth(const double xDepth)
+{
+  m_xDepth=xDepth;
+}
+
+inline void SiLocalPosition::xColumn(const double xColumn)
+{
+  m_xEta=xColumn;
+}
+
+inline void SiLocalPosition::xRow(const double xRow)
+{
+  m_xPhi=xRow;
+}
+
+///////////////////////////////////////////////////////////////////
+// Binary operators:
+///////////////////////////////////////////////////////////////////
+SiLocalPosition operator+(const SiLocalPosition &position1,
+			  const SiLocalPosition &position2);
+
+SiLocalPosition operator*(const SiLocalPosition &position,const double factor);
+
+inline SiLocalPosition operator*(const double factor,const SiLocalPosition &position)
+{
+  return position*factor;
+}
+
+SiLocalPosition operator/(const SiLocalPosition &position,const double factor);
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SILOCALPOSITION_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiNumerology.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiNumerology.h
new file mode 100755
index 0000000000000000000000000000000000000000..f52f015470e0438d42884100a57e4b76db4cd945
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiNumerology.h
@@ -0,0 +1,154 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+//   SiNumerology.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+
+#ifndef INDETREADOUTGEOMETRY_SINUMEROLOGY_H
+#define INDETREADOUTGEOMETRY_SINUMEROLOGY_H
+
+#include <vector>
+
+namespace InDetDD {
+
+  /** @class SiNumerology
+  
+     Class to extract numerology for Pixel and SCT. For example number of layers, disks, sectors, rings, etc.
+     See InnerDetector/InDetExample/InDetDetDescrExample/src/SiReadSiDetectorElements.cxx for example of usage.
+
+     @author Grant Gorfine
+   */
+
+  class SiNumerology {
+
+
+    public:
+    
+      /** Constructor: */
+      SiNumerology();
+      
+      // Accessors:
+      
+      /** Number of barrels. Normally 1. */
+      int numBarrels() const; 
+      
+      /** Number of endcaps. Normally 2. */
+      int numEndcaps() const; 
+      
+      /** Barrel/endcap identifier for each barrel. Normally barrelId(0) = 0 */
+      int barrelId(int index) const;
+      
+      /** Barrel/endcap identifier for each endcap. Normally endcapId(0) returns 2, endcapId(1) returns -2 */
+      int endcapId(int index) const;
+      
+      /** Number of layers */
+      int numLayers() const; 
+      
+      /** Number of disks */
+      int numDisks() const; 
+      
+      /** Number of rings (ie eta_module) in a disk */
+      int numRingsForDisk(int disk) const;
+      
+      /** Number of sectors in phi for a layer */
+      int numPhiModulesForLayer(int layer) const;
+      
+      /** Number of sectors in phi for a ring in a disk */
+      int numPhiModulesForDiskRing(int disk, int ring) const;
+      
+      /** Number of sectors in phi for a ring in a disk */
+      int numEtaModulesForLayer(int layer) const;
+      
+      /** First eta_module number for a layer */
+      int beginEtaModuleForLayer(int layer) const;
+      
+      /** Last eta_module number + 1 */
+      int endEtaModuleForLayer(int layer) const;
+      
+      /** Check if eta_module=0 exists */
+      bool skipEtaZeroForLayer(int layer) const;
+      
+      // Check presence of layer/disk
+      /** Check if layer exists */
+      bool useLayer(int layer) const;
+      
+      /** Check if disk exists */
+      bool useDisk(int disk) const;
+      
+      // Maximums 
+      /** Maximum number of modules in a barrel stave */
+      int maxNumBarrelEta() const;
+      
+      /** Maximum number of rings in a disk */
+      int maxNumEndcapRings() const;
+      
+      /** Maximum number of strips. Same as maxNumPhiCells() */
+      int maxNumStrips() const; 
+      
+      /** Maximum number of cells in phi direction. Same as maxNumStrips()  */
+      int maxNumPhiCells() const;
+      
+      /** Maximum number of cells in eta direction. 0 for SCT. */
+      int maxNumEtaCells() const;
+      
+      // Modifiers:
+      void addBarrel(int id);
+      void addEndcap(int id);
+      void setNumLayers(int nLayers); 
+      void setNumDisks(int nDisks); 
+      void setNumRingsForDisk(int disk, int nRings);
+      void setNumPhiModulesForLayer(int layer, int nPhiModules);
+      void setNumPhiModulesForDiskRing(int disk, int ring, int nPhiModules);
+      void setNumEtaModulesForLayer(int layer, int nEtaModules);
+      void setMaxNumEtaCells(int cells);
+      void setMaxNumPhiCells(int cells);
+      
+      // DBM 
+      int numDisksDBM() const; 
+      int numBarrelDBM() const; 
+      bool useDiskDBM(int disk) const; 
+      int numRingsForDiskDBM(int currentdisk) const; 
+      int numPhiModulesForDiskRingDBM(int disk, int ring) const; 
+      int numEndcapsDBM() const; 
+      int endcapIdDBM(int index) const; 
+      
+      void setNumDisksDBM(int nDisks); 
+      void setNumBarrelDBM(int nBarrel); 
+      void setNumPhiModulesForDiskRingDBM(int disk, int ring, int nPhiModules); 
+      void addEndcapDBM(int id); 
+
+    private:
+      
+      int m_numLayers;
+      int m_numDisks;
+      int m_maxPhiCells;
+      int m_maxEtaCells;
+      int m_maxNumBarrelEta;
+      int m_maxNumEndcapRings;
+      int m_maxNumBarrelPhiModules;
+      int m_maxNumEndcapPhiModules;
+    
+      std::vector<int> m_barrelIds;
+      std::vector<int> m_endcapIds;
+      std::vector<int> m_phiModulesForLayer;
+      std::vector<int> m_ringsForDisk;
+      std::vector<std::vector<int> > m_phiModulesForDiskRing;
+      std::vector<int> m_etaModulesForLayer;
+
+      int m_numDisksDBM; 
+      int m_numBarrelDBM; 
+      std::vector<int> m_endcapIdsDBM; 
+      std::vector<std::vector<int> > m_phiModulesForDiskRingDBM; 
+      int m_maxNumEndcapPhiModulesDBM; 
+  };
+  
+}// End namespace
+
+#include "SiNumerology.icc"
+
+#endif // INDETREADOUTGEOMETRY_SINUMEROLOGY_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiNumerology.icc b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiNumerology.icc
new file mode 100644
index 0000000000000000000000000000000000000000..614cc853d31d22a5e5dd8c7d082b1b3642f09f9a
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiNumerology.icc
@@ -0,0 +1,146 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+namespace InDetDD {
+
+inline int SiNumerology::numBarrels() const
+{
+  return m_barrelIds.size();
+}
+
+inline int SiNumerology::numEndcaps() const
+{
+  return m_endcapIds.size();
+}
+
+inline int SiNumerology::barrelId(int index) const
+{
+  return m_barrelIds[index];
+}
+
+inline int SiNumerology::endcapId(int index) const
+{
+  return m_endcapIds[index]; 
+}
+
+inline int SiNumerology::numLayers() const
+{
+  return m_numLayers;
+}
+
+inline int SiNumerology::numDisks() const
+{
+  return m_numDisks;
+}
+
+inline int SiNumerology::numRingsForDisk(int disk) const
+{
+  return m_ringsForDisk[disk];
+}
+
+inline int SiNumerology::numPhiModulesForLayer(int layer) const
+{
+  return m_phiModulesForLayer[layer];
+}
+
+inline int SiNumerology::numPhiModulesForDiskRing(int disk, int ring) const
+{
+  return m_phiModulesForDiskRing[disk][ring];
+}
+
+inline int SiNumerology::numEtaModulesForLayer(int layer) const
+{
+  return m_etaModulesForLayer[layer];
+}
+
+inline int SiNumerology::beginEtaModuleForLayer(int layer) const
+{
+  // Assume symmetric about zero.
+  return -m_etaModulesForLayer[layer]/2;
+}
+
+inline int SiNumerology::endEtaModuleForLayer(int layer) const
+{
+  // Assume symmetric about zero.
+  return m_etaModulesForLayer[layer]/2+1;
+}
+  
+inline bool SiNumerology::skipEtaZeroForLayer(int layer) const
+{
+  // If even then no module at eta = 0.
+  return !(m_etaModulesForLayer[layer]%2);
+}
+
+inline int SiNumerology::maxNumBarrelEta() const
+{
+  return m_maxNumBarrelEta;
+}
+
+inline int SiNumerology::maxNumEndcapRings() const
+{
+  return m_maxNumEndcapRings;
+}
+
+inline int SiNumerology::maxNumStrips() const 
+{
+  return m_maxPhiCells; 
+}
+
+inline int SiNumerology::maxNumPhiCells() const
+{
+  return m_maxPhiCells;
+}
+
+inline int SiNumerology::maxNumEtaCells() const
+{
+  return m_maxEtaCells;
+}
+
+
+inline bool SiNumerology::useLayer(int layer) const
+{
+  return (m_phiModulesForLayer[layer] != 0);
+}
+
+inline bool SiNumerology::useDisk(int disk) const
+{
+  return (m_ringsForDisk[disk] != 0);
+}
+
+inline int SiNumerology::numBarrelDBM() const 
+{ 
+  return 0; 
+} 
+	 
+inline int SiNumerology::numDisksDBM() const 
+{ 
+  return m_numDisksDBM; 
+} 
+	 
+inline bool SiNumerology::useDiskDBM(int disk) const 
+{ 
+  return (disk<numDisksDBM())?1:0; 
+} 
+	 
+inline int SiNumerology::numRingsForDiskDBM(int /*currentdisk*/) const 
+{ 
+  return 1; 
+} 
+	 
+inline int SiNumerology::numPhiModulesForDiskRingDBM(int disk, int ring) const 
+{ 
+  return m_phiModulesForDiskRingDBM[disk][ring]; 
+} 
+	 
+inline int SiNumerology::numEndcapsDBM() const 
+{ 
+  return m_endcapIdsDBM.size(); 
+} 
+ 
+inline int SiNumerology::endcapIdDBM(int index) const 
+{ 
+  return m_endcapIdsDBM[index];  
+} 
+
+} // End namespace
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiReadoutCellId.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiReadoutCellId.h
new file mode 100755
index 0000000000000000000000000000000000000000..fd4463700fbf23dfd787f8bb25c4754c68ed09c9
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SiReadoutCellId.h
@@ -0,0 +1,77 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiReadoutCellId.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_SIREADOUTCELLID_H
+#define INDETREADOUTGEOMETRY_SIREADOUTCELLID_H
+
+// Base class
+#include "InDetReadoutGeometry/SiCellId.h"
+
+namespace InDetDD {
+
+   /** @class SiReadoutCellId 
+
+   Identifier for the strip or pixel readout cell.
+  
+   SiReadoutCellId behaves identically to its base class. Its only
+   introduced to provide some type safety and distiguish between
+   diodes (base class) and readout cells (this class). This is since
+   more than one diode can be connected to a readout cell. 
+
+   The following conversion is legal
+
+        SiReadoutCellId -> SiCellId   OK   
+
+   However the oppoisite is not allowed 
+
+        SiCellId -> SiReadoutCellId   NOT ALLOWED
+
+   since a SiCellId might not have direct readout out (eg for an
+   edge strip or ganged pixel).
+   
+   @author Grant Gorfine
+   */
+
+  class SiReadoutCellId : public SiCellId {
+
+      ///////////////////////////////////////////////////////////////////
+      // Public methods:
+      ///////////////////////////////////////////////////////////////////
+     public:
+  
+      // Allow construction from base class
+      //  explicit SiReadoutCellId(const SiCellIdentifier &);
+
+      SiReadoutCellId(); // Set in invalid state.
+      SiReadoutCellId(int strip);
+      SiReadoutCellId(int phiIndex, int etaIndex);
+
+};
+
+///////////////////////////////////////////////////////////////////
+// Inline methods:
+///////////////////////////////////////////////////////////////////
+
+inline SiReadoutCellId::SiReadoutCellId() 
+  : SiCellId() 
+{}
+
+inline SiReadoutCellId::SiReadoutCellId(int phiIndex, int etaIndex)
+  : SiCellId(phiIndex, etaIndex)
+{}
+
+inline SiReadoutCellId::SiReadoutCellId(int strip)
+  : SiCellId(strip)
+{}
+
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_SIREADOUTCELLID_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SurfaceCache.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SurfaceCache.h
new file mode 100755
index 0000000000000000000000000000000000000000..826c2ba05cc53e47806096a8bfd8fe49da01a53a
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/SurfaceCache.h
@@ -0,0 +1,84 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SurfaceCache.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef InDetReadoutGeometry_SurfaceCache_h
+#define InDetReadoutGeometry_SurfaceCache_h
+
+#include "GeoPrimitives/GeoPrimitives.h"
+#include "TrkSurfaces/SurfaceBounds.h"
+
+namespace InDetDD {
+
+    /** @class SurfaceCache
+    
+       This class is for internal use in InDetReadoutGeometry.
+       It holds all the cached values related to the element surface.
+       
+       It's a simple class to still alllow the 
+       Trk::Surface::transform() { m_associatedDetectorElement->transform() }
+       method to work, hence, it basically copies the Trk::Surface structure.
+       
+       The surface cache class alows also to store 0 pointers,
+       indicating the the holder of the cache has a commonly shared object,
+       e.g. the straw bounds of all straws in one detector element.
+       
+       @author: Grant Gorfine, Andreas Salzburger 
+    */
+         
+    class SurfaceCache
+    {
+    
+    public:
+      SurfaceCache(const Amg::Transform3D* transform,
+    		         const Amg::Vector3D* center,
+    		         const Amg::Vector3D* normal,
+    		         const Trk::SurfaceBounds* bounds);
+    
+      ~SurfaceCache();
+    
+      const Amg::Transform3D* transform() {return (m_transform);}
+      
+      const Amg::Vector3D* center() {return (m_center);}
+      
+      const Amg::Vector3D*  normal() {return (m_normal);}
+      
+      const Trk::SurfaceBounds* bounds() {return (m_bounds);}
+    
+    private:
+      const Amg::Transform3D*       m_transform;
+      const Amg::Vector3D*          m_center;
+      const Amg::Vector3D*          m_normal;
+      const Trk::SurfaceBounds*     m_bounds;
+    
+    };
+      
+    inline SurfaceCache::SurfaceCache(const Amg::Transform3D* transform,
+    			                      const Amg::Vector3D* center,
+    			                      const Amg::Vector3D* normal,
+    			                      const Trk::SurfaceBounds* bounds)
+      : m_transform(transform),
+        m_center(center),
+        m_normal(normal),
+        m_bounds(bounds)
+    {}
+    
+    
+    inline SurfaceCache::~SurfaceCache()
+    {
+      delete m_transform;
+      delete m_center;
+      delete m_normal;
+      delete m_bounds;
+    }
+
+} // end namespace
+
+  
+#endif // InDetReadoutGeometry_SurfaceCache_h
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelCode.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelCode.h
new file mode 100755
index 0000000000000000000000000000000000000000..e8a4b9bd5206fc334b0345a917292081f0fbb11e
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelCode.h
@@ -0,0 +1,145 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TRT_BarrelCode.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRT_BarrelCode_h
+#define TRT_BarrelCode_h 1
+
+#include <iostream>
+
+// Include the string class header
+#include <string>
+
+namespace InDetDD {
+
+  /** @class TRT_BarrelCode 
+  
+        bit definitions to decode TRT straws in barrel
+  */
+
+  class TRT_BarrelCode 
+    {
+    public:
+      
+      typedef enum { MODULE_A   = 0, 
+		     MODULE_B   = 1,
+		     MODULE_C   = 2 }       Module;
+      
+      TRT_BarrelCode();
+      TRT_BarrelCode( unsigned int  isPositive, unsigned int moduleIndex, unsigned phiIndex, unsigned int strawLayerIndex); 
+      
+      TRT_BarrelCode( const TRT_BarrelCode & right );
+      ~TRT_BarrelCode();
+      
+      const TRT_BarrelCode & operator=( const TRT_BarrelCode & right );
+      
+      bool operator < (const TRT_BarrelCode & right) const;
+      bool operator > (const TRT_BarrelCode & right) const;
+      bool operator== (const TRT_BarrelCode & right) const;
+      bool operator!= (const TRT_BarrelCode & right) const;
+      
+      unsigned int isPosZ()              const;
+      unsigned int getModuleIndex()      const;
+      unsigned int getPhiIndex()         const;
+      unsigned int getStrawLayerIndex()  const;
+      unsigned int getKey()              const;
+      std::string getName()              const;
+      
+    private:  
+      
+      // Define key as a bit string:
+      //   bit 0    Z (negative=0 or positive=1)
+      //   bit 1-2  Module Index (0-2)
+      //   bit 3-7  Phi Index
+      //   bit 8-12 StrawLayer Index
+      
+      unsigned short int _key;
+      
+      static const int Z_MASK;
+      static const int MODULE_MASK;
+      static const int PHI_MASK;
+      static const int STRAWLAYER_MASK;
+      
+      
+      static const int Z_SHIFT;
+      static const int MODULE_SHIFT;
+      static const int PHI_SHIFT;
+      static const int STRAWLAYER_SHIFT;
+      
+  };
+ 
+  
+  
+  inline unsigned int TRT_BarrelCode::isPosZ() const {
+    unsigned int ret = _key;
+    return (ret >> Z_SHIFT) & Z_MASK;
+  }
+  
+  inline unsigned int TRT_BarrelCode::getModuleIndex() const{
+    unsigned int ret = _key;
+    return (ret >> MODULE_SHIFT) & MODULE_MASK;
+  }
+  
+  inline unsigned int TRT_BarrelCode::getPhiIndex() const{
+    unsigned int ret = _key;
+    return (ret >> PHI_SHIFT) & PHI_MASK;
+  }
+  
+  inline unsigned int TRT_BarrelCode::getStrawLayerIndex() const {
+    unsigned int ret = _key;
+    return (ret >> STRAWLAYER_SHIFT) & STRAWLAYER_MASK;
+  }
+  
+  inline unsigned int TRT_BarrelCode::getKey() const {
+    return _key;
+  }
+  
+  
+  inline bool TRT_BarrelCode::operator==(const TRT_BarrelCode &right) const
+    {
+      return (getKey() == right.getKey());
+    }
+  
+  inline bool TRT_BarrelCode::operator!=(const TRT_BarrelCode &right) const
+    {
+      return (getKey() != right.getKey());
+    }
+  
+  inline bool TRT_BarrelCode::operator<(const TRT_BarrelCode &right) const
+    {
+      return (getKey() < right.getKey());
+    }
+  
+  inline bool TRT_BarrelCode::operator>(const TRT_BarrelCode &right) const
+    {
+      return (getKey() > right.getKey());
+    }
+} // End InDetDD namespace
+
+  
+inline std::ostream & operator << (std::ostream & os, const InDetDD::TRT_BarrelCode & code) {
+  // Plus/minus 
+  if (code.isPosZ()) os << '+';
+  else os << '-';
+  // Module
+  unsigned int mod = code.getModuleIndex();
+  if (mod==0) os << 'A';
+  else if (mod==1) os << 'B';
+  else if (mod==2) os << 'C';
+  else os << "?";
+  // Phi Index:
+  os << code.getPhiIndex();
+  // Separator:
+  os << '/';
+  // StrawLayer:  
+  os << code.getStrawLayerIndex();
+  return os;
+}
+
+#endif
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelDescriptor.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelDescriptor.h
new file mode 100755
index 0000000000000000000000000000000000000000..4fb3533e853489f3fd3ba71faeb0ab822cd3e925
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelDescriptor.h
@@ -0,0 +1,117 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TRT_BarrelDescriptor.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRT_BarrelDescriptor_h
+#define TRT_BarrelDescriptor_h 1
+#include "GeoModelKernel/RCBase.h"
+#include "GeoModelKernel/GeoXF.h"
+#include <vector>
+
+namespace Trk{
+  class CylinderBounds;
+  class SurfaceBounds;
+}
+
+namespace InDetDD {
+
+      /** @class TRT_BarrelDescriptor 
+       
+         Local Straw Positions (from the center of the module.)  
+                                                               
+         The center of the module is defined like this:          
+                                                               
+                              .--------.                       
+                             / \      /                       
+                            /   \    /                         
+                           /  o  \  /                          
+                          /_______\/                                        
+                                                               
+       */
+  
+  class TRT_BarrelDescriptor : public RCBase  
+    {
+      
+    public:
+      
+      /** Constructor: */
+      TRT_BarrelDescriptor();
+      
+      /** Add a new straw at position x, y: */
+      void addStraw(double xPos, double yPos);
+      
+      /**  Sets the transform field for straws and offset. Ownership is not passed. */
+      void setStrawTransformField(const GeoXF::Function *xf, size_t offsetInto);
+
+      /** Get X Position: */
+      inline double & strawXPos       (unsigned int i);
+      inline const double & strawXPos (unsigned int i) const;
+      
+      /** Get Y Position: */
+      inline double & strawYPos       (unsigned int i);
+      inline const double & strawYPos (unsigned int i) const;
+      
+      /** Get the number of straws: */
+      inline unsigned int nStraws() const;
+      
+      /** Get the length of the straws: */
+      inline const double & strawLength() const;
+      inline double & strawLength();
+      inline void strawLength(double newLength);
+
+      /** Get inner tube radius of the straw */
+      inline double innerTubeRadius() const;
+    
+      /** Dead part */
+      inline const double & strawZDead() const;
+      inline double & strawZDead();
+      inline void strawZDead(double zDead);      
+
+      /** Position of center of active region. */
+      inline const double & strawZPos() const;
+      inline double & strawZPos();
+      inline void strawZPos(double Pos);      
+
+      /** Get the tranformation field, which we do not own:
+          Does not include the z shift which is different for pos and
+          negative barrel: */
+      inline const GeoXF::Function *getStrawTransform() const;
+      
+      /** Get the offset into the transformation field: */
+      inline size_t getStrawTransformOffset() const;
+
+      /** Get Bounds */
+      const Trk::SurfaceBounds & strawBounds() const;
+
+    protected:
+      
+      virtual ~TRT_BarrelDescriptor();
+      
+    private:
+      
+      TRT_BarrelDescriptor(const TRT_BarrelDescriptor &right);
+      const TRT_BarrelDescriptor & operator=(const TRT_BarrelDescriptor &right);
+      
+      std::vector<double> _x;
+      std::vector<double> _y;
+      double              _length;
+      double              _zDead;
+      double              _zPos;
+      double              m_innerTubeRadius; 
+      const GeoXF::Function *_f;
+      size_t                 _o;
+
+      mutable Trk::CylinderBounds * m_bounds;
+
+    };
+}
+#include "TRT_BarrelDescriptor.icc"
+#endif
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelDescriptor.icc b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelDescriptor.icc
new file mode 100755
index 0000000000000000000000000000000000000000..d7a5247ecd62cc4f89597e089c6270050c807b62
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelDescriptor.icc
@@ -0,0 +1,78 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+namespace InDetDD {
+inline double & TRT_BarrelDescriptor::strawXPos       	(unsigned int i) {
+  return _x[i];
+}
+
+inline const double & TRT_BarrelDescriptor::strawXPos (unsigned int i) const {
+  return _x[i];
+}
+
+inline double & TRT_BarrelDescriptor::strawYPos       (unsigned int i) {
+  return _y[i];
+}
+inline const double & TRT_BarrelDescriptor::strawYPos (unsigned int i) const {
+  return _y[i];
+}
+
+inline unsigned int TRT_BarrelDescriptor::nStraws() const {
+  return _x.size();
+}
+
+inline const double & TRT_BarrelDescriptor::strawLength() const {
+  return _length;
+}
+
+inline double & TRT_BarrelDescriptor::strawLength() {
+  return _length;
+}
+
+inline void TRT_BarrelDescriptor::strawLength(double newLength) {
+  _length = newLength;
+}
+
+ 
+inline double TRT_BarrelDescriptor::innerTubeRadius() const
+{
+  return m_innerTubeRadius;
+}
+
+
+inline const double & TRT_BarrelDescriptor::strawZDead() const  {
+  return _zDead;
+}
+
+inline double & TRT_BarrelDescriptor::strawZDead()  {
+  return _zDead;
+}
+
+inline void TRT_BarrelDescriptor::strawZDead(double zDead)  {
+  _zDead = zDead;
+}
+
+inline const double & TRT_BarrelDescriptor::strawZPos() const  {
+  return _zPos;
+}
+
+inline double & TRT_BarrelDescriptor::strawZPos()  {
+  return _zPos;
+}
+
+inline void TRT_BarrelDescriptor::strawZPos(double zPos)  {
+  _zPos = zPos;
+}
+
+inline const GeoXF::Function * TRT_BarrelDescriptor::getStrawTransform() const {
+  return _f;
+}
+
+inline size_t TRT_BarrelDescriptor::getStrawTransformOffset() const {
+  return _o;
+}
+
+
+
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelElement.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelElement.h
new file mode 100755
index 0000000000000000000000000000000000000000..4ebb5443a8b2d8f564a70c0b2c0f3a7c123e8541
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelElement.h
@@ -0,0 +1,163 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TRT_BarrelElement.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRT_BarrelElement_h
+#define TRT_BarrelElement_h 1
+#include "InDetReadoutGeometry/TRT_BarrelCode.h"
+#include "InDetReadoutGeometry/TRT_BarrelDescriptor.h"
+#include "InDetReadoutGeometry/TRT_BaseElement.h"
+
+class TRT_ID;
+
+namespace Trk{
+  class Surface;
+  class SurfaceBounds;
+}
+
+class SurfaceCache;
+
+namespace InDetDD {
+  
+  class TRT_BarrelConditions;
+  
+  /** @class TRT_BarrelElement 
+   
+      Extended TRT_BaseElement to describe a TRT readout element,
+      this is a planar layer with n ( order of 20 ) straws, in one
+      of the 32 sectors of the TRT barrel.
+      
+      The number of straws described by this readout element can be 
+      retrieved by nStraws() 
+      
+      @author: Grant Gorfine
+      - modified & maintained: Nick Styles, Andreas Salzburger
+      */
+   
+  class TRT_BarrelElement : public TRT_BaseElement  {
+    
+  public:
+    
+    /** Constructor: */
+    TRT_BarrelElement(const GeoVFullPhysVol *volume, 
+		      const TRT_BarrelDescriptor *descriptor, 
+		      bool isPositive, 
+		      unsigned int modIndex, 
+		      unsigned int phiIndex, 
+		      unsigned int strawLayIndex,
+		      const TRT_ID * idHelper,
+		      const TRT_Conditions * conditions);
+    
+    /** Destructor: */
+    virtual ~TRT_BarrelElement();
+    
+    /** Type information */
+    virtual TRT_BaseElement::Type type() const {return TRT_BaseElement::BARREL;} 
+
+    /**	Returns a pointer to conditions data.  This includes
+    	information on dead and noisy wires, as well as wire
+    	sags. */
+    const TRT_BarrelConditions * getConditionsData() const;
+    
+    /**	Returns a pointer to a descriptor, giving common
+    	information on module construction: */
+    const TRT_BarrelDescriptor * getDescriptor() const;
+    
+    /** Get X Position:
+        DEPRECATED. Please use starwCenter(i).x() */
+    inline double strawXPos (unsigned int i) const;
+    
+    /** Get Y Position:
+        DEPRECATED. Please use starwCenter(i).y() */
+    inline double strawYPos (unsigned int i) const;
+    
+    /** Get Z Position:  (active center)
+       DEPRECATED. Please use starwCenter(i).z() */
+    inline double strawZPos (unsigned int i) const;
+    
+    /** Default Local -> global transform of the straw (ie before alignment corrections) */
+    virtual HepGeom::Transform3D defStrawTransform(int straw) const;
+ 
+    /** Get the number of straws: */
+    virtual unsigned int nStraws() const;
+    
+    /** Get the length of the straws (active length): */
+    virtual const double & strawLength() const;
+
+    /**  StrawDirection. +1 if axis is in same direction as local coordinate, -1 otherwise. */
+    virtual int strawDirection() const;
+
+    /**	Returns the next-in-phi detector element, or zero if none (forseeing gaps, in other words). */
+    const TRT_BarrelElement * nextInPhi() const;
+    
+    /**	Returns the previous-in-phi detector element, or zero if none (forseeing gaps, in other words). */
+    const TRT_BarrelElement * previousInPhi() const;
+    
+    /**	Returns the next-in-R detector element, or zero if none. */
+    const TRT_BarrelElement * nextInR() const;
+    
+    /** Returns the next-in-R detector element, or zero if none. */
+    const TRT_BarrelElement * previousInR() const;
+    
+    /**	Sets the next-in-phi detector. */
+    void  setNextInPhi(const TRT_BarrelElement *element);
+    
+    /**	Sets the previous-in-phi detector. */
+    void  setPreviousInPhi(const TRT_BarrelElement *element);
+    
+    /**	Sets the next-in-r detector. */
+    void  setNextInR(const TRT_BarrelElement *element);
+    
+    /**	Sets the previous-in-r detector. */
+    void  setPreviousInR(const TRT_BarrelElement *element);
+    
+    /**	Doomed (?): */
+    const TRT_BarrelCode & getCode() const;
+    
+    /** Surface bounds */
+    virtual const Trk::SurfaceBounds & strawBounds() const;
+
+  private:
+    
+    /** Illegal Operations: */
+    TRT_BarrelElement(const TRT_BarrelElement &right);
+    const TRT_BarrelElement & operator=(const TRT_BarrelElement &right);
+
+  protected:
+    /** These transforms are effectively to the local coord
+      system of a straw derived from GeoModel -> hence CLHEP */
+    HepGeom::Transform3D calculateStrawTransform(int straw) const;
+    HepGeom::Transform3D calculateLocalStrawTransform(int straw) const;
+
+    /** return the surface of the element */ 
+    const Trk::Surface & elementSurface() const;
+    
+    /** create the cache for the element */
+    void createSurfaceCache() const;
+
+  protected:
+    // Protected Member data:
+    TRT_BarrelCode              _code;
+    const TRT_BarrelDescriptor *_descriptor;
+    const TRT_BarrelElement    *_nextInPhi;
+    const TRT_BarrelElement    *_previousInPhi;
+    const TRT_BarrelElement    *_nextInR;
+    const TRT_BarrelElement    *_previousInR;
+
+    mutable Trk::Surface*       m_surface;
+    
+  };
+  
+
+}
+
+#include "TRT_BarrelElement.icc"
+#endif
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelElement.icc b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelElement.icc
new file mode 100755
index 0000000000000000000000000000000000000000..d7afd0e8b052dc8391221a85b3bfc2db55ae8730
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BarrelElement.icc
@@ -0,0 +1,59 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetIdentifier/TRT_ID.h"
+
+namespace InDetDD {
+
+inline const TRT_BarrelElement * TRT_BarrelElement::nextInPhi() const
+{
+  return _nextInPhi;
+}
+
+inline const TRT_BarrelElement * TRT_BarrelElement::previousInPhi() const
+{
+  return _previousInPhi;
+}
+
+inline const TRT_BarrelElement * TRT_BarrelElement::nextInR() const
+{
+  return _nextInR;
+}
+
+inline const TRT_BarrelElement * TRT_BarrelElement::previousInR() const
+{
+  return _previousInR;
+}
+
+inline const TRT_BarrelCode & TRT_BarrelElement::getCode() const
+{
+  return _code;
+}
+
+
+// Get X Position - should not be used anymore
+inline double TRT_BarrelElement::strawXPos (unsigned int straw) const {   
+  return strawCenter(straw).x();
+}
+  
+// Get Y Position - should not be used anymore
+inline double TRT_BarrelElement::strawYPos (unsigned int straw) const {
+    return strawCenter(straw).y();
+}
+  
+// Get Z Position - should not be used anymore
+inline double TRT_BarrelElement::strawZPos (unsigned int straw) const {
+    return strawCenter(straw).z();
+}
+
+// Get the number of straws:
+inline unsigned int  TRT_BarrelElement::nStraws() const {
+  return _descriptor->nStraws();	
+}
+
+// Get the length of the straws:
+inline const double & TRT_BarrelElement::strawLength() const {
+  return _descriptor->strawLength();	
+}
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BaseElement.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BaseElement.h
new file mode 100755
index 0000000000000000000000000000000000000000..8fe2e4e0fc580a7dee8bfe0c24485d0b142bf9d9
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BaseElement.h
@@ -0,0 +1,235 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TRT_BaseElement.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRT_BaseElement_h
+#define TRT_BaseElement_h 1
+
+#include "TrkDetElementBase/TrkDetElementBase.h"
+
+#include "Identifier/IdentifierHash.h"
+#include "Identifier/Identifier.h"
+
+#include "GeoPrimitives/GeoPrimitives.h"
+#include "CLHEP/Geometry/Transform3D.h"
+#include "CLHEP/Geometry/Point3D.h"
+
+#include <vector>
+
+namespace Trk {
+  class Surface;
+  class StraightLineSurface;
+}
+
+
+class TRT_ID;
+
+namespace InDetDD {
+
+  class SurfaceCache;
+  class TRT_Conditions;
+
+  /** @class TRT_BaseElement 
+  
+      Virtual base class of TRT readout elements.
+      Differently to the Silicon readout elements, the TRT readoutelements describe multiple readout surfaces,
+      i.e. several straws that are described by a surface, such as e.g. a planar sector surface in the barrel,
+      or a disc surface in the endcap.
+
+      @author Grant Gorfine
+      - modified& maintained: Andreas Salzburger, Nick Styles
+      
+      */
+  
+  class TRT_BaseElement : public Trk::TrkDetElementBase  {
+    
+  public:
+    
+    enum Type {BARREL, ENDCAP};
+
+    /** Constructor: */
+    TRT_BaseElement(const GeoVFullPhysVol *volume, const Identifier& id, const TRT_ID* idHelper, const TRT_Conditions* conditions);
+    
+    /** Destructor: */
+    virtual ~TRT_BaseElement();
+    
+    /** Type information: returns BARREL or ENDCAP */
+    virtual TRT_BaseElement::Type type() const = 0; 
+
+    /** identifier of this detector element: */
+    virtual Identifier identify() const;
+
+    /** identifier hash */
+    virtual IdentifierHash identifyHash() const;
+
+    // --- GeoModel transformation forwards ----------------------------------------------------- //
+
+    /** Get Default Transform (of module in barrel, layer in endcap) from GeoModel before alignment corrections: CLHEP */
+    const HepGeom::Transform3D& defTransform() const;
+    
+    /** Default Local -> global transform of the straw (ie before alignment corrections) : CLHEP */
+    virtual HepGeom::Transform3D defStrawTransform(int straw) const = 0;
+    
+    /** This is an alias to strawTransform(int straw) */
+    const HepGeom::Transform3D getAbsoluteTransform(int straw) const;
+    
+    // ---- Surface & Tracking information cache ------------------------------------------------ //
+    // (a) Element Surface section - accesses the m_surfaceCache store
+    
+    /** Element Surface: access to the Surface (straw layer) */
+    virtual const Trk::Surface& surface () const;
+    
+    /** Straw layer bounds */
+    virtual const Trk::SurfaceBounds& bounds() const;
+        
+    /** Element Surface: Get Transform of element in Tracking frame: Amg */
+    virtual const Amg::Transform3D& transform() const;
+
+    /** Element Surface: center of a straw layer. */
+    virtual const Amg::Vector3D& center() const;
+    
+    /** Element Surface: normal of a straw layer */
+    virtual const Amg::Vector3D& normal() const;
+    
+    // (b) Straw Surface section - accesses the vector<SurfaceCache> m_strawSurfacesCache store
+    
+    /** Straw Surface: access to the surface via identifier */
+    virtual const Trk::Surface& surface (const Identifier& id) const;
+
+    /** Straw Surface: access to the bounds via Identifier */
+    virtual const Trk::SurfaceBounds& bounds(const Identifier& id) const;
+
+    /** Straw Surface: access to the transform of individual straw in Tracking frame: Amg */
+    virtual const Amg::Transform3D& transform(const Identifier& id) const;
+
+    /** Straw transform - fast access in array, in Tracking frame: Amg */
+    /** Straw Surface: access to the transform of individual straw in Tracking frame: Amg */
+    virtual const Amg::Transform3D& strawTransform(unsigned int straw) const;
+            
+    /** Straw Surface: Center of a straw using Identifier 
+        Straw center and straw axis can be obtained by the following:
+        (The straw center is the center of the active region)
+        Amg::Transform3D& transform = element->strawTransform(straw);
+        Amb::Vector3D& center = element->strawCenter(); 
+        double r = element->strawCenter()->perp();
+        double phi = element->strawCenter()->phi();
+        Amg::Vector3D strawAxis =  element->strawTransform(straw)* Vector3D(0,0,1) * strawDirection() */
+        
+    virtual const Amg::Vector3D& center(const Identifier& id) const;
+
+    /** Normal of a straw. (Not very meaningful). */
+    virtual const Amg::Vector3D& normal(const Identifier& id) const;
+    
+    /** Straw Surface: access to the surface via integer */
+    const Trk::StraightLineSurface& strawSurface(int straw) const;
+    
+    /** Straw Surface: Local -> global transform of the straw via integer */
+    const Amg::Transform3D& strawTransform(int straw) const;
+    
+    /** Straw Surface: Local -> global transform of the straw via integer */
+    const Amg::Vector3D& strawCenter(int straw) const;
+    
+    /** Straw axis. Always in direction of increasing eta.
+        +ve z direction in barrel (for both +ve and -ve half)  
+        Away from beam pipe in -ve z endcap,
+        Towards beam pipe in +ve endcap. */
+    Amg::Vector3D strawAxis(int straw) const;
+      
+    /** Number of straws in the element. */
+    virtual unsigned int nStraws() const = 0;
+
+    /** Active straw length */
+    virtual const double& strawLength() const = 0;
+    
+    /** StrawDirection. +1 if axis is in same direction as local z axis, -1 otherwise. */
+    virtual int strawDirection() const = 0;
+
+    // ---- CLHEP methods ---- to be checked if needed --------------------------------------------- (start)
+    // the cache changed to Amg, hence CLHEP methods don't return by reverence anymore
+
+    /** Element Surface: Get Transform of element in Tracking frame - CLHEP converted */
+    virtual const HepGeom::Transform3D transformCLHEP() const;
+
+    /**  Element Surface: Straw center - CLHEP converted*/
+    virtual const HepGeom::Point3D<double> centerCLHEP() const;
+
+    /**  Element Surface: Normal of a straw layer - CLHEP converted */
+    virtual const HepGeom::Vector3D<double> normalCLHEP() const; 
+
+    /** Straw Surface : get Transform of individual straw in Tracking frame - CLHEP converted */
+    virtual const HepGeom::Transform3D transformCLHEP(const Identifier& id) const;
+
+    /** Straw Surface : Center of a straw using Identifier - CLHEP converted */
+    virtual const HepGeom::Point3D<double> centerCLHEP(const Identifier& id) const;
+
+    /** Straw Surface : Center of a straw using Identifier - CLHEP converted */
+    virtual const HepGeom::Vector3D<double> normalCLHEP(const Identifier& id) const;
+
+    // ---- CLHEP methods ---- to be checked if needed ---------------------------------------------  (end)
+   
+    /** Invalidate cache */
+    void invalidate() const;
+
+    /** Update all caches */
+    void updateAllCaches() const;
+
+    /** Return the TRT_Conditions object associated to this Detector element */
+    const TRT_Conditions* conditions() const;
+
+
+  protected:
+    /** to be overloaded by the extended classes */
+    virtual   HepGeom::Transform3D calculateStrawTransform(int straw) const = 0;
+
+    /** the straw bounds */
+    virtual const Trk::SurfaceBounds&  strawBounds() const = 0; 
+    
+    /** creates surface for detector element, to be implemented in derived class */
+    virtual const Trk::Surface&  elementSurface() const = 0; 
+    
+    /** create the surface cache of the detector element, to be implementd in the deried class */
+    virtual void createSurfaceCache() const = 0;
+    
+    /** create the surface & surface cache for the straw */
+    void createSurfaceCache(Identifier id) const;
+    
+    /** invalidate action on the cache */
+    virtual void invalidateOther()     const {};
+
+  private:
+    
+    /** Illegal operations: */
+    TRT_BaseElement(const TRT_BaseElement&right);
+    const TRT_BaseElement& operator=(const TRT_BaseElement&right);
+
+    /** Helper method for cache dealing */
+    void deleteCache() const;
+
+  protected:
+
+    Identifier                                          m_id;
+    IdentifierHash                                      m_idHash;
+    const TRT_ID*                                       m_idHelper;
+    const TRT_Conditions*                               m_conditions;
+    
+    // Amg cache for the straw surfaces 
+    mutable std::vector<Trk::StraightLineSurface*>*     m_strawSurfaces;
+    mutable std::vector<SurfaceCache*>*                 m_strawSurfacesCache;
+    
+    //!< helper element surface for the cache   
+    mutable SurfaceCache*                               m_surfaceCache;
+
+  };
+    
+}
+
+#include "TRT_BaseElement.icc"
+#endif
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BaseElement.icc b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BaseElement.icc
new file mode 100755
index 0000000000000000000000000000000000000000..828631ffe639d43c00fb32dde2a0a5adf0a6d0bc
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_BaseElement.icc
@@ -0,0 +1,12 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+namespace InDetDD {
+	
+inline const HepGeom::Transform3D & TRT_BaseElement::defTransform() const
+{
+  return getMaterialGeom()->getDefAbsoluteTransform();
+}
+
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_Conditions.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_Conditions.h
new file mode 100755
index 0000000000000000000000000000000000000000..2c1551d6694b4d7ce8905b6d0c28cfd5d1159b30
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_Conditions.h
@@ -0,0 +1,49 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TRT_Conditions.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_TRT_CONDITIONS_H
+#define INDETREADOUTGEOMETRY_TRT_CONDITIONS_H
+
+#include "GeoModelKernel/RCBase.h"
+#include "CLHEP/Geometry/Transform3D.h"
+
+namespace TRTCond {
+  class StrawDxContainer;
+}
+
+namespace InDetDD {
+
+    /** @class TRT_Conditions
+        
+        This class is a interface to conditions objects. There is a single instance shared by all TRT elements
+      */
+
+  class TRT_Conditions : public RCBase {
+  
+    public:
+  
+      TRT_Conditions();
+  
+      const TRTCond::StrawDxContainer* dxContainer() const;
+      void setDxContainer(const TRTCond::StrawDxContainer* container);
+
+      const HepGeom::Transform3D & solenoidFrame() const;
+      void setSolenoidFrame(const HepGeom::Transform3D & frame);
+
+    private:
+      mutable const TRTCond::StrawDxContainer* m_dxContainer;
+      mutable HepGeom::Transform3D m_solenoidFrame;
+  
+  };
+
+} // end namespace
+
+#endif // INDETREADOUTGEOMETRY_TRT_CONDITIONS_H
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_DetElementCollection.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_DetElementCollection.h
new file mode 100755
index 0000000000000000000000000000000000000000..c85a8381727930d91b301807fc2b844e086dfeb4
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_DetElementCollection.h
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDetectorElementCollection.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+
+#ifndef INDETREADOUTGEOMETRY_TRT_DETELEMENTCOLLECTION_H
+#define INDETREADOUTGEOMETRY_TRT_DETELEMENTCOLLECTION_H
+
+#include <vector>
+
+namespace InDetDD {
+
+class TRT_BaseElement;
+
+/// Class to hold collection of TRT detector elements. 
+
+class TRT_DetElementCollection : public std::vector<const TRT_BaseElement *>
+{};
+
+} // namespace InDetDD
+
+#endif // INDETREADOUTGEOMETRY_TRT_DETELEMENTCOLLECTION_H
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_DetectorManager.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_DetectorManager.h
new file mode 100755
index 0000000000000000000000000000000000000000..bb6df7eba3888905f478a5e7effa436e38bb3604
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_DetectorManager.h
@@ -0,0 +1,265 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TRT_DetectorManager.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRT_DetectorManager_h
+#define TRT_DetectorManager_h 1
+#include "InDetReadoutGeometry/InDetDetectorManager.h"
+#include "InDetReadoutGeometry/TRT_BarrelElement.h"
+#include "InDetReadoutGeometry/TRT_EndcapElement.h"
+#include "InDetReadoutGeometry/Version.h"
+#include "InDetReadoutGeometry/TRT_DetElementCollection.h"
+#include "GeoModelKernel/GeoVPhysVol.h"
+#include "InDetIdentifier/TRT_ID.h"
+#include "GeoModelKernel/GeoXF.h"
+#include "AthenaKernel/IIOVSvc.h"
+
+#include "CLHEP/Geometry/Transform3D.h"
+
+#include "InDetReadoutGeometry/InDetDD_Defs.h"
+
+#include <vector>
+#include <string>
+#include <map>
+
+class Identifier;     
+class GeoAlignableTransform;
+class StoreGateSvc;
+
+namespace InDetDD {
+
+  class TRT_Numerology;
+  class ExtendedAlignableTransform;
+
+
+
+  /** class TRT_DetectorManager
+  
+    The Detector Manager for all TRT Detector elements,
+    it acts as the interface to the detector elements which can be retrieved
+    from the TRT_DetectorManager either via numerology or Identifier access. 
+  
+    In addition, the alignable transforms are set via Identifer and forwarded
+    to the GeoModel class; hence, we are sitting at the interface between
+    CLHEP and AMG.
+  
+    @author Grant Gorfine
+     modified & maintined: Nick Styles, Andreas Salzburger
+     
+  */
+  
+  class TRT_DetectorManager : public InDetDetectorManager  {
+    
+  public:
+    
+    // Constructor
+    TRT_DetectorManager(StoreGateSvc * detStore = 0);
+    
+    // Destructor
+    ~TRT_DetectorManager();
+    
+    /** Access Raw Geometry:-------------------------------------------------------*/
+    virtual unsigned int getNumTreeTops()           const;                          //
+    virtual PVConstLink  getTreeTop(unsigned int i) const;                         //
+    //-----------------------------------------------------------------------------//
+    
+    /** Get the ID helper: --------------------------------------------------------*/
+    void setIdHelper(const TRT_ID * idHelper, bool owns=true);                     //
+    //-----------------------------------------------------------------------------//
+
+
+    //** Get and set information about gasType. -----------------------------------*/
+    enum ActiveGasType { unknown, oldgas, newgas };                                //
+    ActiveGasType gasType() const;                                                 //
+    void setGasType(const ActiveGasType &);                                        //
+    //-----------------------------------------------------------------------------//
+  
+    /** Get and set information about digitization version ------------------------*/
+    unsigned int digitizationVersion() const;                                      //
+    std::string digitizationVersionName() const;                                   //
+    void setDigitizationVersion(const unsigned int &, const std::string& name );   //
+    //-----------------------------------------------------------------------------//
+  
+    /** Access Numerological information:------------------------------------------*/
+    TRT_Numerology *getNumerology();                                               //
+    const TRT_Numerology * getNumerology() const;                                  //
+    //-----------------------------------------------------------------------------//
+
+   
+    /** Access Elements Generically------------------------------------------------*/
+    const TRT_BaseElement *getElement(Identifier id) const;       // Slow          //
+    const TRT_BaseElement *getElement(IdentifierHash id) const;   // Fast          //
+    //-----------------------------------------------------------------------------//
+
+
+    /** Access to Whole Collection of Elements -------------------------------------*/
+    const TRT_DetElementCollection * getDetectorElementCollection() const;
+    TRT_DetElementCollection::const_iterator getDetectorElementBegin() const;
+    TRT_DetElementCollection::const_iterator getDetectorElementEnd() const;
+
+    //-----------------------------------------------------------------------------//
+
+    
+    /** Access Barrel Elements:------------------(Fast)----------------------------*/
+    const TRT_BarrelElement *getBarrelElement(unsigned int positive,               //
+					                          unsigned int moduleIndex,            //
+					                          unsigned int phiIndex,               //
+					                          unsigned int strawLayerIndex) const; //
+    TRT_BarrelElement *getBarrelElement(unsigned int positive,                     //
+					                    unsigned int moduleIndex,                  //
+					                    unsigned int phiIndex,                     //
+					                    unsigned int strawLayerIndex);             //
+    //                                                                             //
+    //-----------------------------------------------------------------------------//
+  
+    
+    /** Access Endcap Elements:------------------(Fast)-----------------------------*/
+    const TRT_EndcapElement *getEndcapElement(unsigned int positive,               //
+					                          unsigned int wheelIndex,             //
+					                          unsigned int strawLayerIndex,        //
+					                          unsigned int phiIndex) const;        //
+    TRT_EndcapElement *getEndcapElement(unsigned int positive,                     //
+					                    unsigned int wheelIndex,                   //
+					                    unsigned int strawLayerIndex,              //
+					                    unsigned int phiIndex);                    //
+    //                                                                             //
+    //-----------------------------------------------------------------------------//
+
+    /** Conditions interface (mostly for internal use):----------------------------*/
+    void setConditions(TRT_Conditions * conditions);                               //
+    const TRT_Conditions * conditions() const;                                     //
+    //-----------------------------------------------------------------------------//    
+    
+    
+    // This is for Detector Descriptors -------------------------------------------//
+    void addTreeTop(PVLink);                                                       //
+    //                                                                             //
+    // Manage the barrel elements:                                                 //
+    void manageBarrelElement(TRT_BarrelElement *barrel);                           //
+    //                                                                             //
+    // Manage the endcap elements:                                                 //
+    void manageEndcapElement(TRT_EndcapElement *endcap);                           //
+    //                                                                             //
+    //-----------------------------------------------------------------------------//
+    
+    //-----------------------------------------------------------------------------//
+    //                                                                             //
+    //  Transform of straw relative to module.  Stored as a tranformation field    //
+    //  to make this compact.  Note , GeoXF::Function * is a pointer to a so-      //
+    //  called "TRANSFUNCTION".  Functions are delete when the manager is deleted. //
+    //                                                                             //
+    void setBarrelTransformField(size_t i, const GeoXF::Function *field);          //
+    const GeoXF::Function *barrelTransformField(size_t i) const;                   //
+    void setEndcapTransformField(size_t i, const GeoXF::Function *field);          //
+    const GeoXF::Function *endcapTransformField(size_t i) const;                   //
+    //                                                                             //
+    //-----------------------------------------------------------------------------//
+
+    // Alignment stuff
+    // DEPRECATED - kept for compatibilty with Lisbon CondDB
+    void addKey(const std::string & key, int level);
+    // DEPRECATED use addChannel
+    void addKey(const std::string & key, int level, FrameType frame);
+
+
+
+    /** Add alignable transforms: GeoModel/CLHEP based */
+    void addAlignableTransform (int level,
+				const Identifier &id, 
+				GeoAlignableTransform *transform,
+				const GeoVFullPhysVol * child = 0,
+				const GeoVFullPhysVol * frameVol = 0);
+				
+    /** Add alignable transforms: GeoModel/CLHEP based */
+    void addAlignableTransform (int level,
+				const Identifier &id, 
+				GeoAlignableTransform *transform,
+				const GeoVPhysVol * child = 0,
+				const GeoVPhysVol * frameVol = 0);
+
+    /** Set alignable transforms: Amg based */
+    virtual bool setAlignableTransformDelta(int level, 
+				                            const Identifier & id, 
+				                            const Amg::Transform3D & delta,
+				                            FrameType frame) const;
+
+    /** Set alignable transforms: Amg based */
+    bool setAlignableTransformAnyFrameDelta(ExtendedAlignableTransform * extXF, 
+					                        const Amg::Transform3D & delta,
+					                        FrameType frame) const;
+
+
+    /** Invalidate cache for all detector elements */
+    virtual void invalidateAll() const;
+   
+    /** Update all caches. */
+    virtual void updateAll() const;
+
+
+    /** Check identifier is for this detector */
+    virtual bool identifierBelongs(const Identifier & id) const;
+    
+    /** Call back for alignment updates, DEPRECATED. Now registered in tool. */
+    StatusCode alignmentCallback( IOVSVC_CALLBACK_ARGS );
+
+ 
+ private:  
+  
+
+    // Illegal operations:---------------------------------------------------------//
+    //                                                                             //
+    const TRT_DetectorManager & operator=(const TRT_DetectorManager &right);       //
+    TRT_DetectorManager(const TRT_DetectorManager &right);                         //
+    //                                                                             //
+    //-----------------------------------------------------------------------------//
+    
+    
+    // Private member data:--------------------------------------------------------//
+    std::vector<PVLink> volume;                                                    //
+    //                                                                             //
+    enum {NMODMAX=3};                                                              //
+    enum {NWHEELMAX=18};                                                           //
+    enum {NPHIMAX=32};                                                             //
+    enum {NSTRAWLAYMAXBR=30};                                                      //
+    enum {NSTRAWLAYMAXEC=16};                                                      //
+    //                                                                             //
+    TRT_BarrelElement *barrelArray[2][NMODMAX][NPHIMAX][NSTRAWLAYMAXBR];           //
+    TRT_EndcapElement *endcapArray[2][NWHEELMAX][NSTRAWLAYMAXEC][NPHIMAX];         //
+    TRT_DetElementCollection m_elements;                                           //     
+    //                                                                             //
+    TRT_Numerology  *_numerology;                                                  //
+    const TRT_ID    *m_idHelper;                                                   //
+    bool             _ownsIdHelper;                                                //
+    const GeoXF::Function *_barrelXF[3];                                           //
+    const GeoXF::Function *_endcapXF[3];                                           //
+    //                                                                             //
+    ActiveGasType m_gasType;                                                       //
+    unsigned int m_digvers;                                                        //
+    std::string m_digversname;                                                     //
+
+    TRT_Conditions * m_conditions;
+
+    // Alignment stuff
+    typedef std::map<Identifier, ExtendedAlignableTransform *> AlignableTransformMap;
+    std::vector< AlignableTransformMap > m_alignableTransforms;
+
+    // here temporarily
+    virtual const TRT_ID *getIdHelper() const;                                             //
+    virtual bool processSpecialAlignment(const std::string & key) const;
+
+    //-----------------------------------------------------------------------------//
+  };
+}
+#ifndef GAUDI_NEUTRAL
+#include "CLIDSvc/CLASS_DEF.h" 
+CLASS_DEF(InDetDD::TRT_DetectorManager, 10907524, 1)
+#endif
+#endif
+  
+  
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapCode.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapCode.h
new file mode 100755
index 0000000000000000000000000000000000000000..1572ca3b4f99f242335be864f81a419e673bf41f
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapCode.h
@@ -0,0 +1,141 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDetectorElementCollection.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRT_EndcapCode_h
+#define TRT_EndcapCode_h 1
+
+#include <iostream>
+
+// Include the string class header
+#include <string>
+
+namespace InDetDD {
+
+  /** @class TRT_EndcapCode 
+  
+        bit definitions to decode TRT straws in endcap
+  */
+
+  class TRT_EndcapCode 
+    {
+    public:
+      
+      
+      TRT_EndcapCode();
+      TRT_EndcapCode( unsigned int  isPositive, 
+		      unsigned int wheelIndex, 
+		      unsigned int strawLayerIndex, 
+		      unsigned int phiIndex); 
+      
+      TRT_EndcapCode( const TRT_EndcapCode & right );
+      ~TRT_EndcapCode();
+      
+      const TRT_EndcapCode & operator=( const TRT_EndcapCode & right );
+      
+      bool operator < (const TRT_EndcapCode & right) const;
+      bool operator > (const TRT_EndcapCode & right) const;
+      bool operator== (const TRT_EndcapCode & right) const;
+      bool operator!= (const TRT_EndcapCode & right) const;
+      
+      unsigned int isPosZ()              const;
+      unsigned int getWheelIndex()       const;
+      unsigned int getStrawLayerIndex()  const;
+      unsigned int getPhiIndex()         const;
+      unsigned int getKey()              const;
+      std::string getName()              const;
+      
+    private:  
+      
+      
+      // Define key as a bit string:
+      //   bit 0    Z (negative=0 or positive=1)
+      //   bit 1-2  Wheel Index (0-2)
+      //   bit 3-7  StrawLayer Index
+      //   bit 8-12 Phi position (0-31)      
+      
+      unsigned short int _key;
+      
+      static const int Z_MASK;
+      static const int WHEEL_MASK;
+      static const int STRAWLAYER_MASK;
+      static const int PHIPOS_MASK;
+      
+      static const int Z_SHIFT;
+      static const int WHEEL_SHIFT;
+      static const int STRAWLAYER_SHIFT;
+      static const int PHIPOS_SHIFT;      
+
+    };
+  
+  
+  
+  inline unsigned int TRT_EndcapCode::isPosZ() const {
+    unsigned int ret = _key;
+    return (ret >> Z_SHIFT) & Z_MASK;
+  }
+  
+  inline unsigned int TRT_EndcapCode::getWheelIndex() const{
+    unsigned int ret = _key;
+    return (ret >> WHEEL_SHIFT) & WHEEL_MASK;
+  }
+  
+  
+  inline unsigned int TRT_EndcapCode::getStrawLayerIndex() const {
+    unsigned int ret = _key;
+    return (ret >> STRAWLAYER_SHIFT) & STRAWLAYER_MASK;
+  }
+
+  inline unsigned int TRT_EndcapCode::getPhiIndex() const {
+    unsigned int ret = _key;
+    return (ret >> PHIPOS_SHIFT) & PHIPOS_MASK;
+  }
+  
+  inline unsigned int TRT_EndcapCode::getKey() const {
+    return _key;
+  }
+  
+  
+  inline bool TRT_EndcapCode::operator==(const TRT_EndcapCode &right) const
+    {
+      return (getKey() == right.getKey());
+    }
+  
+  inline bool TRT_EndcapCode::operator!=(const TRT_EndcapCode &right) const
+    {
+      return (getKey() != right.getKey());
+    }
+  
+  inline bool TRT_EndcapCode::operator<(const TRT_EndcapCode &right) const
+    {
+      return (getKey() < right.getKey());
+    }
+  
+  inline bool TRT_EndcapCode::operator>(const TRT_EndcapCode &right) const
+    {
+      return (getKey() > right.getKey());
+    }
+} // End InDetDD namespace
+
+  
+inline std::ostream & operator << (std::ostream & os, const InDetDD::TRT_EndcapCode & code) {
+  // Plus/minus 
+  if (code.isPosZ()) os << '+';
+  else os << '-';
+  // Wheel
+  unsigned int wheel = code.getWheelIndex();
+  os << wheel << "/";
+  // StrawLayer:  
+  os << code.getStrawLayerIndex()<< "/";
+  // Phi
+  os << code.getPhiIndex();
+  return os;
+}
+
+#endif
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapDescriptor.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapDescriptor.h
new file mode 100755
index 0000000000000000000000000000000000000000..10c5ccf1a514cc1935e61f75a39818b1975f75c6
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapDescriptor.h
@@ -0,0 +1,124 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDetectorElementCollection.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRT_EndcapDescriptor_h
+#define TRT_EndcapDescriptor_h 1
+#include "GeoModelKernel/RCBase.h"
+#include "GeoModelKernel/GeoXF.h"
+
+namespace Trk{
+  class CylinderBounds;
+  class SurfaceBounds;
+}
+
+namespace InDetDD {
+
+  /** class TRT_EndcapDescriptor
+      
+       Helper class to access GeoModel infromation and calculation for straws 
+       */
+
+  class TRT_EndcapDescriptor : public RCBase 
+    
+    {
+      
+    public:
+      
+      /** Constructor */
+      TRT_EndcapDescriptor();
+      
+      /** Sets the transform field for straws and offset.  We do not own the function: */
+      void setStrawTransformField(const GeoXF::Function *xf, size_t offsetInto);
+
+      /** The number of straws in a module: */
+      unsigned int &nStraws();
+      inline const unsigned int &nStraws() const;
+      
+      /** The straw pitch (angular!!) */
+      double &strawPitch();
+      inline const double &strawPitch() const;
+      
+      /** The starting phi (angular!!) */
+      double &startPhi();
+      inline const double &startPhi() const;
+      
+      //** The straw length: */
+      double &strawLength();
+      inline const double &strawLength() const;
+      
+      /** The inner radius: */
+      double &innerRadius();
+      inline const double &innerRadius() const;
+      
+      /** Get inner tube radius of the straw */
+      inline double innerTubeRadius() const;
+      
+      /**  Get the tranformation field, which we do not own: */
+      inline const GeoXF::Function *getStrawTransform() const;
+      
+      /** Get the offset into the transformation field: */
+      inline size_t getStrawTransformOffset() const;
+      
+      /** Get Bounds */
+      const Trk::SurfaceBounds & strawBounds() const;
+
+    protected:
+      
+      
+      virtual ~TRT_EndcapDescriptor();
+      
+      
+    private:
+      
+      // Illegal to copy:
+      TRT_EndcapDescriptor(const TRT_EndcapDescriptor &right);
+      
+      
+      // Illegal to assign:
+      const TRT_EndcapDescriptor & operator=(const TRT_EndcapDescriptor &right);
+      
+      
+      // Number of straws in the module.
+      unsigned int _nStraws;
+      
+      // (Angular) straw pitch
+      double _strawPitch;
+      
+      // Starting phi:
+      double _startPhi;
+      
+      // Straw length:
+      double _strawLength;
+      
+      // Inner radius of straw:
+      double _innerRadius;
+
+      // Inner tube radius of straw.
+      double m_innerTubeRadius;
+      
+      // The straw transformation field:
+      const GeoXF::Function *_f;
+
+      // And offset:
+      size_t                 _o;
+      
+      // Bounds
+      mutable Trk::CylinderBounds * m_bounds;
+
+
+    };
+}
+
+
+#include "TRT_EndcapDescriptor.icc"
+
+
+
+#endif
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapDescriptor.icc b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapDescriptor.icc
new file mode 100755
index 0000000000000000000000000000000000000000..77d6879732090dde08e8ff84c91e38f9b968ffb4
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapDescriptor.icc
@@ -0,0 +1,45 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+namespace InDetDD {
+
+//	The number of straws in a module:
+inline const unsigned int &TRT_EndcapDescriptor::nStraws() const {
+  return _nStraws;
+}
+
+inline const double &TRT_EndcapDescriptor::strawPitch() const {
+  return _strawPitch;
+}
+
+inline const double &TRT_EndcapDescriptor::startPhi() const {
+  return _startPhi;
+}
+
+
+inline const double &TRT_EndcapDescriptor::strawLength() const {
+  return _strawLength;
+}
+
+inline double TRT_EndcapDescriptor::innerTubeRadius() const
+{
+  return m_innerTubeRadius;
+}
+
+inline const double &TRT_EndcapDescriptor::innerRadius() const {
+  return _innerRadius;
+}
+
+inline const GeoXF::Function * TRT_EndcapDescriptor::getStrawTransform() const {
+  return _f;
+}
+
+inline size_t TRT_EndcapDescriptor::getStrawTransformOffset() const {
+  return _o;
+}
+
+
+
+}
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapElement.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapElement.h
new file mode 100755
index 0000000000000000000000000000000000000000..f647e81bb47e97ce2855bfa752eafaf342fc0e32
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapElement.h
@@ -0,0 +1,138 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TRT_EndcapElement.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef TRT_EndcapElement_h
+#define TRT_EndcapElement_h 1
+#include "InDetReadoutGeometry/TRT_EndcapCode.h"
+#include "InDetReadoutGeometry/TRT_BaseElement.h"
+#include "InDetReadoutGeometry/TRT_EndcapDescriptor.h"
+
+class TRT_ID;
+
+namespace Trk{
+  class SurfaceBounds;
+}
+
+namespace InDetDD {
+
+  class TRT_EndcapConditions;
+
+  /** @class TRT_EndcapElement 
+  
+      Extended class of a TRT_BaseElement to describe a readout elment in the endcap.
+      It secifies the strawTransfrom methods by getting the information from GeoModel
+      
+      The readout element in the EC is a wheel with straws radially placed on it.
+      
+      The number of straws described by this readout element can be 
+      retrieved by nStraws() 
+      
+      @author: Grant Gorfine
+      - modified & maintained: Nick Styles, Andreas Salzburger
+      
+      */
+  
+  
+  class TRT_EndcapElement : public TRT_BaseElement   {
+    
+    public:
+      /** Constructor */
+      TRT_EndcapElement(const GeoVFullPhysVol *volume, 
+      	                const TRT_EndcapDescriptor *descriptor, 
+      	                bool isPositive, 
+      	                unsigned int wheelIndex, 
+      	                unsigned int strawLayIndex,
+      	                unsigned int phiIndex,
+      	                const TRT_ID * idHelper,
+      		            const TRT_Conditions * conditions);
+    
+      /** Destructor: */
+      virtual ~TRT_EndcapElement();
+      
+      /** Type information: */
+      virtual TRT_BaseElement::Type type() const {return TRT_BaseElement::ENDCAP;} 
+    
+      /** Default Local -> global transform of the straw (ie before alignment corrections) */
+      virtual HepGeom::Transform3D defStrawTransform(int straw) const;
+    
+      /** Number of straws in the element */
+      virtual unsigned int nStraws() const;
+    
+      /** Active straw length */
+      virtual const double & strawLength() const;
+    
+      /** StrawDirection. +1 if axis is in same direction as local coordinate, -1 otherwise. */
+      virtual int strawDirection() const;
+    
+      /** Returns a pointer to conditions data.  This includes
+         information on dead and noisy wires, as well as wire
+         sags. */
+      const TRT_EndcapConditions * getConditionsData() const;
+      
+      /** Returns a pointer to a descriptor, giving common
+          information on module construction */
+      const TRT_EndcapDescriptor * getDescriptor() const;
+      
+      /** Next in Z: */
+      const TRT_EndcapElement * nextInZ() const;
+      
+      /** Prev in Z: */
+      const TRT_EndcapElement * previousInZ() const;
+      
+      /** Set Next in Z */
+      void setNextInZ(const TRT_EndcapElement *element);
+      
+      /** Set Previous in Z */
+      void setPreviousInZ(const TRT_EndcapElement *element);
+      
+      /** Doomed (??) */
+      const TRT_EndcapCode & getCode() const;
+      
+      // Surface bounds
+      virtual const Trk::SurfaceBounds & strawBounds() const;
+    
+    
+    protected:
+      /** These transforms are effectively to the local coord
+        system of a straw derived from GeoModel -> hence CLHEP */
+      HepGeom::Transform3D calculateStrawTransform(int straw) const;
+      HepGeom::Transform3D calculateLocalStrawTransform(int straw) const;
+    
+      /** return the surface of the element */ 
+      const Trk::Surface & elementSurface() const;
+      
+      /** create the cache for the element */
+      void createSurfaceCache() const;
+      
+      /** create the cache for the straw of identifier id */
+      void createSurfaceCache(Identifier id) const;
+    
+    private:
+      
+      // Illegal Operations:
+      TRT_EndcapElement(const TRT_EndcapElement &right);
+      const TRT_EndcapElement & operator=(const TRT_EndcapElement &right);
+      
+      // Private Member Data:
+      TRT_EndcapCode              _code;
+      const TRT_EndcapDescriptor *_descriptor;
+      const TRT_EndcapElement    *_nextInZ;
+      const TRT_EndcapElement    *_previousInZ;
+    
+      mutable Trk::Surface       * m_surface;
+    
+  };
+  
+}
+
+#include "TRT_EndcapElement.icc"  
+#endif
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapElement.icc b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapElement.icc
new file mode 100755
index 0000000000000000000000000000000000000000..d94b0eebb694b2da0298ee6a1aab06b29dc5cd81
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_EndcapElement.icc
@@ -0,0 +1,20 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+namespace InDetDD {
+  inline const TRT_EndcapElement * TRT_EndcapElement::nextInZ() const
+    {
+      return _nextInZ;
+    }
+  
+  inline const TRT_EndcapElement * TRT_EndcapElement::previousInZ() const
+    {
+      return _previousInZ;
+    }
+  
+  inline const TRT_EndcapCode & TRT_EndcapElement::getCode() const
+    {
+      return _code;
+    }
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_Numerology.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_Numerology.h
new file mode 100755
index 0000000000000000000000000000000000000000..39d5b9cb5cbf1b2cbdbaf495b7f4e8e958430699
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_Numerology.h
@@ -0,0 +1,62 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// TRT_Numerology.h
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+
+#ifndef _TRTNUMEROLOGY_H_
+#define _TRTNUMEROLOGY_H_
+
+namespace InDetDD {
+  
+  /** @class TRT_Numerology
+
+      Helper class to organize the straw elements on 
+      TRT readout elements.
+
+    */
+  class TRT_Numerology {
+  
+    public:
+    
+      // Constructor:
+      TRT_Numerology();
+    
+      // Destructor:
+      ~TRT_Numerology();
+    
+      // Modifiers:
+      void setNBarrelLayers(unsigned int module, unsigned int nLayers);
+      void setNEndcapLayers(unsigned int wheel,  unsigned int nLayers);
+    
+      void setNBarrelRings (unsigned int ring );
+      void setNBarrelPhi   (unsigned int phi  );
+      void setNEndcapWheels(unsigned int wheel);
+      void setNEndcapPhi   (unsigned int phi  );
+
+      // Accessors:
+      inline unsigned int getNBarrelLayers(unsigned int iMod  ) const; 
+      inline unsigned int getNEndcapLayers(unsigned int iWheel) const; 
+
+      inline unsigned int getNBarrelRings () const;
+      inline unsigned int getNBarrelPhi   () const;
+      inline unsigned int getNEndcapWheels() const;
+      inline unsigned int getNEndcapPhi   () const;
+    
+    private:
+    
+      unsigned int _nlayerBarrel[3];
+      unsigned int _nlayerEndcap[18];
+
+      unsigned int _nringBarrel;
+      unsigned int _nphiBarrel;
+      unsigned int _nwheelEndcap;
+      unsigned int _nphiEndcap;
+  };
+}
+#include "TRT_Numerology.icc"
+#endif
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_Numerology.icc b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_Numerology.icc
new file mode 100755
index 0000000000000000000000000000000000000000..877ddaa504a9ab4586008aa91e00ab778eebdbd5
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/TRT_Numerology.icc
@@ -0,0 +1,30 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+namespace InDetDD {
+inline unsigned int TRT_Numerology::getNBarrelLayers (unsigned int iMod) const {
+  return _nlayerBarrel[iMod];
+}
+
+
+inline unsigned int TRT_Numerology::getNEndcapLayers (unsigned int iWheel) const {
+  return _nlayerEndcap[iWheel];
+}
+
+inline unsigned int TRT_Numerology::getNBarrelRings() const {
+  return _nringBarrel;
+}
+
+inline unsigned int TRT_Numerology::getNBarrelPhi() const {
+  return _nphiBarrel;
+}
+
+inline unsigned int TRT_Numerology::getNEndcapWheels() const {
+  return _nwheelEndcap;
+}
+
+inline unsigned int TRT_Numerology::getNEndcapPhi() const {
+  return _nphiEndcap;
+}
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/Version.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/Version.h
new file mode 100755
index 0000000000000000000000000000000000000000..1493133da4bbaa9ec07ef34b4494c1bce7b4c209
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/InDetReadoutGeometry/Version.h
@@ -0,0 +1,91 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+////////////////////////////////////////////////////////////
+// Version.h
+////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+////////////////////////////////////////////////////////////
+
+#ifndef INDETREADOUTGEOMETRY_VERSION 
+#define INDETREADOUTGEOMETRY_VERSION 
+
+#include <string>
+
+namespace InDetDD {
+
+  /** @class Version
+
+    Class to hold version information consisting of tag, name layout and description as strings,
+    such as their integer regpresentation in the major-minor-tag scheme 
+    */
+
+  class Version {
+
+    public:
+
+      /** Constructor.  */
+      Version(const std::string & tag, 
+	  const std::string & name, 
+	  const std::string & layout, 
+	  const std::string & description, 
+	  int major,
+	  int minor,
+	  int patch);
+
+     /** Constructor. DEPRECATED */
+      Version(const std::string & name, 
+	  const std::string & layout, 
+	  const std::string & description, 
+	  int major,
+	  int minor,
+	  int patch);
+
+      /** Empty Constructor  */
+      Version();
+
+      /** Version tag */
+      const std::string & tag() const;
+
+      /** Version label */
+      const std::string & name() const;
+  
+      /** Layout (eg Initial, Final, TestBeam) */
+      const std::string & layout() const;
+
+      /** Description or comment. */
+      const std::string & description() const;
+
+      /** Major version number */
+      int majorNum() const;
+  
+      /** Minor version number */
+      int minorNum() const;
+
+      /** Patch version number  */
+      int patchNum() const;
+
+      /** Print out version number (eg. 2.00.00) */
+      std::string versionNumber() const;
+  
+      /** Full Description 
+          For example,
+          Version: SCT-DC1-00, Name: DC1, Layout: Final, Code Version: 2.00.00, Description: DC1 Geometry */
+      std::string fullDescription() const;
+
+  
+   private:
+ 
+      std::string m_tag;
+      std::string m_name;
+      std::string m_layout;
+      std::string m_description;
+      int m_major;
+      int m_minor;
+      int m_patch;
+  };
+
+} //  namespace  InDetDD
+
+#endif // INDETREADOUTGEOMETRY_VERSION 
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/README b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/README
new file mode 100755
index 0000000000000000000000000000000000000000..89969ca86c7aa930dcb9f03c0c2b925173969964
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/README
@@ -0,0 +1,10 @@
+Package:      offline/InnerDetector/InDetDetDescr/InDetReadoutGeometry  
+
+Responsible:  Grant Gorfine <Grant.Gorfine@nikhef.nl>
+
+Description:  Detector description managers and readout elements for Pixel
+              SCT and TRT.
+
+Dependencies: Identifier, InDetIdentifier, GeoModelKernel, IdDictDetDescr, StoreGate
+
+Last modified: October 1, 2003 by Grant Gorfine
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/cmt/requirements b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/cmt/requirements
new file mode 100755
index 0000000000000000000000000000000000000000..27f823090cae11d5f03a40342a5ef0d26ba7f93b
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/cmt/requirements
@@ -0,0 +1,35 @@
+package InDetReadoutGeometry
+
+manager Grant Gorfine <Grant.Gorfine>
+
+private
+
+use DetDescrConditions DetDescrConditions-* DetectorDescription/DetDescrCond
+use IdDictDetDescr     IdDictDetDescr-*     DetectorDescription
+use TRT_ConditionsData TRT_ConditionsData-* InnerDetector/InDetConditions
+use StoreGate	       StoreGate-*          Control
+
+public
+
+use AtlasPolicy	       AtlasPolicy-*
+use AtlasCLHEP	       AtlasCLHEP-*         External 
+use GaudiInterface     GaudiInterface-*     External
+use AthenaKernel       AthenaKernel-*       Control
+use CLIDSvc	           CLIDSvc-*	        Control
+use Identifier	       Identifier-*         DetectorDescription 
+use AtlasDetDescr      AtlasDetDescr-*      DetectorDescription
+use GeoModelKernel     GeoModelKernel-*     DetectorDescription/GeoModel 
+use InDetIdentifier    InDetIdentifier-*    InnerDetector/InDetDetDescr
+use InDetCondServices  InDetCondServices-*  InnerDetector/InDetConditions
+use TrkDetElementBase  TrkDetElementBase-*  Tracking/TrkDetDescr 
+use TrkSurfaces        TrkSurfaces-*        Tracking/TrkDetDescr
+use TrkEventPrimitives TrkEventPrimitives-* Tracking/TrkEvent 
+use GeoPrimitives      GeoPrimitives-*      DetectorDescription
+
+apply_pattern default_installed_library
+
+private
+macro DOXYGEN_IMAGE_PATH "../doc/images"
+
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/doc/images/pixeldiodematrix.gif b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/doc/images/pixeldiodematrix.gif
new file mode 100644
index 0000000000000000000000000000000000000000..4beda4026c20db8c7f1eb22931a132d2bfbf844d
Binary files /dev/null and b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/doc/images/pixeldiodematrix.gif differ
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/doc/mainpage.h b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/doc/mainpage.h
new file mode 100755
index 0000000000000000000000000000000000000000..170f513437a985bc4a134ff2040203c59de1612f
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/doc/mainpage.h
@@ -0,0 +1,73 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+
+@mainpage InDetReadoutGeometry Package
+
+@authors Grant Gorfine, Joe Boudreau, Thomas Kittlemann, 
+         Davide Costanzo, David Calvet, Alessandro Fornaini
+
+@section InDetReadoutGeometryIntro Introduction 
+
+This package contains the readout classes for
+the inner detector. These are mainly used by digitization and
+reconstruction. 
+
+
+- Managers:
+  The Detector managers contain methods to access the Identifier helpers and detector elements.
+
+
+- Detector Elements:
+The detector element is the object where geometrical information of the readout elements is obtained: 
+  -  Pixel: The silicon sensor in a pixel module. 
+  -  SCT: One side of the module. (One or two silicon wafers wire bonded together)
+  -  TRT: A straw layer (contains several straws).
+
+- Design and Descriptor Classes:
+As well as the detector element there are design and descriptor classes which contain information common to several elements.
+
+
+@section InDetReadoutGeometryClassOverview  Class Overview
+
+Described here are just the classes that clients will 
+normally use.
+
+- Managers:
+  - InDetDD::SiDetectorManager: Base class for Pixel and SCT managers.
+  - InDetDD::PixelDetectorManager: The Pixel detector manager.
+  - InDetDD::SCT_DetectorManager: The SCT detector manager.
+  - InDetDD::TRT_DetectorManager: The TRT detector manager.
+
+- Detector Elements, Design and Descriptor Classes:
+  - InDetDD::SiDetectorElement: Pixel and SCT share a common detector element class. This class contains most of the methods needed by reconstruction clients.
+  - InDetDD::SiDetectorDesign: Base class for design.  
+  - InDetDD::PixelModuleDesign: 
+  - InDetDD::SCT_ModuleSideDesign:
+  - InDetDD::SCT_BarrelModuleSideDesign:
+  - InDetDD::SCT_ForwardModuleSideDesign:
+  - InDetDD::TRT_BaseElement: 
+  - InDetDD::TRT_BarrelElement:
+  - InDetDD::TRT_EndcapElement:
+  - InDetDD::TRT_BarrelDescriptor:
+  - InDetDD::TRT_EndcapDescriptor:
+
+
+- Other: 
+  - InDetDD::SiCellId: Strip number for SCT or phi_index, eta_index for pixel.
+  - InDetDD::Version: Version information
+  - InDetDD::TRT_Numerology: TRT numerology 
+  - InDetDD::SiNumerology: Pixel and SCT numerology
+
+@section InDetReadoutGeometryUsage Usage Notes
+The managers are retrieved from storegate. Their names are Pixel, SCT and TRT.
+From the manager, one can get the id helpers and access the detector elements using various methods. 
+
+@section InDetReadoutGeometryReq Requirements
+
+
+@include requirements
+
+*/
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/doc/pixeldiodematrix.fig b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/doc/pixeldiodematrix.fig
new file mode 100644
index 0000000000000000000000000000000000000000..7d59c0f42b235875e8830eff8604883373cbdc10
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/doc/pixeldiodematrix.fig
@@ -0,0 +1,104 @@
+#FIG 3.2
+Landscape
+Center
+Metric
+Letter  
+100.00
+Single
+-2
+1200 2
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2
+	 2475 450 2475 5130
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2
+	 2565 450 2565 5130
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2
+	 2385 450 2385 5130
+2 2 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 5
+	 630 450 2655 450 2655 5130 630 5130 630 450
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2
+	 810 450 810 5130
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2
+	 900 450 900 5130
+2 1 0 2 0 7 50 -1 -1 0.000 0 0 7 0 0 2
+	 720 450 720 5130
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 3420 1125 3510 1125
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 3420 1800 3510 1800
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 3420 2475 3510 2475
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 3420 3150 3510 3150
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 3420 3825 3510 3825
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 3420 4500 3510 4500
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 3420 5175 3510 5175
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 4545 5625 4680 5625
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 4545 5175 4680 5175
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 7 0 0 2
+	 4545 4725 4680 4725
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 4545 1125 4680 1125
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 4545 1575 4680 1575
+2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2
+	 4545 2025 4680 2025
+2 1 1 1 0 7 50 -1 -1 4.000 0 0 7 0 0 2
+	 2700 495 3375 450
+2 1 1 1 0 7 50 -1 -1 4.000 0 0 7 0 0 2
+	 3555 495 4500 450
+2 1 1 1 0 7 50 -1 -1 4.000 0 0 7 0 0 2
+	 3555 1080 4455 6300
+2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 5940 1035 4725 765
+2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 5895 2745 4725 1350
+2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 5850 2700 4770 1800
+2 1 1 1 0 7 50 -1 -1 4.000 0 0 -1 1 0 2
+	1 1 1.00 60.00 120.00
+	 5895 1080 4725 5985
+2 1 1 1 0 11 50 -1 20 4.000 0 0 7 0 0 2
+	 2700 5085 3375 5850
+2 2 0 1 0 23 50 -1 20 0.000 0 0 -1 0 0 5
+	 4545 1125 4680 1125 4680 1575 4545 1575 4545 1125
+2 2 0 1 0 23 50 -1 20 0.000 0 0 -1 0 0 5
+	 4545 1575 4680 1575 4680 2025 4545 2025 4545 1575
+2 2 0 1 0 23 50 -1 20 0.000 0 0 -1 0 0 5
+	 4545 4725 4680 4725 4680 5175 4545 5175 4545 4725
+2 2 0 1 0 23 50 -1 20 0.000 0 0 -1 0 0 5
+	 4545 5175 4680 5175 4680 5625 4545 5625 4545 5175
+2 2 0 1 0 12 50 -1 20 0.000 0 0 -1 0 0 5
+	 4545 450 4680 450 4680 1125 4545 1125 4545 450
+2 2 0 1 0 12 50 -1 20 0.000 0 0 -1 0 0 5
+	 4545 5625 4680 5625 4680 6300 4545 6300 4545 5625
+2 2 0 2 11 7 48 -1 -1 0.000 0 0 7 0 0 5
+	 4545 450 4680 450 4680 6300 4545 6300 4545 450
+2 2 0 2 4 11 52 -1 20 0.000 0 0 7 0 0 5
+	 3420 450 3510 450 3510 5850 3420 5850 3420 450
+2 2 0 2 0 12 50 -1 20 0.000 0 0 7 0 0 5
+	 5985 450 6075 450 6075 1755 5985 1755 5985 450
+2 2 0 2 0 23 50 -1 20 0.000 0 0 7 0 0 5
+	 5985 2295 6075 2295 6075 3150 5985 3150 5985 2295
+2 2 0 1 0 30 52 -1 20 0.000 0 0 -1 0 0 5
+	 2385 450 2655 450 2655 5130 2385 5130 2385 450
+2 2 0 1 0 30 52 -1 20 0.000 0 0 -1 0 0 5
+	 630 450 900 450 900 5130 630 5130 630 450
+4 0 0 50 -1 0 42 0.0000 4 60 360 1440 2295 ...\001
+4 0 0 50 -1 16 12 0.0000 4 135 750 1260 180 fullMatrix\001
+4 0 0 50 -1 16 12 0.0000 4 180 1245 4410 225 singleChipRow\001
+4 0 0 50 -1 16 12 0.0000 4 180 855 3150 225 singleRow\001
+4 0 0 50 -1 0 42 1.5708 4 60 360 4635 3555 ...\001
+4 0 0 50 -1 16 12 0.0000 4 135 195 3600 900 x8\001
+4 0 0 50 -1 16 12 0.0000 4 135 405 2745 2250 x328\001
+4 0 0 50 -1 16 12 0.0000 4 135 300 4815 2340 x16\001
+4 0 0 50 -1 16 16 0.0000 4 180 1305 5580 5310 Not to scale\001
+4 0 0 50 -1 16 12 0.0000 4 180 585 6210 1080 bigCell\001
+4 0 0 50 -1 16 12 0.0000 4 135 885 6165 2700 normalCell\001
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/InDetDetectorManager.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/InDetDetectorManager.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..cd74b3ebd1e121957f6eaafdd71c2fb206a7e7b6
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/InDetDetectorManager.cxx
@@ -0,0 +1,279 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "InDetReadoutGeometry/InDetDetectorManager.h"
+
+#include "StoreGate/StoreGateSvc.h"
+#include "DetDescrConditions/AlignableTransformContainer.h"
+#include "DetDescrConditions/AlignableTransform.h"
+#include "AtlasDetDescr/AtlasDetectorID.h"
+#include "GeoPrimitives/CLHEPtoEigenConverter.h" 
+
+namespace InDetDD 
+{
+
+    InDetDetectorManager::InDetDetectorManager(StoreGateSvc * detStore, const std::string & name)
+        : m_detStore(detStore), 
+        m_msg(name+"DetectorManager"), 
+        m_suppressWarnings(false)
+    {
+        setName(name);
+    }
+
+  // Destructor
+    InDetDetectorManager::~InDetDetectorManager() 
+        {}
+
+
+    const Version& InDetDetectorManager::getVersion() const
+    {
+        return m_version;
+    }
+
+    const std::string& InDetDetectorManager::getLayout() const
+    {
+        return m_version.layout();
+    }
+
+    void InDetDetectorManager::setVersion(const Version & version)
+    {
+        m_version = version;
+
+    // Since default alignments are for final layout, Pixel Rome-Initial
+    // layout will result in several (harmless) WARNING message. We suppress these.  
+    // Also the SR1 layout produce warnings due to missing parts. We suppress these also.
+        m_suppressWarnings = ( (getName() == "Pixel" && 
+            (version.tag() == "Pixel-01" || version.tag() == "Pixel-DC2-Initial-00"))
+            || version.layout() == "SR1" || version.layout() == "SR1-EndcapC");
+
+    }
+
+    void InDetDetectorManager::addChannel(const std::string & key, int level, FrameType frame)
+    {
+        if (msgLvl(MSG::DEBUG)) {
+            std::string frameStr = "other";
+            if (frame == InDetDD::global) frameStr = "global";
+            if (frame == InDetDD::local) frameStr  = "local";
+            msg(MSG::DEBUG) << "Registering alignment channel with key " << key << ", level " << level 
+                << ", with frame " << frameStr << "." <<endreq;
+        }
+        m_keys[key] = LevelInfo(level, frame); 
+    }
+
+    void InDetDetectorManager::addFolder(const std::string & key)
+    {
+        m_folders.insert(key);
+    }
+
+    void InDetDetectorManager::addSpecialFolder(const std::string & key)
+    {
+        m_specialFolders.insert(key);
+    }
+
+
+  // Return the level in the hierarchy (user defined) corresponding to the key.
+    const InDetDetectorManager::LevelInfo& InDetDetectorManager::getLevel(const std::string & key) const 
+    {
+        static LevelInfo invalidLevel;
+        std::map<std::string, LevelInfo>::const_iterator iter;
+        iter = m_keys.find(key);
+        if (iter == m_keys.end()) return invalidLevel;
+        return iter->second;
+    }
+
+
+    StatusCode InDetDetectorManager::align( IOVSVC_CALLBACK_ARGS_P(I,keys) ) const
+    {
+        (void) I; // avoid warning about unused parameter 
+
+        if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "AlignmentCallback called " << endreq;
+
+        if (!getIdHelper()) return StatusCode::SUCCESS;
+
+        bool alignmentChange = false;
+
+        // If dummy arguments
+        if (keys.empty()) {
+
+            // Regular alignments. Loop through folder keys. Normally only one.
+            for (std::set<std::string>::const_iterator iterFolders = m_folders.begin();
+            iterFolders != m_folders.end();
+            ++iterFolders) {
+                try {
+                    bool status = processAlignmentContainer(*iterFolders);
+                    alignmentChange = (alignmentChange || status);
+                }
+                catch(std::runtime_error& err) {
+                    // alignments should always exist so we return fatal if we could not process the alignment for this key
+                    msg(MSG::FATAL) << err.what() << endreq;
+                    return StatusCode::FAILURE;
+                }
+            }  
+            // Detector specific aligments
+            for (std::set<std::string>::const_iterator iterFolders = m_specialFolders.begin();
+            iterFolders != m_specialFolders.end();
+            ++iterFolders) {
+                try {
+                    bool status = processSpecialAlignment(*iterFolders);
+                    alignmentChange = (alignmentChange || status);
+                } catch(std::runtime_error& err) {
+                    // keys are empty when running simualtion. It is normal for detector specific aligments not to exist.
+                    if (msgLvl(MSG::INFO)) msg(MSG::INFO) << err.what() << endreq;
+                    // We continue as detector specific aligments don't always exist.
+                }
+            }
+
+        } else {
+            // Loop over all the keys.
+            for (std::list<std::string>::const_iterator itr=keys.begin(); itr!=keys.end(); ++itr) {
+
+                const std::string & key = *itr;
+
+                if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << " Processing call back key  " << key << endreq;      
+
+                    if ( m_folders.find(key) != m_folders.end() ) { 
+
+                    try {
+                        // Regular alignemnts
+                        bool status = processAlignmentContainer(key);
+                        alignmentChange = (alignmentChange || status);
+                    } catch(std::runtime_error& err) {
+                        // alignments should always exist so we return fatal if we could not process the alignment for this key
+                        msg(MSG::FATAL) << err.what() << endreq;
+                        return StatusCode::FAILURE;
+                    }
+
+                } else if ( m_specialFolders.find(key) !=  m_specialFolders.end() ) {
+                    try {
+                        // Detector specific alignments
+                        bool status = processSpecialAlignment(key);
+                        alignmentChange = (alignmentChange || status);
+                    } 
+                    catch(std::runtime_error& err) {
+                        // Should always exist if the folder was requested so we return fatal if we could not process the alignment for this key
+                        msg(MSG::FATAL) << err.what() << endreq;
+                        return StatusCode::FAILURE;
+                    }
+                } else {
+                    // Should not be any other keys specified in call back.
+                    msg(MSG::ERROR) << "Unrecognized key in call back." << endreq;
+                    return  StatusCode::SUCCESS;
+                }
+            }
+        }
+
+    // We invalidate all the elements if at least one alignment changed.
+        if (alignmentChange) {
+            invalidateAll();
+        }    
+
+        return StatusCode::SUCCESS;
+    }
+
+
+
+    bool InDetDetectorManager::processAlignmentContainer(const std::string & key) const
+    {
+        bool alignmentChange = false;
+
+        if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "Dealing with key as container" << endreq;
+        const AlignableTransformContainer* container;
+        if (StatusCode::SUCCESS!=m_detStore->retrieve(container, key)) {        
+            msg(MSG::ERROR) << "Cannot find AlignableTransformContainer for key " 
+                << key << " - no misalignment" << endreq;
+            // This should not occur in normal situations so we force job to abort.
+            throw std::runtime_error("Unable to apply Inner Detector alignments");
+        }
+        // Check if container is empty - this can occur if it is an invalid IOV.
+        if (container->empty()) {
+            msg(MSG::ERROR) << "AlignableTransformContainer for key " 
+                << key << " is empty. Probably due to out of range IOV" << endreq;
+            // This should not occur in normal situations so we force job to abort.
+            throw std::runtime_error("Unable to apply Inner Detector alignments.");
+        }
+        // loop over all the AlignableTransform objects in the collection
+        for (DataVector<AlignableTransform>::const_iterator pat=container->begin();
+        pat!=container->end();++pat) {
+            bool status = processKey((*pat)->tag(),*pat);
+            alignmentChange = (alignmentChange || status);
+        }
+        return alignmentChange;
+    } 
+
+    bool InDetDetectorManager::processKey(const std::string key, const AlignableTransform* transformCollection) const 
+    {  
+        bool alignmentChange = false;
+
+        // From the key determine what level in hierarchy we are dealing with.
+        // returns -1 if unrecognized.  
+        const LevelInfo & levelInfo = getLevel(key);
+        if (msgLvl(MSG::DEBUG)) {
+            if (levelInfo.isValid()) {
+                if (msgLvl(MSG::VERBOSE)) msg(MSG::VERBOSE) << "Processing channel: " << key << endreq;
+            } else {
+                msg(MSG::DEBUG) << "Channel " << key << " not registered in this manager" << endreq;
+            }
+        }
+        // return silently if unrecognised - this can happen in container mode
+        // when a single container holds transforms for both pixel and SCT
+        if (!levelInfo.isValid() ) return false;
+
+
+        //Loop over the effected nodes.
+        for (AlignableTransform::AlignTransMem_citr trans_iter = transformCollection->begin(); 
+        trans_iter != transformCollection->end(); 
+        ++trans_iter) {
+            if (msgLvl(MSG::VERBOSE)) {
+                msg(MSG::VERBOSE) << "Get alignment for identifier " 
+                    << getIdHelper()->show_to_string(trans_iter->identify())  
+                    << " at level " << levelInfo.level() << endreq;
+            }
+            // The delta in the conditions DB is not necessarily the same as what is needed in the
+            // alignable transform. At the moment we support global frame, local frame or an alternative frame
+            // The setAlignableTransformDelta method takes care of this correction - this is CLHEP <--> Amg interfaced
+            bool status = setAlignableTransformDelta(levelInfo.level(), 
+                                                     trans_iter->identify(),
+						     Amg::CLHEPTransformToEigen(trans_iter->transform()),
+                                                     levelInfo.frame());
+
+            alignmentChange = (alignmentChange || status);
+
+            if (!status) {
+                if (!identifierBelongs(trans_iter->identify())) {
+                    // Its probably OK. Eg /Indet/Align/ID contains alse pixel and sct ids.
+                    if (msgLvl(MSG::DEBUG)) {
+                        msg(MSG::DEBUG) << "Cannot set AlignableTransform for identifier."
+                            << " Probably OK if its /Indet/Align/ID folder. "  
+                            << getIdHelper()->show_to_string(trans_iter->identify())  
+                            << " at level " << levelInfo.level() << endreq;
+                    }
+                } else {
+                    if (m_suppressWarnings) {
+                        if (msgLvl(MSG::DEBUG)) {	      
+                            msg(MSG::DEBUG) << "WARNING: Cannot set AlignableTransform for identifier  " 
+                                << getIdHelper()->show_to_string(trans_iter->identify())  
+                                << " at level " << levelInfo.level() << endreq;
+                        }
+                    } else {
+                        msg(MSG::WARNING) << "Cannot set AlignableTransform for identifier  " 
+                            << getIdHelper()->show_to_string(trans_iter->identify())  
+                            << " at level " << levelInfo.level() << endreq;
+                        msg(MSG::WARNING) << "Subsequent WARNINGS will be printed at DEBUG level."  << endreq;
+                        m_suppressWarnings = true; 
+                    }
+                }
+            }  
+        }
+        return alignmentChange;
+    }
+
+  // We provide a default implementation of any detector specific alignment.
+    bool InDetDetectorManager::processSpecialAlignment(const std::string &) const
+    {
+        return false;
+    }
+
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelDetectorManager.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelDetectorManager.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..941dcef681b0d2a24a4050a65a9594a1b37d501a
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelDetectorManager.cxx
@@ -0,0 +1,306 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "InDetReadoutGeometry/PixelDetectorManager.h"
+#include "InDetIdentifier/PixelID.h"
+#include "Identifier/Identifier.h"
+#include "Identifier/IdentifierHash.h"
+#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
+#include "InDetReadoutGeometry/SiDetectorElement.h"
+#include "InDetReadoutGeometry/ExtendedAlignableTransform.h"
+#include "InDetReadoutGeometry/PixelModuleDesign.h"
+#include "StoreGate/StoreGateSvc.h"
+
+namespace InDetDD {
+
+    const int FIRST_HIGHER_LEVEL = 1;
+
+
+    PixelDetectorManager::PixelDetectorManager(StoreGateSvc* detStore) 
+        : SiDetectorManager(detStore, "Pixel"),
+        m_idHelper(0)
+    {
+
+        //  
+        // Initialized the Identifier helper.
+        //
+
+        StatusCode sc = detStore->retrieve(m_idHelper,"PixelID");
+        if (sc.isFailure() ) {
+            msg(MSG::ERROR) << "Could not retrieve Pixel id helper" << endreq;
+        }
+
+        // Initialize the collections.
+        if (m_idHelper) {
+            m_elementCollection.resize(m_idHelper->wafer_hash_max());
+            m_alignableTransforms.resize(m_idHelper->wafer_hash_max());
+        } 
+    }
+
+
+    PixelDetectorManager::~PixelDetectorManager()
+    {
+        // Clean up
+        SiDetectorElementCollection::iterator iter;
+        for (iter = m_elementCollection.begin(); iter != m_elementCollection.end(); ++iter){
+            delete *iter;
+        }
+
+        for (size_t i=0; i < m_volume.size(); i++) {
+            m_volume[i]->unref();
+        }
+
+        for (size_t j=0; j < m_higherAlignableTransforms.size(); j++){
+            AlignableTransformMap::iterator iterMap;    
+            for (iterMap = m_higherAlignableTransforms[j].begin(); 
+            iterMap != m_higherAlignableTransforms[j].end();
+            ++iterMap) {
+                delete iterMap->second;
+            }
+        }
+
+        for (size_t k=0; k < m_alignableTransforms.size(); k++){
+            delete m_alignableTransforms[k];
+        }
+    }
+
+
+
+    unsigned int PixelDetectorManager::getNumTreeTops() const
+    {
+        return m_volume.size(); 
+    }
+
+    PVConstLink PixelDetectorManager::getTreeTop(unsigned int i) const
+    {
+        return m_volume[i];
+    }
+
+    void PixelDetectorManager::addTreeTop(PVLink vol){
+        vol->ref();
+        m_volume.push_back(vol);
+    }
+
+
+    SiDetectorElement* PixelDetectorManager::getDetectorElement(const Identifier & id) const
+    {  
+  // NB the id helpers implementation for getting a hash is not optimal.
+  // Essentially does a binary search.
+  // Make sure it is a wafer Id
+        Identifier waferId = id;
+#ifndef __IDENTIFIER_64BIT__
+  // pixel ids have special treatement. It is possible to distinguish between
+  // a wafer id and a pixel cell id by checking bit 32, which is set for a pixel cell id.
+        if (id.is_valid() && (id.get_compact() & 0x80000000)) {
+            waferId =  m_idHelper->wafer_id(id);
+        }
+#else  
+        waferId =  m_idHelper->wafer_id(id);
+#endif /* __IDENTIFIER_64BIT__ */
+        IdentifierHash idHash = m_idHelper->wafer_hash(waferId);
+        if (idHash.is_valid()) {
+            return m_elementCollection[idHash];
+        } else {
+            return 0;
+        }
+    }
+
+
+    SiDetectorElement*  PixelDetectorManager::getDetectorElement(const IdentifierHash & idHash) const
+    {
+        return m_elementCollection[idHash];
+    }
+
+    SiDetectorElement* PixelDetectorManager::getDetectorElement(int barrel_endcap, int layer_wheel, int phi_module, int eta_module) const
+    {
+        return getDetectorElement(m_idHelper->wafer_id(barrel_endcap, layer_wheel, phi_module, eta_module));
+    }
+
+
+    const SiDetectorElementCollection* PixelDetectorManager::getDetectorElementCollection() const
+    { 
+        return &m_elementCollection;
+    }
+
+    SiDetectorElementCollection::const_iterator PixelDetectorManager::getDetectorElementBegin() const
+    {
+        return m_elementCollection.begin();
+    }
+
+    SiDetectorElementCollection::const_iterator PixelDetectorManager::getDetectorElementEnd() const
+    {
+        return m_elementCollection.end();
+    }
+
+
+    void PixelDetectorManager::addDetectorElement(SiDetectorElement * element)
+    {
+        IdentifierHash idHash = element->identifyHash();
+        if (idHash >=  m_elementCollection.size())
+            throw std::runtime_error("PixelDetectorManager: Error adding detector element.");
+        m_elementCollection[idHash] = element;
+    }
+
+    void PixelDetectorManager::initNeighbours()
+    {
+        SiDetectorElementCollection::iterator iter;
+
+        // Loop over all elements and set the neighbours
+        for (iter = m_elementCollection.begin(); iter != m_elementCollection.end(); ++iter){
+
+            SiDetectorElement * element = *iter;
+            if (element) {
+
+                IdentifierHash idHash = element->identifyHash();
+                IdentifierHash idHashOther;
+
+                int result;
+                // If no neighbour, result != 0 in which case we leave neighbour as null
+                result = m_idHelper->get_next_in_eta(idHash, idHashOther);
+                if (result==0) element->setNextInEta(m_elementCollection[idHashOther]);
+
+                result = m_idHelper->get_prev_in_eta(idHash, idHashOther);
+                if (result==0) element->setPrevInEta(m_elementCollection[idHashOther]);
+
+                result = m_idHelper->get_next_in_phi(idHash, idHashOther);
+                if (result==0) element->setNextInPhi(m_elementCollection[idHashOther]);
+
+                result = m_idHelper->get_prev_in_phi(idHash, idHashOther);
+                if (result==0) element->setPrevInPhi(m_elementCollection[idHashOther]);
+            }
+        }
+    }
+
+
+    const PixelID* PixelDetectorManager::getIdHelper() const
+    {
+        return m_idHelper;
+    }
+
+    unsigned int PixelDetectorManager::getBarrelLayers() const
+    {
+        unsigned int barrelLayers = 0;
+        for (int i = numerology().numLayers() - 1; i >= 0; --i) {
+            barrelLayers *= 10;
+            barrelLayers += numerology().useLayer(i);
+        }
+        return barrelLayers;
+    }
+
+    unsigned int PixelDetectorManager::getEndcapLayers() const
+    {
+        unsigned int endcapLayers = 0;
+        for (int i = numerology().numDisks() - 1; i >= 0; --i) {
+            endcapLayers *= 10;
+            endcapLayers += numerology().useDisk(i);
+        }
+        return endcapLayers;
+    }
+
+
+    bool PixelDetectorManager::setAlignableTransformDelta(int level, 
+                                                          const Identifier & id, 
+                                                          const Amg::Transform3D & delta,
+                                                          FrameType frame) const
+    {
+
+        if (level == 0) { // At the element level - local shift
+
+            // We retrieve it via a hashId.
+            IdentifierHash idHash = m_idHelper->wafer_hash(id);
+            if (!idHash.is_valid()) return false;
+
+            if (frame == InDetDD::global) {
+
+                return setAlignableTransformGlobalDelta(m_alignableTransforms[idHash], delta);
+
+            } else if (frame == InDetDD::local) {
+
+                const SiDetectorElement * element =  m_elementCollection[idHash];
+                if (!element) return false;
+
+                // Its a local transform
+                return setAlignableTransformLocalDelta(m_alignableTransforms[idHash], element->transform(), delta);
+            } else {
+                // other not supported
+                msg(MSG::WARNING) << "Frames other than global or local are not supported." << endreq;
+                return false;
+            }
+
+        } else { // higher level
+
+            if (frame != InDetDD::global) {
+                msg(MSG::WARNING) << "Non global shift at higher levels is not possible." << endreq;
+                return false;
+            }
+
+            int index = level - FIRST_HIGHER_LEVEL; // level 0 is treated separately.
+            if (index >=  static_cast<int>(m_higherAlignableTransforms.size())) return false;
+
+            // We retrieve it from a map. 
+            AlignableTransformMap::const_iterator iter;    
+            iter = m_higherAlignableTransforms[index].find(id);
+            if (iter == m_higherAlignableTransforms[index].end()) return false;          
+
+            // Its a global transform
+            return setAlignableTransformGlobalDelta(iter->second, delta);
+        }
+
+    }
+
+
+    void PixelDetectorManager::addAlignableTransform (int level, 
+                                                      const Identifier & id, 
+                                                      GeoAlignableTransform *transform,
+                                                      const GeoVPhysVol * child)
+    {
+        if (m_idHelper) {
+
+            const GeoVFullPhysVol * childFPV = dynamic_cast<const GeoVFullPhysVol *>(child);
+            if (!childFPV) { 
+                msg(MSG::ERROR) << "Child of alignable transform is not a full physical volume" 
+                    << endreq;
+            } else {
+                addAlignableTransform (level, id, transform, childFPV);
+            }
+        }
+    }
+
+    void PixelDetectorManager::addAlignableTransform (int level, 
+                                                      const Identifier & id, 
+                                                      GeoAlignableTransform *transform,
+                                                      const GeoVFullPhysVol * child)
+    {
+        if (m_idHelper) {
+            if (level == 0) {
+                IdentifierHash idHash = m_idHelper->wafer_hash(id);
+                if (idHash.is_valid()) {
+                    m_alignableTransforms[idHash]= new ExtendedAlignableTransform(transform, child);
+                } 
+            } else {
+                // Higher levels are saved in a map. NB the index is level-1 as level=0 is treated above.     
+                int index = level - FIRST_HIGHER_LEVEL; 
+                if (index >= static_cast<int>(m_higherAlignableTransforms.size())) m_higherAlignableTransforms.resize(index+1); 
+                m_higherAlignableTransforms[index][id] = new ExtendedAlignableTransform(transform, child);
+            }
+        }  
+    }
+
+    bool PixelDetectorManager::identifierBelongs(const Identifier & id) const
+    {
+        return getIdHelper()->is_pixel(id);
+    }
+
+
+
+    const PixelModuleDesign* PixelDetectorManager::getPixelDesign(int i) const
+    {
+        return dynamic_cast<const PixelModuleDesign *>(getDesign(i));
+    }
+
+
+} // namespace InDetDD
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelDiodeMap.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelDiodeMap.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..7d6514a887118d7669d4cd317933b7e43755320c
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelDiodeMap.cxx
@@ -0,0 +1,299 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelDiodeMap.cxx
+//   Implementation file for class PixelDiodeMap
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Pixel Detector software
+///////////////////////////////////////////////////////////////////
+// Version 4.2 14/08/2001 David Calvet
+// Modified: Grant Gorfine
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/PixelDiodeMap.h"
+#include "InDetReadoutGeometry/PixelDiodeMatrix.h"
+#include "InDetReadoutGeometry/SiCellId.h"
+
+#include <cmath>
+#include <algorithm>
+
+namespace InDetDD {
+
+
+
+// Implicit constructor:
+PixelDiodeMap::PixelDiodeMap(const PixelDiodeMatrix * matrix) :
+  m_matrix(matrix),
+  m_generalLayout(false) 
+{
+  m_matrix->ref();
+}
+
+PixelDiodeMap::~PixelDiodeMap()
+{
+  m_matrix->unref();
+}
+
+
+  SiCellId PixelDiodeMap::cellIdOfPosition(const Amg::Vector2D & localPos) const
+{
+  using std::abs;
+  using Trk::distPhi;
+  using Trk::distEta;
+
+  // Check that we are in the bounds of the top level matrix
+  // NB. edge is included in bounds.
+
+  double halfWidth = 0.5*width();
+  double halfLength = 0.5*length();
+  if ( (abs(localPos[distPhi]) > halfWidth) || 
+       (abs(localPos[distEta]) > halfLength) ) {
+    return SiCellId(); // Invalid Id.
+  }
+
+  // position relative to bottom left corner.
+  Amg::Vector2D relativePos = localPos + Amg::Vector2D(halfWidth, halfLength);
+
+  // The cellId returned will be added to this so we must start with 0,0.
+  SiCellId cellId(0,0);
+
+  const PixelDiodeMatrix * cell = m_matrix->cellIdOfPosition(relativePos, cellId);
+
+  // return invalid Id if there was a problem (don't expect this to be the case).
+  if (!cell) {
+    return SiCellId(); // Invalid id.
+  } 
+
+  return cellId;
+  
+}
+
+  
+// Get diodes parameters (position and size):
+SiDiodesParameters
+PixelDiodeMap::parameters(const SiCellId & cellId) const
+{
+
+  // Check we are in range
+  
+  if (!cellId.isValid() || 
+      (cellId.phiIndex() < 0) || 
+      (cellId.phiIndex() >= m_matrix->phiCells()) ||
+      (cellId.etaIndex() < 0) ||
+      (cellId.etaIndex() >= m_matrix->etaCells())) {
+    return SiDiodesParameters();
+  }
+
+  double halfWidth = 0.5*width();
+  double halfLength = 0.5*length();
+  
+  //
+  // Position is relative to left bottom corner.
+  //
+  Amg::Vector2D position(-halfWidth, -halfLength);
+  const PixelDiodeMatrix * cell = m_matrix->positionOfCell(cellId, position);
+  
+  if (cell) {
+    
+    // get size
+    Amg::Vector2D size(cell->phiWidth(), cell->etaWidth());
+
+    // return parameters
+    return SiDiodesParameters(position,size);
+  }
+
+  // return something in case of failure.
+  return SiDiodesParameters();
+}
+
+void PixelDiodeMap::neighboursOfCell(const SiCellId & cellId,
+				     std::vector<SiCellId> &neighbours) const
+{
+  neighbours.clear();
+
+  if (!cellId.isValid()) return;
+
+  // If non regular layout revert to slower method
+  if (m_generalLayout) return neighboursOfCellGeneral(cellId, neighbours);
+
+  neighbours.reserve(8);
+  // neighbours easily determined from cell number
+  // normally 8 neighbours 4 edge and 4 corners
+  
+  int phiIndex = cellId.phiIndex();
+  int etaIndex = cellId.etaIndex();
+
+  // M = minus
+  // P = plus
+  int phiM = phiIndex-1;
+  int phiP = phiIndex+1;
+  int etaM = etaIndex-1;
+  int etaP = etaIndex+1;
+
+  // -,0
+  if (phiM >= 0)                                 neighbours.push_back(SiCellId(phiM,etaIndex));
+  // -,-
+  if (phiM >= 0 && etaM >= 0)                    neighbours.push_back(SiCellId(phiM,etaM));
+  // 0,-
+  if (etaM >= 0)                                 neighbours.push_back(SiCellId(phiIndex,etaM));
+  // +,-
+  if (phiP < phiDiodes() && etaM >= 0)           neighbours.push_back(SiCellId(phiP,etaM));
+  // +,0
+  if (phiP < phiDiodes())                        neighbours.push_back(SiCellId(phiP,etaIndex));
+  // -,+
+  if (phiM >= 0 && etaP < etaDiodes())           neighbours.push_back(SiCellId(phiM,etaP));
+  // 0,+
+  if (etaP < etaDiodes())                        neighbours.push_back(SiCellId(phiIndex,etaP));
+  // +,+
+  if (phiP < phiDiodes() && etaP < etaDiodes())  neighbours.push_back(SiCellId(phiP,etaP));
+}
+
+// Get the neighbouring PixelDiodes of a given PixelDiode:
+// This will work for more complex layouts such as bricking. Probably never really needed but
+// since the code was here I keep it available.
+void PixelDiodeMap::neighboursOfCellGeneral(const SiCellId & cellId,
+					    std::vector<SiCellId> &neighbours) const
+{
+  // extract the diode spatial parameters
+  const SiDiodesParameters params=parameters(cellId);
+  const SiLocalPosition diodeCenter=params.centre();
+  const SiLocalPosition diodeSize=params.width();
+  const double &centerColumn=diodeCenter.xColumn();
+  const double &centerRow=diodeCenter.xRow();
+  const double halfSizeColumn=diodeSize.xColumn()/2;
+  const double halfSizeRow=diodeSize.xRow()/2;
+
+  // parameter
+  const double epsilon=0.01;
+
+  // compute the points to check
+  const double left1=centerColumn-halfSizeColumn*(1+epsilon);
+  const double right1=centerColumn+halfSizeColumn*(1+epsilon);
+  const double left2=centerColumn-halfSizeColumn*(1-epsilon);
+  const double right2=centerColumn+halfSizeColumn*(1-epsilon);
+  const double top1=centerRow+halfSizeRow*(1+epsilon);
+  const double bot1=centerRow-halfSizeRow*(1+epsilon);
+  const double top2=centerRow+halfSizeRow*(1-epsilon);
+  const double bot2=centerRow-halfSizeRow*(1-epsilon);
+
+  // build the list of positions to check
+  std::vector<SiLocalPosition> positions;
+  positions.reserve(12);
+  SiLocalPosition position;
+  position.xRow(bot1); position.xColumn(left2); positions.push_back(position);
+  position.xRow(bot1); position.xColumn(left1); positions.push_back(position);
+  position.xRow(bot2); position.xColumn(left1); positions.push_back(position);
+  position.xRow(top2); position.xColumn(left1); positions.push_back(position);
+  position.xRow(top1); position.xColumn(left1); positions.push_back(position);
+  position.xRow(top1); position.xColumn(left2); positions.push_back(position);
+  position.xRow(bot1); position.xColumn(right2); positions.push_back(position);
+  position.xRow(bot1); position.xColumn(right1); positions.push_back(position);
+  position.xRow(bot2); position.xColumn(right1); positions.push_back(position);
+  position.xRow(top2); position.xColumn(right1); positions.push_back(position);
+  position.xRow(top1); position.xColumn(right1); positions.push_back(position);
+  position.xRow(top1); position.xColumn(right2); positions.push_back(position);
+
+  // build the list of neighbours
+  neighbours.reserve(8);
+
+  // loop on all positions to check
+  for(std::vector<SiLocalPosition>::const_iterator p_position=positions.begin() ;
+      p_position!=positions.end() ; ++p_position) {
+
+    // get the PixelDiode for this position
+    SiCellId cellId_neighb = cellIdOfPosition(*p_position);
+
+    if (cellId.isValid()) {
+      // check if the diode is already in the list
+      //bool found=false;
+      std::vector<SiCellId>::const_iterator foundIter
+	= std::find(neighbours.begin(), neighbours.end(), cellId_neighb );
+
+      // If not found add this diode to the list
+      if (foundIter ==  neighbours.end()) neighbours.push_back(cellId_neighb);
+		    
+    } 
+  }
+}
+
+
+// Compute the intersection length of two diodes:
+double PixelDiodeMap::intersectionLength(const SiCellId &diode1,
+					 const SiCellId &diode2) const
+{ 
+  if(!diode1.isValid() || !diode2.isValid()) return 0;
+  // If non regular layout revert to slower method
+  if (m_generalLayout) return intersectionLengthGeneral(diode1, diode2);
+
+  const SiLocalPosition size = parameters(diode1).width();
+
+  int phiIndexDelta = std::abs(diode1.phiIndex() - diode2.phiIndex());
+  int etaIndexDelta = std::abs(diode1.etaIndex() - diode2.etaIndex());
+
+  // Intersection length is just the length or width of the diode depending on which neighbour.
+  if (phiIndexDelta == 1 && etaIndexDelta == 0) return size.xEta();
+  if (phiIndexDelta == 0 && etaIndexDelta == 1) return size.xPhi();
+  // Will return 0 if it is a corner neighbour or if its not a neighbour or if they are oth the same diode.
+  return 0;
+}
+
+// Compute the intersection length of two diodes:
+// This will work for more complex layouts such as bricking. Probably never really needed but
+// since the code was here I keep it available.
+double PixelDiodeMap::intersectionLengthGeneral(const SiCellId &diode1,
+						const SiCellId &diode2) const
+
+{
+  const SiDiodesParameters params1=parameters(diode1);
+  const SiDiodesParameters params2=parameters(diode2);
+  const SiLocalPosition center1=params1.centre();
+  const SiLocalPosition center2=params2.centre();
+  const SiLocalPosition size1=params1.width();
+  const SiLocalPosition size2=params2.width();
+  
+  // compute intersection length on column direction
+  const double intersectionColumn=intersectionLength1D(center1.xColumn(),
+					  size1.xColumn(),
+					  center2.xColumn(),
+					  size2.xColumn());
+  // compute intersection length on row direction
+  const double intersectionRow=intersectionLength1D(center1.xRow(),
+				       size1.xRow(),
+				       center2.xRow(),
+				       size2.xRow());
+
+  // return the real intersection 
+  // (if both directions intersect, there is a problem)
+  if (intersectionColumn>0) {
+    if (intersectionRow>0) return 0;
+    return intersectionColumn;
+  } else {
+    return intersectionRow;
+  }
+}
+
+// Compute the intersection length along one direction:
+double PixelDiodeMap::intersectionLength1D(const double x1,const double dx1,
+					   const double x2,const double dx2) const
+{
+  // compute distance between the two centers
+  double distance=std::abs(x1-x2);
+
+  // compute theoretical intersection
+  double intersection=(dx1+dx2)/2-distance;
+
+  // if intersection if negative, no intersection
+  if (intersection<-1e-10) return intersection;
+  else if (intersection<1e-10) return 0;
+  else {
+    // intersection cannot exceed size
+    if (intersection>dx1) intersection=dx1;
+    if (intersection>dx2) intersection=dx2;
+    return intersection;
+  }
+}
+
+} // namespace InDetDD
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelDiodeMatrix.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelDiodeMatrix.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..95f21a1cf999db54dc35d045508787e7db793c57
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelDiodeMatrix.cxx
@@ -0,0 +1,325 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/PixelDiodeMatrix.h"
+#include "InDetReadoutGeometry/SiCellId.h"
+#include "TrkEventPrimitives/ParamDefs.h"
+
+#include <cassert>
+
+namespace InDetDD {
+
+PixelDiodeMatrix::PixelDiodeMatrix(double phiWidth, double etaWidth)
+  : m_phiWidth(phiWidth),
+    m_etaWidth(etaWidth),
+    m_phiCells(1),
+    m_etaCells(1),
+    m_direction(phiDir), // Irrelevant
+    m_numCells(0),
+    m_lowerCell(0),
+    m_middleCells(0),
+    m_upperCell(0),
+    m_singleCell(true)
+{}
+
+PixelDiodeMatrix::PixelDiodeMatrix(Direction direction,  // phi or eta
+				   const PixelDiodeMatrix * lowerCell,
+				   const PixelDiodeMatrix * middleCells,
+				   int numCells,
+				   const PixelDiodeMatrix * upperCell)
+  : m_phiWidth(0),
+    m_etaWidth(0),
+    m_phiCells(0),
+    m_etaCells(0),
+    m_direction(direction),
+    m_numCells(numCells),
+    m_lowerCell(lowerCell),
+    m_middleCells(middleCells),
+    m_upperCell(upperCell),
+    m_singleCell(false)
+{
+  // middleCells must be non zero.
+  assert(m_middleCells);
+
+  // Increment ref counts
+  if (m_lowerCell) m_lowerCell->ref();
+  if (m_middleCells) m_middleCells->ref();
+  if (m_upperCell) m_upperCell->ref();
+ 
+  if (m_direction == phiDir) {
+    
+    // In eta direction widths must be all the same.
+    if (m_middleCells){
+      m_etaWidth = m_middleCells->etaWidth();
+      m_etaCells = m_middleCells->etaCells();
+    }
+    // Check lower and upper are consistent
+    // TODO.
+    
+    if (m_lowerCell) {
+      m_phiWidth += m_lowerCell->phiWidth();
+      m_phiCells += m_lowerCell->phiCells();
+    }
+
+    if (m_middleCells){
+      m_phiWidth += m_numCells * m_middleCells->phiWidth();
+      m_phiCells += m_numCells * m_middleCells->phiCells();
+    }
+  
+    if (m_upperCell) {
+      m_phiWidth += m_upperCell->phiWidth();
+      m_phiCells += m_upperCell->phiCells();
+    }
+
+  } else { // eta Direction
+
+    // In phi direction widths must be all the same.
+    if (m_middleCells){
+      m_phiWidth = m_middleCells->phiWidth();
+      m_phiCells = m_middleCells->phiCells();
+    }
+    // Check lower and upper are consistent
+    // TODO.
+    
+    if (m_lowerCell) {
+      m_etaWidth += m_lowerCell->etaWidth();
+      m_etaCells += m_lowerCell->etaCells();
+    }
+
+    if (m_middleCells){
+      m_etaWidth += m_numCells * m_middleCells->etaWidth();
+      m_etaCells += m_numCells * m_middleCells->etaCells();
+    }
+  
+    if (m_upperCell) {
+      m_etaWidth += m_upperCell->etaWidth();
+      m_etaCells += m_upperCell->etaCells();
+    }
+
+  }
+
+}
+
+PixelDiodeMatrix:: ~PixelDiodeMatrix()
+{
+  // unref the point the pointers.
+  if (m_lowerCell) m_lowerCell->unref();
+  if (m_middleCells) m_middleCells->unref();
+  if (m_upperCell) m_upperCell->unref();
+}
+
+const PixelDiodeMatrix * 
+PixelDiodeMatrix::cellIdOfPosition(const Amg::Vector2D & relPosition, SiCellId & cellId) const
+
+  /// Description.  
+  /// Overview of algoritm:
+  /// 
+  ///  - Before calling this method on the top level matrix the 2D position is
+  ///    calculated relative to the bottom left corner.
+  ///  - The method cellIdOfPosition is always called with the position relative to
+  ///    bottom left of the cell and the cell id of bottom left child cell. 
+  ///    For the top level matrix this is the position (-halfWidth, -halfLength) and a starting 
+  ///    cell id of (0,0).
+  ///  - It first checks if it is in the lower cell (if it exists). 
+  ///  - If not, it determines which cell by dividing the position relative to
+  ///    the start of the cell array by the pitch in that direction. 
+  ///  - If it is beyond the range of the middle cells it is taken as being in 
+  ///    the upper cell.
+  ///  - The cell number is added to the cellId that is passed to the method
+  ///  - Once the cell is determined the function is called recursively until it
+  ///    reaches a single cell. 
+  ///
+
+{
+  using Trk::distPhi;
+  using Trk::distEta;
+
+  if (m_singleCell) {
+    return this;
+  }
+
+  double relPosDir = 0; // Relative position along m_direction
+  int startIndex = 0;
+  double pitch = 0;
+  int middleCells = 0;
+
+  if (m_direction == phiDir) {
+
+    relPosDir = relPosition[distPhi];
+    pitch = m_middleCells->phiWidth();
+    middleCells = m_middleCells->phiCells();
+
+    if (m_lowerCell) {
+      if (relPosDir < m_lowerCell->phiWidth()) {
+	return m_lowerCell->cellIdOfPosition(relPosition, cellId);
+      } else {
+	relPosDir  -=  m_lowerCell->phiWidth();
+	startIndex +=  m_lowerCell->phiCells();
+      }
+    }
+  } else { // etaDir
+
+    relPosDir = relPosition[distEta];
+    pitch = m_middleCells->etaWidth();
+    middleCells = m_middleCells->etaCells();
+
+    if (m_lowerCell) {
+      if (relPosDir < m_lowerCell->etaWidth()) {
+	return m_lowerCell->cellIdOfPosition(relPosition, cellId);
+      } else {
+	relPosDir  -=  m_lowerCell->etaWidth();
+	startIndex +=  m_lowerCell->etaCells();
+      }
+    }
+  } 
+
+  
+  int index = static_cast<int>((relPosDir) / pitch);
+
+  if (index < 0) index = 0; // Make sure its in range (in case of rounding errors)
+  const PixelDiodeMatrix * nextCell = 0;
+
+  if (m_upperCell && (index >= m_numCells)) { 
+    // We are in the upper cell. 
+    index = m_numCells;
+    nextCell = m_upperCell;
+  } else {
+    // We are in the middle cells
+    // Make sure its in range (in case of rounding errors)
+    if (index >= m_numCells) index = m_numCells - 1;
+    nextCell = m_middleCells;
+  }
+  
+
+  relPosDir  -= index *  pitch;
+  startIndex += index *  middleCells;
+
+  int newPhiIndex = cellId.phiIndex();
+  int newEtaIndex = cellId.etaIndex();
+  const PixelDiodeMatrix * cell = 0;
+
+  if (m_direction == phiDir) {
+    if (nextCell->singleCell()) {
+      newPhiIndex += startIndex;
+      cell = nextCell;
+    } else {
+      Amg::Vector2D newRelPos(relPosDir, relPosition[distEta]);
+      SiCellId relId(0,0);
+      cell = nextCell->cellIdOfPosition(newRelPos, relId);
+      newPhiIndex += startIndex + relId.phiIndex();
+      newEtaIndex += relId.etaIndex();
+    } 
+  } else { 
+    if (nextCell->singleCell()) {
+      newEtaIndex += startIndex;
+      cell = nextCell;
+    } else {
+      Amg::Vector2D newRelPos(relPosition[distPhi], relPosDir);
+      SiCellId relId(0,0);
+      cell = nextCell->cellIdOfPosition(newRelPos, relId);
+      newPhiIndex += relId.phiIndex();
+      newEtaIndex += startIndex + relId.etaIndex();
+    }
+  }
+
+  cellId = SiCellId(newPhiIndex, newEtaIndex);
+  return cell;
+}
+
+	
+	   
+const PixelDiodeMatrix * 
+PixelDiodeMatrix::positionOfCell(const SiCellId & cellId, Amg::Vector2D & position) const
+
+  /// Description.  
+  /// Overview of algoritm:
+  ///
+  ///  - It starts with the position of the bottom left corner of the cell.
+  ///    For the full matrix this is (-halfwidth,-halflength)
+  ///  - It first checks if is in the lower cell (if it exists).
+  ///  - If not it determines the bottom edge of the cell by multiplying the cell
+  ///    number by the pitch.
+  ///  - If it is beyond the range of the middle cells it is taken as being in 
+  ///    the upper cell.
+  ///  - This position is then passed recursively to the same method until it
+  ///    reaches a single cell.
+  ///  - At the end the 2D position is then transformed to the position
+  ///    relative to the module center.
+
+{
+  using Trk::distPhi;
+  using Trk::distEta;
+
+  if (m_singleCell) {
+    position[distPhi] += 0.5*m_phiWidth;
+    position[distEta] += 0.5*m_etaWidth;
+    return this;
+  }
+
+  int relIndex = 0; // Relative index along m_direction
+  double pitch = 0;
+  int middleCells = 0;
+  double startPos = 0;
+
+  if (m_direction == phiDir) {
+
+    relIndex = cellId.phiIndex();
+    pitch = m_middleCells->phiWidth();
+    middleCells = m_middleCells->phiCells();
+    
+    if (m_lowerCell) {
+      if (relIndex < m_lowerCell->phiCells()) {
+	return m_lowerCell->positionOfCell(cellId, position);
+      } else {
+	relIndex -=  m_lowerCell->phiCells();
+	startPos +=  m_lowerCell->phiWidth();
+      }
+    } 
+
+  } else { // etaDir
+
+    relIndex = cellId.etaIndex();
+    pitch = m_middleCells->etaWidth();
+    middleCells = m_middleCells->etaCells();
+
+    if (m_lowerCell) {
+      if (relIndex < m_lowerCell->etaCells()) {
+	return m_lowerCell->positionOfCell(cellId, position);
+      } else {
+	relIndex -=  m_lowerCell->etaCells();
+	startPos +=  m_lowerCell->etaWidth();
+      }
+    }
+  } 
+
+  int index = relIndex / middleCells;
+  if (index > m_numCells) index = m_numCells;
+  relIndex -= index * middleCells;
+  startPos += index * pitch;
+
+  const PixelDiodeMatrix * nextCell = 0;
+
+  if (m_upperCell && (index == m_numCells)) { 
+    // We are in the upper cell. 
+    nextCell = m_upperCell;
+  } else {
+    // We are in the middle cells
+    nextCell = m_middleCells;
+  }
+
+  const PixelDiodeMatrix * cell = 0;
+  if (m_direction == phiDir) {
+    SiCellId relId(relIndex,cellId.etaIndex());
+    position[distPhi] += startPos;
+    cell = nextCell->positionOfCell(relId, position);
+  } else {
+    SiCellId relId(cellId.phiIndex(),relIndex);
+    position[distEta] += startPos;
+    cell = nextCell->positionOfCell(relId, position);
+  }    
+  
+  return cell;
+}
+
+} // end namespace
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelModuleDesign.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelModuleDesign.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..573c1cf92e9a239533da66c934c010067632d191
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelModuleDesign.cxx
@@ -0,0 +1,252 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelModuleDesign.cxx
+//   Implementation file for class PixelModuleDesign
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Pixel Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.9 18/03/2002 Alessandro Fornaini
+// Modified: Grant Gorfine
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/PixelModuleDesign.h"
+#include "Identifier/Identifier.h"
+#include "InDetReadoutGeometry/SiCellId.h"
+#include "InDetReadoutGeometry/SiReadoutCellId.h"
+#include "TrkSurfaces/RectangleBounds.h"
+
+#include <cmath>
+
+namespace InDetDD {
+
+using std::abs;
+
+// Constructor with parameters:
+
+PixelModuleDesign::PixelModuleDesign(const double thickness,
+				     const int circuitsPerColumn,
+				     const int circuitsPerRow,
+				     const int cellColumnsPerCircuit,
+				     const int cellRowsPerCircuit,
+				     const int diodeColumnsPerCircuit,
+				     const int diodeRowsPerCircuit,
+				     const PixelDiodeMatrix * matrix,
+				     InDetDD::CarrierType carrierType,
+				     int readoutSide,
+				     bool is3D) :
+
+  SiDetectorDesign(thickness, 
+		   true, true, true, // phi,eta,depth axes symmetric
+		   carrierType,
+		   readoutSide),
+  m_diodeMap(matrix),
+  m_readoutScheme(circuitsPerColumn,circuitsPerRow,
+		  cellColumnsPerCircuit,cellRowsPerCircuit,
+		  diodeColumnsPerCircuit,diodeRowsPerCircuit),
+  m_bounds(0),
+  m_is3D(is3D)
+{
+  //  m_bounds = new Trk::RectangleBounds(0.5*width(), 0.5*length());
+}
+
+// Destructor:
+PixelModuleDesign::~PixelModuleDesign()
+{
+  delete m_bounds;
+}
+
+// Returns distance to nearest detector edge 
+// +ve = inside
+// -ve = outside
+void
+PixelModuleDesign::distanceToDetectorEdge(const SiLocalPosition & localPosition,
+					  double & etaDist, double & phiDist) const
+{ 
+  // This assume element is centered at 0,0 
+  // As the calculation is symmetric around 0,0 we only have to test it for one side.
+  double xEta = abs(localPosition.xEta());
+  double xPhi = abs(localPosition.xPhi());
+
+  double xEtaEdge = 0.5*length();
+  double xPhiEdge = 0.5*width();
+
+  // Distance to top/bottom
+  etaDist = xEtaEdge - xEta;
+  
+  // Distance to right/left edge
+  phiDist = xPhiEdge - xPhi;
+
+}
+ 
+SiDiodesParameters PixelModuleDesign::parameters(const SiCellId & cellId) const
+{
+  return m_diodeMap.parameters(cellId);
+}
+
+SiLocalPosition PixelModuleDesign::localPositionOfCell(const SiCellId & cellId) const
+{
+  return m_diodeMap.parameters(cellId).centre(); 
+}
+
+
+// Helper method for stereo angle computation
+HepGeom::Vector3D<double> PixelModuleDesign::phiMeasureSegment(const SiLocalPosition&) const
+{
+  HepGeom::Vector3D<double> segment;
+  segment[etaAxis()]=1;
+  return segment;
+}
+
+// Special method for SCT (irrelevant here):
+std::pair<SiLocalPosition,SiLocalPosition> PixelModuleDesign::endsOfStrip(const SiLocalPosition &position) const
+{
+  return std::pair<SiLocalPosition,SiLocalPosition>(position,position);
+}
+ 
+  
+// Methods to calculate length of a module
+double PixelModuleDesign::length() const
+{
+  return m_diodeMap.length();  
+}
+
+// Methods to calculate average width of a module
+double PixelModuleDesign::width() const
+{
+  return m_diodeMap.width();
+}
+
+// Methods to calculate minimum width of a module
+double PixelModuleDesign::minWidth() const
+{
+  return width();
+}
+
+// Methods to calculate maximum width of a module
+double PixelModuleDesign::maxWidth() const
+{
+  return width();
+}
+
+
+// Method to calculate eta width from a column range
+double PixelModuleDesign::widthFromColumnRange(const int colMin, const int colMax) const 
+{
+  SiCellId idMin(0, colMin);
+  SiCellId idMax(0, colMax);
+  
+  double minEta = parameters(idMin).xEtaMin(); 
+  double maxEta = parameters(idMax).xEtaMax();
+  
+  return fabs(maxEta-minEta);
+}
+
+// Method to calculate phi width from a row range
+double PixelModuleDesign::widthFromRowRange(const int rowMin, const int rowMax) const 
+{
+
+  SiCellId idMin(rowMin, 0);
+  SiCellId idMax(rowMax, 0);
+  double minPhi = parameters(idMin).xPhiMin();
+  double maxPhi = parameters(idMax).xPhiMax(); 
+
+  return fabs(maxPhi-minPhi);
+}
+
+// Pitch in phi direction
+double 
+PixelModuleDesign::phiPitch() const
+{
+  // Average pitch. 
+  return width() / rows();
+}
+
+// Pitch in phi direction
+double 
+PixelModuleDesign::phiPitch(const SiLocalPosition &) const
+{
+  // Cheat since we know its constant.
+  return phiPitch();
+}
+
+// Pitch in eta direction
+double 
+PixelModuleDesign::etaPitch() const
+{
+  // Average pitch
+  return length() / columns();
+}
+
+SiCellId PixelModuleDesign::cellIdOfPosition(const SiLocalPosition & localPosition) const
+{
+  return m_diodeMap.cellIdOfPosition(localPosition);
+}
+
+
+int PixelModuleDesign::numberOfConnectedCells(const SiReadoutCellId & readoutId) const
+{
+  return m_readoutScheme.numberOfConnectedCells(readoutId);
+}
+
+SiCellId 
+PixelModuleDesign::connectedCell(const SiReadoutCellId & readoutId, int number) const
+{
+  return m_readoutScheme.connectedCell(readoutId, number);
+}
+
+SiCellId 
+PixelModuleDesign::gangedCell(const SiCellId & cellId) const
+{
+  return m_readoutScheme.gangedCell(cellId);  
+}
+
+SiReadoutCellId
+PixelModuleDesign::readoutIdOfCell(const SiCellId & cellId) const
+{
+  return m_readoutScheme.readoutIdOfCell(cellId);
+}
+
+
+SiReadoutCellId 
+PixelModuleDesign::readoutIdOfPosition(const SiLocalPosition & localPos) const
+{
+  return m_readoutScheme.readoutIdOfCell(m_diodeMap.cellIdOfPosition(localPos));
+}
+
+// Given row and column index of diode, returns position of diode center
+// ALTERNATIVE/PREFERED way is to use localPositionOfCell(const SiCellId & cellId) or 
+// rawLocalPositionOfCell method in SiDetectorElement.
+// DEPRECATED (but used in numerous places)
+SiLocalPosition PixelModuleDesign::positionFromColumnRow(const int column, const int row) const
+{
+  return localPositionOfCell(SiCellId(row,column));
+}
+ 
+
+const Trk::SurfaceBounds & 
+PixelModuleDesign::bounds() const
+{
+  // We create on demand as width and length are 0 when PixeModuleDesign first gets
+  // created.
+  if (!m_bounds) m_bounds = new Trk::RectangleBounds(0.5*width(), 0.5*length());
+  return *m_bounds;
+}
+
+
+
+void PixelModuleDesign::setGeneralLayout()
+{
+  m_diodeMap.setGeneralLayout();
+}
+
+SiCellId 
+PixelModuleDesign::cellIdInRange(const SiCellId & cellId) const
+{
+  return m_diodeMap.cellIdInRange(cellId);
+}
+
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelMultipleConnection1D.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelMultipleConnection1D.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..d2f6d11c8158fc5019f44298828c640c14ebc7d5
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelMultipleConnection1D.cxx
@@ -0,0 +1,141 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelMultipleConnection1D.cxx 
+//   Implementation file for class PixelMultipleConnection1D
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Pixel Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.1 05/04/2001 David Calvet
+// 06/02/2008 Grant Gorfine
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/PixelMultipleConnection1D.h"
+#include <iostream>
+
+namespace InDetDD {
+
+// Constructor with parameters:
+PixelMultipleConnection1D::PixelMultipleConnection1D(const int lowerIndex,
+						     const std::vector<int> &connections) 
+  : m_lowerDiode(0),
+    m_upperDiode(-1),
+    m_lowerReadout(0),
+    m_upperReadout(-1)
+{
+  set(lowerIndex, connections);
+}
+
+PixelMultipleConnection1D::PixelMultipleConnection1D() 
+  : m_lowerDiode(0),
+    m_upperDiode(-1),
+    m_lowerReadout(0),
+    m_upperReadout(-1)
+{}
+ 
+void
+PixelMultipleConnection1D::set(const int lowerIndex,
+			       const std::vector<int> &connections) 
+{
+
+  // extract lower and upper diode and readout cell numbers from connections vector
+  bool firstDiode = true;
+  bool firstReadout = true;
+  for(unsigned int index = 0; index < connections.size(); ++index) {
+    int readout = connections[index];
+    int diode = lowerIndex + index;
+    if (firstDiode && readout != diode) {
+      m_lowerDiode = diode; 
+      m_upperDiode = diode; 
+      firstDiode = false;
+    }
+    if (firstReadout) {
+      m_lowerReadout=readout;
+      m_upperReadout=readout;
+      firstReadout = false;
+    }
+    if (readout<m_lowerReadout) m_lowerReadout=readout;
+    if (readout>m_upperReadout) m_upperReadout=readout;
+    if (readout != diode && diode < m_lowerDiode) m_lowerDiode = diode; 
+    if (readout != diode && diode > m_upperDiode) m_upperDiode = diode; 
+  }
+
+  // Fource readout range to be include diode range (this is generally already the case)
+  if (m_lowerReadout > m_lowerDiode) m_lowerReadout = m_lowerDiode;
+  if (m_upperReadout < m_upperDiode) m_upperReadout = m_upperDiode;
+
+  m_diodeToReadout.resize(m_upperDiode - m_lowerDiode + 1);
+  m_readoutToDiode.resize(m_upperReadout - m_lowerReadout + 1);
+
+  // First fill primary cell. ie diode and readout the same.
+  for(unsigned int index = 0; index < connections.size(); ++index) {
+    int readout = connections[index];
+    int diode = lowerIndex + index;
+    if (readout == diode)  m_readoutToDiode[readout-m_lowerReadout].push_back(diode);
+  }
+
+  
+  // Now the rest of readoutToDiode ie diode and readout not the same.
+  // Fill also diodeToReadout
+  for(unsigned int index = 0; index < connections.size(); ++index) {
+    int readout = connections[index];
+    int diode = lowerIndex + index;
+    if (readout != diode)  m_readoutToDiode[readout - m_lowerReadout].push_back(diode);
+    if (diode >= m_lowerDiode && diode <= m_upperDiode) m_diodeToReadout[diode - m_lowerDiode] = readout;
+  }
+
+  // Created ganged map. If the diode is ganged it points to the other diode.
+  m_diodeGanged.resize(m_upperReadout - m_lowerReadout + 1);
+  for(int iDiode = m_lowerReadout; iDiode <=  m_upperReadout; iDiode++) {
+    // Fill with the same index which indicates its not ganged.
+    m_diodeGanged[iDiode - m_lowerReadout] = iDiode;
+    int readout = iDiode;
+    if (!outsideDiode(iDiode)) readout = readoutOfDiode(iDiode);
+    if (numberOfConnectedCells(readout) >= 2) {
+      int cell0 = connectedCell(readout, 0);
+      int cell1 = connectedCell(readout, 1);
+      if (iDiode == cell0) {
+	m_diodeGanged[iDiode - m_lowerReadout] = cell1;
+      } else {
+	m_diodeGanged[iDiode - m_lowerReadout] = cell0;
+      }
+    }
+  }
+
+  // For debugging only
+  //debugPrintout();
+}
+
+void PixelMultipleConnection1D::debugPrintout() 
+{
+  // Debug printout
+  std::cout << "m_lowerDiode = " << m_lowerDiode << std::endl;
+  std::cout << "m_upperDiode = " << m_upperDiode << std::endl;
+  std::cout << "m_lowerReadout = " << m_lowerReadout << std::endl;
+  std::cout << "m_upperReadout = " << m_upperReadout << std::endl;
+  std::cout << "m_readoutToDiode: ";
+  for (unsigned int i = 0; i < m_readoutToDiode.size(); i++) {
+    std::cout << "(" << m_lowerReadout + i << ": ";
+    for (unsigned int j = 0; j < m_readoutToDiode[i].size(); j++) {
+      std::cout << m_readoutToDiode[i][j] << " ";
+    }
+    std::cout << ") ";
+  }
+  std::cout << std::endl;
+  
+  for (unsigned int i = 0; i < m_diodeToReadout.size(); i++) {
+    std::cout << "(" << m_lowerDiode + i << ": " << m_diodeToReadout[i] << ") ";
+  }
+  std::cout << std::endl;
+  
+  for (unsigned int i = 0; i < m_diodeGanged.size(); i++) {
+    std::cout << "(" << m_lowerReadout + i << ": " << m_diodeGanged[i] << ") ";
+  }
+  std::cout << std::endl;
+}
+
+  
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelReadoutScheme.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelReadoutScheme.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..e0e80ff52f89927dfe7263b1590a45c40bba2ff8
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/PixelReadoutScheme.cxx
@@ -0,0 +1,104 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// PixelReadoutScheme.cxx
+//   Implementation file for class PixelReadoutScheme
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Pixel Detector software
+///////////////////////////////////////////////////////////////////
+// Version 2.1 08/06/2001 David Calvet
+// Modified: Grant Gorfine
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/PixelReadoutScheme.h"
+#include "InDetReadoutGeometry/SiCellId.h"
+#include "InDetReadoutGeometry/SiReadoutCellId.h"
+
+namespace InDetDD {
+
+// Constructor with parameters:
+PixelReadoutScheme::PixelReadoutScheme(const int circuitsPerColumn,
+				       const int circuitsPerRow,
+				       const int cellColumnsPerCircuit,
+				       const int cellRowsPerCircuit,
+				       const int diodeColumnsPerCircuit,
+				       const int diodeRowsPerCircuit) :
+  m_numberOfCircuits(circuitsPerColumn*circuitsPerRow),
+  m_columnsPerCircuit(cellColumnsPerCircuit),
+  m_rowsPerCircuit(cellRowsPerCircuit),
+  m_columns(circuitsPerRow*diodeColumnsPerCircuit),
+  m_rows(circuitsPerColumn*diodeRowsPerCircuit)
+{}
+
+
+
+// Number of cells connected to this readout. 2 means its ganged.
+int 
+PixelReadoutScheme::numberOfConnectedCells(const SiReadoutCellId & readoutId) const
+{
+  if (!readoutId.isValid()) return 0;
+  
+  // Do quick check to see if it is outside ganged pixel range.
+  int phiIndex = readoutId.phiIndex();
+  if (m_rowConnections.outsideReadout(phiIndex)) return 1;
+  
+  return m_rowConnections.numberOfConnectedCells(phiIndex);
+  
+}
+
+// Id of diodes connected to this readout. 0 is the primary cell.
+SiCellId 
+PixelReadoutScheme::connectedCell(const SiReadoutCellId & readoutId, unsigned int number) const
+{
+  if (!readoutId.isValid()) return SiCellId();
+  
+  // Do quick check to see if it is outside ganged pixel range.
+  int phiIndex = readoutId.phiIndex();
+  if (m_rowConnections.outsideReadout(phiIndex)) return readoutId;
+
+  int numConnected = m_rowConnections.numberOfConnectedCells(phiIndex);
+  if (!numConnected || static_cast<int>(number) >= numConnected) return SiCellId();
+
+  int newPhiIndex = m_rowConnections.connectedCell(phiIndex, number);
+  return SiCellId(newPhiIndex, readoutId.etaIndex());
+}  
+
+// Id of the readout cell for this diode.
+SiReadoutCellId
+PixelReadoutScheme::readoutIdOfCell(const SiCellId & cellId) const
+{
+  if (!cellId.isValid()) return SiReadoutCellId();
+
+  int phiIndex = cellId.phiIndex();
+  int newPhiIndex = phiIndex;
+  if (!m_rowConnections.outsideDiode(phiIndex)) {
+    newPhiIndex = m_rowConnections.readoutOfDiode(phiIndex);
+  } 
+  
+  return SiReadoutCellId(newPhiIndex, cellId.etaIndex()); 
+
+}
+
+SiCellId
+PixelReadoutScheme::gangedCell(const SiCellId & cellId) const
+{
+  if (!cellId.isValid()) return cellId;
+  int phiIndex = cellId.phiIndex();
+  if (m_rowConnections.outsideReadout(phiIndex)) return SiCellId(); // Invalid ID
+  int newPhiIndex = m_rowConnections.gangedCell(phiIndex); 
+  if (newPhiIndex == phiIndex) return SiCellId(); // Invalid ID
+  return SiCellId(newPhiIndex, cellId.etaIndex());
+}
+
+
+void PixelReadoutScheme::addMultipleRowConnection(const int lowerIndex,
+						  const std::vector<int> &connections)
+{
+ 
+  m_rowConnections.set(lowerIndex, connections);
+}
+
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_BarrelModuleSideDesign.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_BarrelModuleSideDesign.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..c699ed8363a09199792258dff0f8c51e1103eb10
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_BarrelModuleSideDesign.cxx
@@ -0,0 +1,279 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_BarrelModuleSideDesign.cxx
+//   Implementation file for class SCT_BarrelModuleSideDesign
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+//
+///////////////////////////////////////////////////////////////////
+// Version 1.0a 31/5/2001 Class creator tool
+// Version 1.0   9/6/2001 Szymon Gadomski
+// Version 1.0.1 20/6/2001 Alessandro Fornaini
+// 3/8/2001 Szymon Gadomski: restored correct calculation
+// in the new diode e.t.c., inActiveArea made fast
+// 15/08/2001 SG: works with new SiDiodesParameters, tested
+// 28/08/2001 SG: endsOfStrip method added
+// 29/10/2001 AF: phiMeasureSegment added
+// Modified: Grant Gorfine
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SCT_BarrelModuleSideDesign.h"
+#include "InDetReadoutGeometry/SiDiodesParameters.h"
+
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "CLHEP/Geometry/Vector3D.h"
+
+#include "TrkSurfaces/RectangleBounds.h"
+
+#include <cmath>
+
+namespace InDetDD {
+
+using std::abs;
+
+// Constructor with parameters:
+SCT_BarrelModuleSideDesign::SCT_BarrelModuleSideDesign(const double thickness,
+						       const int crystals,
+						       const int diodes,
+						       const int cells,
+						       const int shift,
+						       const bool swapStripReadout,
+						       InDetDD::CarrierType carrierType,
+						       const double stripPitch,
+						       const double stripLength,
+						       const double xEtaStripPatternCentre,
+						       const double xPhiStripPatternCentre,
+						       const double totalDeadLength,
+						       int readoutSide) :
+  SCT_ModuleSideDesign(thickness, 
+		       true, true, true, // phi,eta,depth axes symmetric
+		       crystals,diodes,cells,shift,swapStripReadout,carrierType,readoutSide),
+  m_stripPitch(stripPitch),
+  m_stripLength(stripLength),
+  m_xEtaStripPatternCentre(xEtaStripPatternCentre),
+  m_xPhiStripPatternCentre(xPhiStripPatternCentre),
+  m_totalDeadLength(totalDeadLength)
+{
+  m_xPhiAbsSize = 0.5*m_stripPitch*diodes;
+  if(crystals==1) {
+    m_xEtaAbsSizeLow = m_totalDeadLength/2;
+    if (m_xEtaAbsSizeLow == 0) m_xEtaAbsSizeLow = -1.0 * CLHEP::mm; // Anything negative will do
+    m_xEtaAbsSizeHigh = m_stripLength/2;
+  }
+  else if(crystals==2) {
+    m_xEtaAbsSizeLow = m_totalDeadLength/2;
+    m_xEtaAbsSizeHigh =  m_stripLength + m_totalDeadLength/2; 
+  } else {
+    std::cout << "wrong number of crystals!\n";
+    m_xEtaAbsSizeLow = m_xEtaAbsSizeHigh = m_xPhiAbsSize = 0.0;
+  }
+  
+  m_bounds = new Trk::RectangleBounds(0.5*width(), 0.5*length());
+}
+
+
+SCT_BarrelModuleSideDesign::~SCT_BarrelModuleSideDesign()
+{
+  delete m_bounds;
+}
+
+// Returns distance to nearest detector edge 
+// +ve = inside
+// -ve = outside
+void
+SCT_BarrelModuleSideDesign::distanceToDetectorEdge(const SiLocalPosition & localPosition,
+						   double & etaDist, double & phiDist) const
+{ 
+  // As the calculation is symmetric around 0,0 we only have to test it for one side.
+  double xEta = abs(localPosition.xEta() - m_xEtaStripPatternCentre);
+  double xPhi = abs(localPosition.xPhi() - m_xPhiStripPatternCentre);
+
+  double xEtaEdge = 0.5 * length();
+  double xPhiEdge = 0.5 * width();
+
+  // Distance to top/bottom
+  etaDist = xEtaEdge - xEta;
+  
+  // Distance to right/left edge
+  phiDist = xPhiEdge - xPhi;
+
+}
+
+
+bool SCT_BarrelModuleSideDesign::nearBondGap(const SiLocalPosition & localPosition, double etaTol) const
+{
+  // Symmetric around xEta = 0 so we can use absolute value.
+  if (m_totalDeadLength==0) return false; 
+  return ( abs(localPosition.xEta()) < 0.5*m_totalDeadLength + etaTol);
+}
+
+// check if the position is in active area
+bool SCT_BarrelModuleSideDesign::inActiveArea(const SiLocalPosition &chargePos, 
+					      bool checkBondGap) const 
+{
+  // in Phi
+  if (abs(chargePos.xPhi()-m_xPhiStripPatternCentre) > m_xPhiAbsSize) return false;
+
+  // in Eta
+  double relEta = fabs(chargePos.xEta() - m_xEtaStripPatternCentre);
+  if (relEta > m_xEtaAbsSizeHigh) return false;
+
+  // bond gap
+  return !(checkBondGap && (relEta < m_xEtaAbsSizeLow));
+}
+
+
+// distance to the nearest diode in units of pitch, from 0.0 to 0.5, 
+// this method should be fast as it is called for every surface charge
+// in the SCT_SurfaceChargesGenerator
+// an active area check, done in the Generator anyway, is removed here
+double SCT_BarrelModuleSideDesign::scaledDistanceToNearestDiode(const SiLocalPosition &chargePos) const
+{
+    double dstrip=fabs(chargePos.xPhi()-m_xPhiStripPatternCentre)/m_stripPitch;
+    dstrip=dstrip-static_cast<double>(int(dstrip))-0.5;
+    // the above -0.5 is because we have an even number of strips, centre of detector
+    // is in the middle of an interstrip gap
+    return fabs(dstrip);
+}
+
+std::pair<SiLocalPosition,SiLocalPosition> SCT_BarrelModuleSideDesign::endsOfStrip(const SiLocalPosition &position) const
+{
+    // this method returns the ends of the strip
+    // assume input xPhi
+
+    SiLocalPosition end1(m_xEtaStripPatternCentre+m_xEtaAbsSizeHigh,position.xPhi());
+    SiLocalPosition end2(m_xEtaStripPatternCentre-m_xEtaAbsSizeHigh,position.xPhi());
+    
+    std::pair<SiLocalPosition,SiLocalPosition> two_ends(end1,end2);
+    return two_ends;
+}
+
+
+double SCT_BarrelModuleSideDesign::length() const
+{
+  return crystals()*m_stripLength+m_totalDeadLength;
+}
+
+double SCT_BarrelModuleSideDesign::width() const
+{
+  return m_stripPitch*diodes();
+}
+
+double SCT_BarrelModuleSideDesign::minWidth() const
+{
+  return width();
+}
+
+double SCT_BarrelModuleSideDesign::maxWidth() const
+{
+  return width();
+}
+
+
+// method for stereo angle computation - returns a vector parallel to the 
+// strip being hit
+HepGeom::Vector3D<double> SCT_BarrelModuleSideDesign::phiMeasureSegment(const SiLocalPosition& ) const
+{
+  HepGeom::Vector3D<double> segment;
+  segment[etaAxis()]=1;
+  return segment;
+}
+
+// give length of dead area
+double SCT_BarrelModuleSideDesign::deadAreaLength() const
+{
+  return m_totalDeadLength;
+}  
+
+// give upper boundary of dead area (origin in module centre)
+double SCT_BarrelModuleSideDesign::deadAreaUpperBoundary() const
+{
+  return m_totalDeadLength/2;
+}
+// give lower boundary of dead area (origin in module centre)
+double SCT_BarrelModuleSideDesign::deadAreaLowerBoundary() const
+{
+  return -m_totalDeadLength/2;
+}
+
+
+
+SiLocalPosition 
+SCT_BarrelModuleSideDesign::localPositionOfCell(const SiCellId & cellId) const
+{
+
+  // NB. No check is made that cellId is valid or in the correct range.
+
+  int strip =  cellId.strip();
+
+  // center of cluster (in units of number of strips) from detector center
+  double clusterCenter = strip - 0.5*cells() + 0.5;
+
+  double xPhi=m_xPhiStripPatternCentre + m_stripPitch * clusterCenter;
+
+  // Return the position.
+  // no matter how many crystals we have, xEta of the position is in the centre!
+  return SiLocalPosition(m_xEtaStripPatternCentre, xPhi);
+}
+
+SiLocalPosition 
+SCT_BarrelModuleSideDesign::localPositionOfCluster(const SiCellId & cellId, int clusterSize) const
+{
+  // This method returns the position of the centre of the cluster starting at cellId.strip()
+  
+  // NB. No check is made that cellId is valid or in the correct range.
+
+  if (clusterSize < 1) clusterSize = 1;
+
+  int strip =  cellId.strip();
+
+  // center of cluster (in units of number of strips) from detector center
+  double clusterCenter = strip - 0.5*cells() + 0.5;
+  if (clusterSize>1) clusterCenter += 0.5 * (clusterSize-1);
+
+  double xPhi=m_xPhiStripPatternCentre + m_stripPitch * clusterCenter;
+
+  // Return the position.
+  // no matter how many crystals we have, xEta of the position is in the centre!
+  return SiLocalPosition(m_xEtaStripPatternCentre, xPhi);
+}
+
+
+SiDiodesParameters 
+SCT_BarrelModuleSideDesign::parameters(const SiCellId & cellId) const
+{
+  // NB. We treat the two crytals as one.
+  SiLocalPosition center=localPositionOfCell(cellId);
+  double xPhiSize=m_stripPitch;
+  double xEtaSize=2*m_xEtaAbsSizeHigh;
+  SiLocalPosition width(xEtaSize,xPhiSize);
+  return SiDiodesParameters(center,width);
+}
+
+SiCellId 
+SCT_BarrelModuleSideDesign::cellIdOfPosition(const SiLocalPosition & localPosition) const
+{
+  // NB We do not distinguish between the two crystals anymore.
+  // Check if we are in the active region. No bondgap check.
+  if (!inActiveArea(localPosition, false)) return SiCellId(); // return an invalid id
+  double xPhi=localPosition.xPhi();
+  double dstrip=(xPhi-m_xPhiStripPatternCentre)/m_stripPitch+0.5*diodes();
+  if (dstrip < 0) return SiCellId(); // return an invalid id
+  int strip = static_cast<int>(dstrip);
+  if (strip > diodes())  return SiCellId();// return an invalid id if strip # greater than number of diodes.
+  return SiCellId(strip-shift()); // strip numbering starts from first readout strip. 
+                                   // Those to the left will have negative numbers.
+
+}
+
+const Trk::SurfaceBounds & 
+SCT_BarrelModuleSideDesign::bounds() const
+{
+  return *m_bounds;
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_DetectorManager.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_DetectorManager.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..c3f95f8b098aeecf98c244b9ebb276338800dfcd
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_DetectorManager.cxx
@@ -0,0 +1,316 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/SCT_DetectorManager.h"
+#include "InDetIdentifier/SCT_ID.h"
+#include "Identifier/Identifier.h"
+#include "Identifier/IdentifierHash.h"
+#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
+#include "InDetReadoutGeometry/SiDetectorElement.h"
+#include "InDetReadoutGeometry/ExtendedAlignableTransform.h"
+#include "InDetReadoutGeometry/SCT_ModuleSideDesign.h"
+#include "StoreGate/StoreGateSvc.h"
+
+#include "GeoPrimitives/CLHEPtoEigenConverter.h"
+
+#include <iostream>
+namespace InDetDD {
+
+    const int FIRST_HIGHER_LEVEL = 2;
+
+    SCT_DetectorManager::SCT_DetectorManager( StoreGateSvc* detStore )
+        : SiDetectorManager(detStore, "SCT"),
+        m_idHelper(0)
+    {
+        //  
+        // Initialized the Identifier helper.
+        //
+        StatusCode sc = detStore->retrieve(m_idHelper, "SCT_ID");    
+        if (sc.isFailure() ) {
+            msg(MSG::ERROR) << "Could not retrieve SCT id helper" << endreq;
+        }
+        // Initialize the collections.
+        if (m_idHelper) {
+            m_elementCollection.resize(m_idHelper->wafer_hash_max());
+            m_alignableTransforms.resize(m_idHelper->wafer_hash_max());
+            m_moduleAlignableTransforms.resize(m_idHelper->wafer_hash_max()/2);
+        } 
+    }
+
+
+    SCT_DetectorManager::~SCT_DetectorManager()
+    {
+        // Clean up
+        SiDetectorElementCollection::iterator iter;
+        for (iter = m_elementCollection.begin(); iter != m_elementCollection.end(); ++iter){
+            delete *iter;
+        }
+
+        for (size_t i=0; i < m_volume.size(); i++) {
+            m_volume[i]->unref();
+        }
+
+        for (size_t j=0; j < m_higherAlignableTransforms.size(); j++){
+            AlignableTransformMap::iterator iterMap;    
+            for (iterMap = m_higherAlignableTransforms[j].begin(); 
+            iterMap != m_higherAlignableTransforms[j].end();
+            ++iterMap) {
+                delete iterMap->second;
+            }
+        }
+
+        for (size_t k=0; k < m_alignableTransforms.size(); k++){
+            delete m_alignableTransforms[k];
+        }
+
+        for (size_t l=0; l < m_moduleAlignableTransforms.size(); l++){
+            delete m_moduleAlignableTransforms[l];
+        }
+    }
+
+    unsigned int SCT_DetectorManager::getNumTreeTops() const
+    {
+        return m_volume.size(); 
+    }
+
+    PVConstLink SCT_DetectorManager::getTreeTop(unsigned int i) const
+    {
+        return m_volume[i];
+    }
+
+    void SCT_DetectorManager::addTreeTop(PVLink vol){
+        vol->ref();
+        m_volume.push_back(vol);
+    }
+
+
+    SiDetectorElement* SCT_DetectorManager::getDetectorElement(const Identifier & id) const
+    {  
+        // NB the id helpers implementation for getting a hash is not optimal.
+        // Essentially does a binary search.
+        // Make sure it is a wafer Id
+        Identifier waferId =  m_idHelper->wafer_id(id);
+        IdentifierHash idHash = m_idHelper->wafer_hash(waferId);
+        if (idHash.is_valid()) {
+            return m_elementCollection[idHash];
+        } else {
+            return 0;
+        }
+    }
+
+    SiDetectorElement* SCT_DetectorManager::getDetectorElement(const IdentifierHash & idHash) const
+    {
+        return m_elementCollection[idHash];
+    }
+
+    SiDetectorElement* SCT_DetectorManager::getDetectorElement(int barrel_endcap, int layer_wheel, int phi_module, int eta_module, int side) const
+    {
+        return getDetectorElement(m_idHelper->wafer_id(barrel_endcap, layer_wheel, phi_module, eta_module, side));
+    }
+
+
+    const SiDetectorElementCollection* SCT_DetectorManager::getDetectorElementCollection() const
+    { 
+        return &m_elementCollection;
+    }
+
+    SiDetectorElementCollection::const_iterator SCT_DetectorManager::getDetectorElementBegin() const
+    {
+        return m_elementCollection.begin();
+    }
+
+    SiDetectorElementCollection::const_iterator SCT_DetectorManager::getDetectorElementEnd() const
+    {
+        return m_elementCollection.end();
+    }
+
+
+    void SCT_DetectorManager::addDetectorElement(SiDetectorElement * element)
+    {
+        IdentifierHash idHash = element->identifyHash();
+        if (idHash >=  m_elementCollection.size())
+            throw std::runtime_error("SCT_DetectorManager: Error adding detector element.");
+        m_elementCollection[idHash] = element;
+    }
+
+    void SCT_DetectorManager::initNeighbours()
+    {
+        SiDetectorElementCollection::iterator iter;
+
+        // Loop over all elements and set the neighbours
+        for (iter = m_elementCollection.begin(); iter != m_elementCollection.end(); ++iter){
+
+            SiDetectorElement * element = *iter;
+            if (element) {
+
+                IdentifierHash idHash = element->identifyHash();
+                IdentifierHash idHashOther;
+
+                int result;
+                // If no neighbour, result != 0 in which case we leave neighbour as null
+                result = m_idHelper->get_next_in_eta(idHash, idHashOther);
+                if (result==0) element->setNextInEta(m_elementCollection[idHashOther]);
+
+                result = m_idHelper->get_prev_in_eta(idHash, idHashOther);
+                if (result==0) element->setPrevInEta(m_elementCollection[idHashOther]);
+
+                result = m_idHelper->get_next_in_phi(idHash, idHashOther);
+                if (result==0) element->setNextInPhi(m_elementCollection[idHashOther]);
+
+                result = m_idHelper->get_prev_in_phi(idHash, idHashOther);
+                if (result==0) element->setPrevInPhi(m_elementCollection[idHashOther]);
+
+                result = m_idHelper->get_other_side(idHash, idHashOther);
+                if (result==0) element->setOtherSide(m_elementCollection[idHashOther]);
+            }
+        }
+    }
+
+
+    const SCT_ID* SCT_DetectorManager::getIdHelper() const
+    {
+        return m_idHelper;
+    }
+
+
+    bool SCT_DetectorManager::setAlignableTransformDelta(int level, 
+                                                         const Identifier & id, 
+                                                         const Amg::Transform3D & delta,
+                                                         FrameType frame) const
+    {
+
+        if (level == 0) { // 0 - At the element level
+
+            // We retrieve it via a hashId.
+            IdentifierHash idHash = m_idHelper->wafer_hash(id);
+            if (!idHash.is_valid()) return false;
+
+            if (frame == InDetDD::global) { // global shift
+                // Its a global transform
+                return setAlignableTransformGlobalDelta(m_alignableTransforms[idHash], delta);
+
+            } else if (frame == InDetDD::local) { // local shift
+
+                const SiDetectorElement * element =  m_elementCollection[idHash];
+                if (!element) return false;
+
+                // Its a local transform
+                return setAlignableTransformLocalDelta(m_alignableTransforms[idHash], element->transform(), delta);
+
+            } else {   
+                // other not supported
+                msg(MSG::WARNING) << "Frames other than global or local are not supported." << endreq;
+                return false;
+            }
+
+        } else if (level == 1) { // module level
+
+            // We retrieve it via a hashId.
+            IdentifierHash idHash = m_idHelper->wafer_hash(id);
+            if (!idHash.is_valid()) return false;
+
+            int idModuleHash = idHash / 2;
+
+            if (idHash%2) {
+                msg(MSG::WARNING) << "Side 1 wafer id used for module id" << endreq;
+                return false;
+            }
+
+            if (frame == InDetDD::global) { // global shift
+                // Its a global transform
+                return setAlignableTransformGlobalDelta(m_moduleAlignableTransforms[idModuleHash], delta);
+            } else if (frame == InDetDD::local) { // local shift
+                const SiDetectorElement * element =  m_elementCollection[idHash];
+                if (!element) return false;
+                // Its a local transform
+                return setAlignableTransformLocalDelta(m_moduleAlignableTransforms[idModuleHash],element->defModuleTransform(), delta);
+
+            } else {
+                // other not supported
+                msg(MSG::WARNING) << "Frames other than global or local are not supported." << endreq;
+                return false;
+            }
+
+        } else { // higher level
+
+            if (frame != InDetDD::global) {
+                msg(MSG::WARNING) << "Non global shift at higher levels is not supported." << endreq;
+                return false;
+            }
+
+            int index = level - FIRST_HIGHER_LEVEL; // level 0 and 1 is treated separately.
+            if (index  >=  static_cast<int>(m_higherAlignableTransforms.size())) return false;
+
+            // We retrieve it from a map. 
+            AlignableTransformMap::const_iterator iter;    
+            iter = m_higherAlignableTransforms[index].find(id);
+            if (iter == m_higherAlignableTransforms[index].end()) return false;          
+
+            // Its a global transform
+            return setAlignableTransformGlobalDelta(iter->second, delta);
+        }
+
+    }
+
+    void SCT_DetectorManager::addAlignableTransform (int level, 
+                                                     const Identifier & id, 
+                                                     GeoAlignableTransform *transform,
+                                                     const GeoVPhysVol * child)
+    {
+        if (m_idHelper) {
+
+            const GeoVFullPhysVol * childFPV = dynamic_cast<const GeoVFullPhysVol *>(child);
+            if (!childFPV) { 
+                msg(MSG::ERROR) << "Child of alignable transform is not a full physical volume" 
+                    << endreq;
+            } else {
+                addAlignableTransform (level, id, transform, childFPV);
+            }
+        }
+    }
+
+    void SCT_DetectorManager::addAlignableTransform (int level, 
+                                                     const Identifier & id, 
+                                                     GeoAlignableTransform *transform,
+                                                     const GeoVFullPhysVol * child)
+    { 
+        if (m_idHelper) {
+            if (level == 0) { 
+                // Element
+                IdentifierHash idHash = m_idHelper->wafer_hash(id);
+                if (idHash.is_valid()) {
+                    m_alignableTransforms[idHash]= new ExtendedAlignableTransform(transform, child);
+                } 
+            } else if (level == 1) {
+                // Module
+                IdentifierHash idHash = m_idHelper->wafer_hash(id);
+                if (idHash.is_valid()) {
+                    m_moduleAlignableTransforms[idHash/2]=new ExtendedAlignableTransform(transform, child);
+                } 
+
+            } else {
+
+                // Higher levels are saved in a map. NB level=0,1 is treated above.     
+                int index = level - FIRST_HIGHER_LEVEL; // level 0 and 1 is treated separately.
+                if (index >= static_cast<int>(m_higherAlignableTransforms.size())) m_higherAlignableTransforms.resize(index+1); 
+                m_higherAlignableTransforms[index][id] = new ExtendedAlignableTransform(transform, child);
+            }  
+        }
+    }
+
+    bool
+        SCT_DetectorManager::identifierBelongs(const Identifier & id) const
+    {
+        return getIdHelper()->is_sct(id);
+    }
+
+
+    const SCT_ModuleSideDesign* SCT_DetectorManager::getSCT_Design(int i) const
+    {
+        return dynamic_cast<const SCT_ModuleSideDesign *>(getDesign(i));
+    }
+
+
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardFrameTransformation.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardFrameTransformation.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..518a47fdb04138d42a788e6177a89560d110c32a
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardFrameTransformation.cxx
@@ -0,0 +1,70 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ForwardFrameTransformation.cxx
+//   Implementation file for class SCT_ForwardFrameTransformation
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.4 09/7/2001 Alessandro Fornaini
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SCT_ForwardFrameTransformation.h"
+#include "InDetReadoutGeometry/SCT_ForwardPolarPosition.h"
+#include "InDetReadoutGeometry/SiLocalPosition.h"
+#include <cmath>
+
+namespace InDetDD {
+
+// Copy constructor:
+SCT_ForwardFrameTransformation::SCT_ForwardFrameTransformation(const SCT_ForwardFrameTransformation &frame) :
+  m_etaCenter(frame.m_etaCenter),
+  m_phiCenter(frame.m_phiCenter),
+  m_radius(frame.m_radius)
+{}
+
+// Constructor with parameters:
+SCT_ForwardFrameTransformation::SCT_ForwardFrameTransformation(const double etaCenter,const double phiCenter,const double radius) :
+  m_etaCenter(etaCenter),
+  m_phiCenter(phiCenter),
+  m_radius(radius)
+{ 
+  //check if parameters are consistent
+  if (m_radius<0) m_radius=0;
+}
+
+
+// Assignment operator:
+SCT_ForwardFrameTransformation &SCT_ForwardFrameTransformation::operator=(const SCT_ForwardFrameTransformation &frame)
+{
+  if (this!=&frame) {
+    m_etaCenter=frame.m_etaCenter;
+    m_phiCenter=frame.m_phiCenter;
+    m_radius=frame.m_radius;
+  } else {}
+  return *this;
+}
+
+
+// create a SCT_ForwardPolarPosition from a SiLocalPosition
+SCT_ForwardPolarPosition SCT_ForwardFrameTransformation::polarFromCartesian(const SiLocalPosition &cartesian) const
+{ 
+  const double deltaPhi = cartesian.xPhi()-m_phiCenter;
+  const double deltaEta = cartesian.xEta()-m_etaCenter+m_radius;
+  const double r = sqrt(deltaPhi*deltaPhi+deltaEta*deltaEta);
+  if (r<=0) return SCT_ForwardPolarPosition();
+  const double theta = asin((cartesian.xPhi()-m_phiCenter)/r);
+  return SCT_ForwardPolarPosition(r,theta);
+}
+
+// create a SiLocalPosition from a SCT_ForwardPolarPosition
+SiLocalPosition SCT_ForwardFrameTransformation::cartesianFromPolar(const SCT_ForwardPolarPosition &polar) const
+{
+  const double phi = m_phiCenter + polar.r()*sin(polar.theta());
+  const double eta = m_etaCenter + polar.r()*cos(polar.theta()) - m_radius;
+  return SiLocalPosition(eta, phi);
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardModuleSideDesign.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardModuleSideDesign.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..b7f21ec2df4daeba549ad22f8d32ca2f01f78285
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardModuleSideDesign.cxx
@@ -0,0 +1,285 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ForwardModuleSideDesign.cxx
+//   Implementation file for class SCT_ForwardModuleSideDesign
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.16 29/10/2001 Alessandro Fornaini
+// Modified: Grant Gorfine
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SCT_ForwardModuleSideDesign.h"
+#include "CLHEP/Units/SystemOfUnits.h"
+#include "CLHEP/Geometry/Vector3D.h"
+#include "InDetReadoutGeometry/SiDiodesParameters.h"
+#include "TrkSurfaces/TrapezoidBounds.h"
+
+namespace InDetDD {
+
+// Constructor with parameters:
+SCT_ForwardModuleSideDesign::SCT_ForwardModuleSideDesign(const double thickness,
+							 const int crystals,
+                                                         const int diodes,
+                                                         const int cells,
+                                                         const int shift,
+							 const bool swapStripReadout,
+                                                         InDetDD::CarrierType carrierType,
+							 const double radius1,
+                                                         const double halfHeight1,
+                                                         const double radius2,          
+                                                         const double halfHeight2, 
+                                                         const double step,
+                                                         const double etaCenter,
+                                                         const double phiCenter,
+							 int readoutSide) :
+  SCT_ModuleSideDesign(thickness,
+		       true,  // phi 
+		       false, // eta: For trapezoid we cant swap z (xEta) axis.
+		       true,  // depth
+		       crystals,diodes,cells,shift,swapStripReadout,carrierType,readoutSide),
+  m_geometry(radius1,halfHeight1,radius2,halfHeight2,diodes,step,crystals),
+  m_frame(etaCenter,phiCenter,radius1)
+{ 
+  if (crystals > 1) {
+    double radius = 0.5 * (radius1 + radius2 + halfHeight2 - halfHeight1);
+    m_frame=SCT_ForwardFrameTransformation(etaCenter,phiCenter,radius);
+  }
+  m_bounds = new Trk::TrapezoidBounds(0.5*minWidth(), 0.5*maxWidth(), 0.5*length());
+}
+
+// Destructor:
+SCT_ForwardModuleSideDesign::~SCT_ForwardModuleSideDesign()
+{
+  delete m_bounds;
+}
+
+void
+SCT_ForwardModuleSideDesign::distanceToDetectorEdge(const SiLocalPosition & localPosition,
+						   double & etaDist, double & phiDist) const
+{
+  m_geometry.distanceToDetectorEdge(localPosition,
+				    m_frame.polarFromCartesian(localPosition),
+				    etaDist, phiDist);
+}
+
+bool 
+SCT_ForwardModuleSideDesign::nearBondGap(const SiLocalPosition & localPosition, double etaTol) const
+{
+  return m_geometry.nearBondGap(localPosition, etaTol);
+}  
+
+// check if the position is in active area
+bool SCT_ForwardModuleSideDesign::inActiveArea(const SiLocalPosition &chargePos, bool checkBondGap) const
+{
+  //const SCT_ForwardPolarPosition polar=m_frame.polarFromCartesian(chargePos);
+  //return m_geometry.inActiveArea(m_frame.polarFromCartesian(chargePos));
+  return m_geometry.inActiveArea(chargePos, checkBondGap);
+}
+
+// give distance to the nearest diode in units of pitch, from 0.0 to 0.5, 
+// this method should be fast as it is called for every surface charge
+// in the SCT_SurfaceChargesGenerator
+double SCT_ForwardModuleSideDesign::scaledDistanceToNearestDiode(const SiLocalPosition &chargePos) const
+{
+  const SCT_ForwardPolarPosition polar=m_frame.polarFromCartesian(chargePos);
+  return m_geometry.scaledDistanceToNearestDiode(polar);;
+}
+
+
+// give the strip pitch (dependence on position needed for forward)  
+double SCT_ForwardModuleSideDesign::stripPitch(const SiLocalPosition & chargePos) const
+{
+  const SCT_ForwardPolarPosition polar=m_frame.polarFromCartesian(chargePos);
+  // No longer make inActive check
+  // if (!m_geometry.inActiveArea(polar)) return 0;
+  return m_geometry.stripPitch(polar);
+}
+
+// give the strip pitch (dependence on position needed for forward)  
+double SCT_ForwardModuleSideDesign::stripPitch() const
+{
+  // Use center.
+  const SCT_ForwardPolarPosition polarCenter(m_frame.radius(), 0);
+  // No longer make inActive check
+  //  if (!m_geometry.inActiveArea(polar)) return 0;
+  return m_geometry.stripPitch(polarCenter);
+}
+
+
+ 
+// this method returns the extremities of a strip passing by the point
+std::pair<SiLocalPosition,SiLocalPosition> SCT_ForwardModuleSideDesign::endsOfStrip(const SiLocalPosition &position) const
+{
+  const SCT_ForwardPolarPosition polarPosition = 
+    m_frame.polarFromCartesian(position);
+  const double theta = polarPosition.theta();
+  const double innerRadius = (m_geometry.radius1()-m_geometry.halfHeight1())/cos(theta);
+  double outerRadius;
+  if (crystals()==1) {
+    outerRadius = (m_geometry.radius1()+m_geometry.halfHeight1())/cos(theta);
+  } else {
+    outerRadius = (m_geometry.radius2()+m_geometry.halfHeight2())/cos(theta);
+  }    
+  const SCT_ForwardPolarPosition innerPointPolar = SCT_ForwardPolarPosition(innerRadius,theta);
+  const SCT_ForwardPolarPosition outerPointPolar = SCT_ForwardPolarPosition(outerRadius,theta);
+  const SiLocalPosition innerPoint = m_frame.cartesianFromPolar(innerPointPolar);
+  const SiLocalPosition outerPoint = m_frame.cartesianFromPolar(outerPointPolar);
+    
+  return std::pair<SiLocalPosition,SiLocalPosition>(innerPoint,outerPoint);
+}
+
+
+// method for stereo angle computation - returns a vector parallel to the 
+// strip being hit
+HepGeom::Vector3D<double> SCT_ForwardModuleSideDesign::phiMeasureSegment(const SiLocalPosition &position) const
+{
+  const SCT_ForwardPolarPosition secondPolarPosition(0,0);
+  const SiLocalPosition secondPosition = m_frame.cartesianFromPolar(secondPolarPosition); 
+  
+  HepGeom::Vector3D<double> notUnitVector;
+  notUnitVector[phiAxis()]=position.xPhi()-secondPosition.xPhi();
+  notUnitVector[etaAxis()]=position.xEta()-secondPosition.xEta();
+
+  return notUnitVector.unit();
+}
+	    
+double SCT_ForwardModuleSideDesign::length() const
+{
+  return m_geometry.length();
+}
+
+double SCT_ForwardModuleSideDesign::width() const
+{
+  return m_geometry.width();
+}
+
+double SCT_ForwardModuleSideDesign::minWidth() const
+{
+  return m_geometry.minWidth();
+}
+
+double SCT_ForwardModuleSideDesign::maxWidth() const
+{
+  return m_geometry.maxWidth();
+}
+
+double SCT_ForwardModuleSideDesign::deadAreaLength() const
+{
+  return m_geometry.deadAreaLength();
+}
+
+double SCT_ForwardModuleSideDesign::deadAreaUpperBoundary() const
+{
+  return m_geometry.deadAreaUpperBoundary();
+}
+
+double SCT_ForwardModuleSideDesign::deadAreaLowerBoundary() const
+{
+  return m_geometry.deadAreaLowerBoundary();
+} 
+
+//this method returns the position of the centre of a strips
+SiLocalPosition 
+SCT_ForwardModuleSideDesign::localPositionOfCell(const SiCellId & cellId) const
+{
+  // This method returns the position of the centre of the cell
+  
+  // NB. No check is made that cellId is valid or in the correct range.
+
+  int strip =  cellId.strip();
+
+  double clusterCenter = strip - 0.5*cells() + 0.5;
+
+  const double theta = m_geometry.angularPitch()*clusterCenter;
+  const double r =  radius() / cos(theta);
+
+  // positions in polar coordinates and then cartesian
+  const SCT_ForwardPolarPosition polarPosition(r, theta);
+  return m_frame.cartesianFromPolar(polarPosition);
+}
+
+//this method returns the position of the centre of the cluster of strips
+SiLocalPosition 
+SCT_ForwardModuleSideDesign::localPositionOfCluster(const SiCellId & cellId,
+						    int clusterSize) const
+{
+  // This method returns the position of the centre of the cluster starting at cellId.strip()
+  
+  // NB. No check is made that cellId is valid or in the correct range.
+
+  if (clusterSize < 1) clusterSize = 1;
+
+  int strip =  cellId.strip();
+
+  double clusterCenter = strip - 0.5*cells() + 0.5;
+  if (clusterSize>1) clusterCenter += 0.5 * (clusterSize-1);
+
+  const double theta = angularPitch()*clusterCenter;
+  const double r = radius() / cos(theta);
+
+  // positions in polar coordinates and then cartesian
+  const SCT_ForwardPolarPosition polarPosition(r,theta);
+  return m_frame.cartesianFromPolar(polarPosition);
+}
+
+SiDiodesParameters 
+SCT_ForwardModuleSideDesign::parameters(const SiCellId & cellId) const
+{
+  int strip =  cellId.strip();
+
+  double clusterCenter = strip - 0.5*cells() + 0.5;
+
+  const double theta = m_geometry.angularPitch()*clusterCenter;
+  const double r =  radius() / cos(theta);
+
+  // positions in polar coordinates and then cartesian
+  const SCT_ForwardPolarPosition polarPosition(r, theta);
+  SiLocalPosition center = m_frame.cartesianFromPolar(polarPosition);
+
+  // The strip is not rectangular put we return pitch at radius.
+  double stripWidth = angularPitch()*r;
+  double stripLength = length() / cos(theta);
+
+  SiLocalPosition width(stripLength, stripWidth);
+  return SiDiodesParameters(center, width);
+}
+
+
+SiCellId 
+SCT_ForwardModuleSideDesign::cellIdOfPosition(const SiLocalPosition & localPosition) const
+{
+  // NB We do not distinguish between the two crystals anymore.
+  // Check if we are in the active region. No bondgap check.
+  if (!inActiveArea(localPosition, false)) return SiCellId(); // return an invalid id
+
+  const SCT_ForwardPolarPosition polar = m_frame.polarFromCartesian(localPosition);
+  double theta = polar.theta();
+
+  double dstrip = theta/angularPitch() + 0.5*diodes();
+
+  if (dstrip < 0) return SiCellId(); // return an invalid id
+  int strip = static_cast<int>(dstrip);
+  if (strip > diodes())  return SiCellId();// return an invalid id if strip # greater 
+                                           // than number of diodes.
+  return SiCellId(strip-shift()); // strip numbering starts from first readout strip. 
+                                   // Those to the left will have negative numbers.
+}
+
+
+DetectorShape 
+SCT_ForwardModuleSideDesign::shape() const
+{
+  return InDetDD::Trapezoid;
+}
+
+const Trk::SurfaceBounds & 
+SCT_ForwardModuleSideDesign::bounds() const
+{
+  return *m_bounds;
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardModuleSideGeometry.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardModuleSideGeometry.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..f6298d8125f7a60a57d2e03da34a0a26cc25988b
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardModuleSideGeometry.cxx
@@ -0,0 +1,221 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ForwardModuleSideGeometry.cxx
+//   Implementation file for class SCT_ForwardModuleSideGeometry
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.6 09/7/2001 Alessandro Fornaini
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SCT_ForwardModuleSideGeometry.h"
+#include <cmath>
+
+namespace InDetDD {
+
+using std::abs;
+
+// Constructor with parameters:
+SCT_ForwardModuleSideGeometry::SCT_ForwardModuleSideGeometry(const double radius1,
+                                                             const double halfHeight1, 
+                                                             const double radius2,                    
+							     const double halfHeight2,
+                                                             const int strips,
+                                                             const double step,
+                                                             const int nCrystals ) :
+  m_radius1(radius1),
+  m_halfHeight1(halfHeight1),
+  m_radius2(radius2),
+  m_halfHeight2(halfHeight2),
+  m_strips(strips),
+  m_step(step) ,
+  m_nCrystals(nCrystals),
+  m_leftSide(step*strips*(-0.5)),
+  m_rightSide(step*strips*0.5),
+  m_upperSide1(radius1+halfHeight1),
+  m_lowerSide1(radius1-halfHeight1),
+  m_upperSide2(radius2+halfHeight2),
+  m_lowerSide2(radius2-halfHeight2)
+
+
+{
+  if (m_radius1<0) m_radius1=0.0;
+  if (m_halfHeight1<0) m_halfHeight1=0.0;
+  if (m_radius2<0) m_radius2=0.0;
+  if (m_halfHeight2<0) m_halfHeight2=0.0; 
+  if (m_strips<0) m_strips=0;
+  if (m_step<0) m_step=0.0;
+  if (m_nCrystals==0) m_nCrystals=1; 
+  if (m_nCrystals<2) {
+    m_radius2=0;
+    m_halfHeight2=0;
+  }
+
+  if (m_nCrystals==1) {
+    m_radius = m_radius1;
+    m_halfLength = m_halfHeight1;
+  } else {
+    m_radius = 0.5 * (m_radius1 + m_radius2 + m_halfHeight2 - m_halfHeight1);
+    m_halfLength = 0.5 * (m_radius2 + m_halfHeight2 - m_radius1 + m_halfHeight1);
+  }
+
+  m_tangent = tan(m_rightSide);
+
+  if (m_nCrystals==1) {
+    m_deadRegionUpper = 0; 
+    m_deadRegionLower = 0; 
+  } else {
+    m_deadRegionUpper = m_radius2 - m_halfHeight2 - m_radius;
+    m_deadRegionLower = m_radius1 + m_halfHeight1 - m_radius;
+  }
+  
+}
+
+
+
+// Returns distance to nearest detector edge 
+// +ve = inside
+// -ve = outside
+void
+SCT_ForwardModuleSideGeometry::distanceToDetectorEdge(const SiLocalPosition & localPosition,
+						      const SCT_ForwardPolarPosition & polar,
+						      double & etaDist, double & phiDist) const
+{ 
+
+  // Distance to top/bottom.
+  // Calculation symmetric around zero so we can use abs.
+  etaDist = m_halfLength - abs(localPosition.xEta());
+
+  // For phi distance use r*phiDiff.
+  phiDist = polar.r() * (m_rightSide - abs(polar.theta()));
+
+}
+
+
+bool SCT_ForwardModuleSideGeometry::nearBondGap(const SiLocalPosition & localPosition, double etaTol) const
+{
+  if (m_nCrystals == 1) return false; // No bond gap (eg for truncated middle detectors)
+  
+  return ((localPosition.xEta() < m_deadRegionUpper + etaTol ) &&
+	  (localPosition.xEta() > m_deadRegionLower - etaTol));
+    
+}  
+
+
+// check if the position is in active area
+bool SCT_ForwardModuleSideGeometry::inActiveArea(const SiLocalPosition &chargePos, 
+						 bool checkBondGap) const
+{
+  double xEta = chargePos.xEta();
+  double xPhi = chargePos.xPhi();
+
+  if (abs(xEta) > m_halfLength) return false;
+
+  if (checkBondGap && m_nCrystals > 1) {
+    // Check if in bond gap
+    if (xEta > m_deadRegionLower && xEta < m_deadRegionUpper) return false;
+  }
+  
+  // edge at xEta
+  double edge = (xEta + m_radius) * m_tangent;
+  
+  return (abs(xPhi) < edge);
+}
+
+// DEPRECATED
+// check if the position is in active area
+bool SCT_ForwardModuleSideGeometry::inActiveArea(const SCT_ForwardPolarPosition
+						 &polarPos ) const
+{
+  bool conditionTheta=false;
+  bool conditionEtaOne=false;
+  bool conditionEtaTwo=false;
+  if (polarPos.r()*cos(polarPos.theta())<m_upperSide1 &&
+      polarPos.r()*cos(polarPos.theta())>m_lowerSide1)
+    conditionEtaOne=true;
+  if (polarPos.r()*cos(polarPos.theta())<m_upperSide2 &&
+      polarPos.r()*cos(polarPos.theta())>m_lowerSide2)
+    conditionEtaTwo=true;
+  if (polarPos.theta()<m_rightSide &&
+      polarPos.theta()>m_leftSide) conditionTheta=true;
+  return (conditionEtaOne || conditionEtaTwo) && conditionTheta;
+}   
+
+// give the strip pitch (dependence on position needed for forward)  
+double SCT_ForwardModuleSideGeometry::stripPitch(const SCT_ForwardPolarPosition
+						 &polarPos) const
+{
+  return 2.0*polarPos.r()*fabs(sin(m_step*0.5));
+}
+
+// give distance to the nearest diode in units of pitch, from 0.0 to 0.5, 
+// this method should be fast as it is called for every surface charge
+// in the SCT_SurfaceChargesGenerator
+double SCT_ForwardModuleSideGeometry::scaledDistanceToNearestDiode(const SCT_ForwardPolarPosition &polarPos) const
+{
+  int stripIndex;
+  if (polarPos.theta()>0) stripIndex = 
+			    static_cast<int>(polarPos.theta()/m_step);
+  else stripIndex = static_cast<int>(polarPos.theta()/m_step-1);
+  const double thetaStrip = (stripIndex+0.5)*m_step;
+  const double pitch = 2.0*polarPos.r()*fabs(sin(m_step*0.5));
+  return polarPos.r()*fabs(sin(polarPos.theta()-thetaStrip))/pitch;
+}  
+
+// Method to calculate length of a module
+double SCT_ForwardModuleSideGeometry::length() const
+{
+  return 2 * m_halfLength;
+}
+
+// Method to calculate average width of a module
+double SCT_ForwardModuleSideGeometry::width() const
+{
+    return 2 * m_radius * m_tangent;
+}
+
+// Method to calculate minimum width of a module
+double SCT_ForwardModuleSideGeometry::minWidth() const
+{
+    return 2 * m_lowerSide1 * m_tangent;
+}
+
+// Method to calculate maximum width of a module
+double SCT_ForwardModuleSideGeometry::maxWidth() const
+{
+  if (m_nCrystals==1) {
+    return 2 * m_upperSide1 * m_tangent;
+  }
+  else {
+    return 2 * m_upperSide2 * m_tangent;
+  }
+}
+
+// give length of dead area
+double SCT_ForwardModuleSideGeometry::deadAreaLength() const
+{
+  if (m_nCrystals==1) { 
+    return 0;
+  } else {
+    return m_deadRegionUpper - m_deadRegionLower;
+  }
+  
+}
+
+
+// give upper boundary of dead area
+double SCT_ForwardModuleSideGeometry::deadAreaUpperBoundary() const
+{
+  return m_deadRegionUpper;
+}
+
+// give lower boundary of dead area
+double SCT_ForwardModuleSideGeometry::deadAreaLowerBoundary() const
+{
+  return m_deadRegionLower;
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardPolarPosition.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardPolarPosition.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..d41578573c5f32847cb8769482416b0bfe9c9e6f
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ForwardPolarPosition.cxx
@@ -0,0 +1,69 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ForwardPolarPosition.cxx
+//   Implementation file for class SCT_ForwardPolarPosition
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.0a 1/6/2001 Class creator tool
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SCT_ForwardPolarPosition.h"
+#include <new>
+#include <sstream>
+
+namespace InDetDD {
+
+// Implicit constructor:
+SCT_ForwardPolarPosition::SCT_ForwardPolarPosition() :
+  m_r(0),
+  m_theta(0)
+{}
+
+// Copy constructor:
+SCT_ForwardPolarPosition::SCT_ForwardPolarPosition(const SCT_ForwardPolarPosition &polar) :
+  m_r(polar.m_r),
+  m_theta(polar.m_theta)
+{}
+
+// Constructor with parameters:
+SCT_ForwardPolarPosition::SCT_ForwardPolarPosition(const double r,const double theta) :
+  m_r(r),
+  m_theta(theta)
+{
+  //check if parameters are consistent
+  if (m_r<0) m_r=0;
+}
+
+// Destructor:
+SCT_ForwardPolarPosition::~SCT_ForwardPolarPosition()
+{}
+
+// Assignment operator:
+SCT_ForwardPolarPosition &SCT_ForwardPolarPosition::operator=(const SCT_ForwardPolarPosition &polar)
+{
+  if (this!=&polar) {
+    m_r=polar.m_r;
+    m_theta=polar.m_theta;
+  } else {}
+  return *this;
+}
+
+//Comparison operator
+bool SCT_ForwardPolarPosition::operator==(const SCT_ForwardPolarPosition &polar) const
+{
+  return (m_r==polar.m_r && m_theta==polar.m_theta);
+}
+
+//Print method:
+std::string SCT_ForwardPolarPosition::print() const
+{
+  std::ostringstream out;
+  out<<"r = "<<m_r<<" theta = "<<m_theta;
+  return out.str();
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ModuleSideDesign.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ModuleSideDesign.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..7829b5a29a17d4a90fea7840168fcd315fa14542
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ModuleSideDesign.cxx
@@ -0,0 +1,92 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ModuleSideDesign.cxx
+//   Implementation file for class SCT_ModuleSideDesign
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.2 03/7/2001 Alessandro Fornaini
+// Modified: Grant Gorfine
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SCT_ModuleSideDesign.h"
+#include "Identifier/Identifier.h"
+
+namespace InDetDD {
+
+
+// Constructor with parameters: 
+//   local axis corresponding to eta direction   
+//   local axis corresponding to phi direction   
+//   local axis corresponding to depth direction 
+//   thickness of silicon sensor
+//   number of crystals within module side
+//   number of diodes within crystal
+//   number of cells within module side
+//   index of diode connected to cell with index 0
+
+
+SCT_ModuleSideDesign::SCT_ModuleSideDesign(const double thickness,
+					   const bool phiSymmetric,
+					   const bool etaSymmetric,
+					   const bool depthSymmetric,
+					   const int crystals,
+					   const int diodes,
+					   const int cells,
+					   const int shift,
+					   const bool swapStripReadout,
+					   InDetDD::CarrierType carrierType,
+					   int readoutSide) :
+  SiDetectorDesign(thickness, 
+		   phiSymmetric, etaSymmetric, depthSymmetric, 
+		   carrierType,
+		   readoutSide),
+  m_scheme(crystals,diodes,cells,shift),
+  m_swapStripReadout(swapStripReadout)
+{}
+
+
+
+// Destructor:
+SCT_ModuleSideDesign::~SCT_ModuleSideDesign()
+{}
+
+
+void SCT_ModuleSideDesign::neighboursOfCell(const SiCellId & cellId,
+					    std::vector<SiCellId> &neighbours) const
+{
+  neighbours.clear();
+  neighbours.reserve(2);
+  
+  if (!cellId.isValid()) return;
+
+  int strip = cellId.strip();
+  int stripM = strip - 1;
+  int stripP = strip + 1;
+  
+  if(stripM >= m_scheme.shift()) neighbours.push_back(stripM);
+  if(stripP < m_scheme.diodes()+m_scheme.shift()) neighbours.push_back(stripP);
+  
+}   
+
+// This method returns the position of the centre of a strip
+// ALTERNATIVE/PREFERED way is to use localPositionOfCell(const SiCellId & cellId) or 
+// rawLocalPositionOfCell method in SiDetectorElement.
+// DEPRECATED (but used in numerous places)
+SiLocalPosition SCT_ModuleSideDesign::positionFromStrip(const int stripNumber) const
+{
+  return localPositionOfCell(SiCellId(stripNumber));
+}
+
+/// Check if cell is in range. Returns the original cellId if it is in range, otherwise it returns an invalid id.
+SiCellId SCT_ModuleSideDesign::cellIdInRange(const SiCellId & cellId) const
+{
+  if (!cellId.isValid() || 
+      cellId.strip() <0 || cellId.strip() >= cells()) return SiCellId(); // Invalid
+  return cellId; 
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ReadoutScheme.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ReadoutScheme.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..bfbe2afd05be4cb6d851bdbc9bc0b58fa634cf43
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SCT_ReadoutScheme.cxx
@@ -0,0 +1,67 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SCT_ReadoutScheme.cxx
+//   Implementation file for class SCT_ReadoutScheme
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.0 23/5/2001 Alessandro Fornaini
+// Modified: Grant Gorfine
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SCT_ReadoutScheme.h"
+
+namespace InDetDD {
+
+// Copy constructor:
+SCT_ReadoutScheme::SCT_ReadoutScheme(const SCT_ReadoutScheme &scheme) :
+  m_crystals(scheme.m_crystals),
+  m_diodes(scheme.m_diodes),
+  m_cells(scheme.m_cells),
+  m_shift(scheme.m_shift)
+{}
+
+// Constructor with parameters:
+SCT_ReadoutScheme::SCT_ReadoutScheme(const int crystals,const int diodes,
+				     const int cells,const int shift) :
+  m_crystals(crystals),
+  m_diodes(diodes),
+  m_cells(cells),
+  m_shift(shift)
+{ 
+  //check if parameters are consistent
+  if (m_crystals<1) m_crystals=1;
+  if (m_diodes<0) m_diodes=0;
+  if (m_cells<0) m_cells=0;
+}
+
+// Assignment operator:
+SCT_ReadoutScheme &SCT_ReadoutScheme::operator=(const SCT_ReadoutScheme &scheme)
+{
+  if (this!=&scheme) {
+    m_crystals=scheme.m_crystals;
+    m_diodes=scheme.m_diodes;
+    m_cells=scheme.m_cells;
+    m_shift=scheme.m_shift;
+  } else {}
+  return *this;
+}
+
+
+// diode id -> readout id
+SiReadoutCellId 
+SCT_ReadoutScheme::readoutIdOfCell(const SiCellId & cellId) const
+{
+  // readout cell and diode numbering are the same.
+  // The range can be different due to the unconnected edge strips (if m_shift != 0).
+  if (!cellId.isValid()) return SiReadoutCellId(); // return an invalid id. 
+  int strip = cellId.strip();
+  // I think this should be >= m_cells. But need to check if this has any implications.
+  if (strip < 0 || strip > m_cells) return SiReadoutCellId(); // return an invalid id.
+  return SiReadoutCellId(strip);
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiCellId.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiCellId.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..8ac51f4d72dae3762adc9ce21699bb21367f9256
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiCellId.cxx
@@ -0,0 +1,15 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/SiCellId.h"
+
+std::ostream & operator << (std::ostream & os, const InDetDD::SiCellId & cellId)
+{
+  if (cellId.isValid()){
+    return os << "[" << cellId.phiIndex() << "." << cellId.etaIndex() << "]";
+  } else {
+    return os << "[INVALID]";
+  }
+}
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiCommonItems.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiCommonItems.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..0ad156edd241548d2cc9bbb7d7b19a2fec762fc8
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiCommonItems.cxx
@@ -0,0 +1,48 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/SiCommonItems.h"
+
+#include "InDetCondServices/ISiLorentzAngleSvc.h"
+
+namespace InDetDD {
+
+SiCommonItems::SiCommonItems(const AtlasDetectorID* const idHelper)
+  :  m_msg("SiDetectorElement"),
+     m_idHelper(idHelper), 
+     m_lorentzAngleSvcHandle("", "SiDetectorElement"),
+     m_lorentzAngleSvc(0),
+     m_lorentzAngleSvcInit(false)
+{}
+
+void   
+SiCommonItems::setSolenoidFrame(const HepGeom::Transform3D & transform) const
+{
+  m_solenoidFrame = transform;
+}
+
+void 
+SiCommonItems::setLorentzAngleSvc(const ServiceHandle<ISiLorentzAngleSvc> & lorentzAngleSvc)
+{
+  m_lorentzAngleSvcHandle = lorentzAngleSvc;
+}
+  
+ISiLorentzAngleSvc * 
+SiCommonItems::lorentzAngleSvc() const 
+{
+  if (!m_lorentzAngleSvcInit) {
+    if (!m_lorentzAngleSvcHandle.empty()) {
+      StatusCode sc = m_lorentzAngleSvcHandle.retrieve(); 
+      if (sc.isFailure()) {
+	msg(MSG::ERROR) << "InDetReadoutGeometry ERROR: Could not locate Lorentz angle service: " << m_lorentzAngleSvcHandle.name() << endreq;
+      }
+    }
+    m_lorentzAngleSvc =  &*m_lorentzAngleSvcHandle;
+    m_lorentzAngleSvcInit = true;
+  }
+  return m_lorentzAngleSvc;
+}
+
+
+} // End namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDetectorDesign.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDetectorDesign.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..28a6f368f6cc38261126f4c821794734ea6b2f75
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDetectorDesign.cxx
@@ -0,0 +1,102 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDetectorDesign.cxx
+//   Implementation file for class SiDetectorDesign
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 3.0 05/05/2001 David Calvet
+// Modified: Grant Gorfine
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SiDetectorDesign.h"
+#include "InDetReadoutGeometry/SiIntersect.h"
+
+namespace InDetDD {
+
+// Constructor with parameters:
+SiDetectorDesign::SiDetectorDesign(double thickness, 
+				   bool phiSymmetric,
+				   bool etaSymmetric,
+				   bool depthSymmetric,
+				   InDetDD::CarrierType carrierType,
+				   int readoutSide) :
+  m_etaAxis(zAxis),
+  m_phiAxis(yAxis),
+  m_depthAxis(xAxis),
+  m_thickness(thickness),
+  m_carrierType(carrierType),
+  m_phiSymmetric(phiSymmetric),
+  m_etaSymmetric(etaSymmetric),
+  m_depthSymmetric(depthSymmetric),
+  m_readoutSidePosDepth(readoutSide > 0)
+
+{}
+
+// Destructor:
+SiDetectorDesign::~SiDetectorDesign()
+{}
+
+SiIntersect
+SiDetectorDesign::inDetector(const SiLocalPosition & localPosition, double phiTol, double etaTol) const
+{
+  double etaDist=0;
+  double phiDist=0;
+  
+  distanceToDetectorEdge(localPosition, etaDist, phiDist);
+  
+  SiIntersect state;
+ 
+  if (phiDist < -phiTol || etaDist < -etaTol) {
+    state.setOut();
+    return state;
+  }
+
+  if (phiDist > phiTol && etaDist > etaTol) {
+    state.setIn();
+    return state;
+  }
+  
+  // Near boundary.
+  state.setNearBoundary();
+  return state;
+}
+
+
+
+void SiDetectorDesign::setSymmetry(bool phiSymmetric, bool etaSymmetric, bool depthSymmetric)
+{
+  // Flags can be changed from true to false but not false to true.
+  if (m_phiSymmetric) {
+    m_phiSymmetric = phiSymmetric;
+  } else if (phiSymmetric) {
+    std::cout << "SiDetectorDesign: WARNING! Attempt to allow swapping of xPhi axis direction ignored." 
+	      << std::endl;
+  }
+  
+  if (m_etaSymmetric) {
+    m_etaSymmetric = etaSymmetric;
+  } else if (etaSymmetric) {
+      std::cout << "SiDetectorDesign: WARNING! Attempt to allow swapping of xEta axis direction ignored." 
+		<< std::endl;
+  }
+
+  if (m_depthSymmetric) {
+    m_depthSymmetric = depthSymmetric;
+  } else if (depthSymmetric) {
+      std::cout << "SiDetectorDesign: WARNING! Attempt to allow swapping of xDepth axis direction ignored." 
+		<< std::endl;
+  }
+}
+
+DetectorShape 
+SiDetectorDesign::shape() const
+{
+  // Default is Box. 
+  return InDetDD::Box;
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDetectorElement.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDetectorElement.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..75527e3453e11d6e88022d9509aa62988eb9ebd6
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDetectorElement.cxx
@@ -0,0 +1,1114 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDetectorElement.cxx
+//   Implementation file for class SiDetectorElement
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Authors: Grant Gorfine
+// Based on version developed by David Calvet.
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SiDetectorElement.h"
+
+#include "InDetIdentifier/PixelID.h"
+#include "InDetIdentifier/SCT_ID.h"
+
+#include "GeoModelKernel/GeoVFullPhysVol.h"
+#include "AtlasDetDescr/AtlasDetectorID.h"
+
+#include "CLHEP/Geometry/Point3D.h"
+#include "CLHEP/Geometry/Vector3D.h"
+#include "CLHEP/Vector/ThreeVector.h"
+#include "CLHEP/Units/PhysicalConstants.h" // for M_PI
+#include "CLHEP/Units/SystemOfUnits.h" 
+//#include "GeoPrimitives/CLHEPtoEigenConverter.h"
+
+#include "InDetReadoutGeometry/SiCellId.h"
+#include "InDetReadoutGeometry/SiReadoutCellId.h"
+
+#include "InDetReadoutGeometry/SiCommonItems.h"
+
+#include "TrkSurfaces/PlaneSurface.h"
+#include "TrkSurfaces/SurfaceBounds.h"
+
+#include "InDetCondServices/ISiLorentzAngleSvc.h"
+
+
+
+#include <cmath>
+#include <cassert>
+
+namespace InDetDD {
+
+using Trk::distPhi;
+using Trk::distEta;
+using Trk::distDepth;
+
+// Constructor with parameters:
+SiDetectorElement::SiDetectorElement(const Identifier &id,
+				     const SiDetectorDesign *design,
+				     const GeoVFullPhysVol *geophysvol,
+				     SiCommonItems * commonItems) :
+  TrkDetElementBase(geophysvol),
+  m_id(id),
+  m_design(design),
+  m_commonItems(commonItems),
+  m_nextInEta(0),
+  m_prevInEta(0),
+  m_nextInPhi(0),
+  m_prevInPhi(0),
+  m_otherSide(0),
+  m_cacheValid(false),
+  m_conditionsCacheValid(false),
+  m_firstTime(true),
+  m_isStereo(false),
+  m_tanLorentzAnglePhi(0),
+  m_tanLorentzAngleEta(0),
+  m_lorentzCorrection(0),
+  m_surface(0)
+{
+  commonConstructor();
+}
+
+void
+SiDetectorElement::commonConstructor() 
+{
+  
+  if (!m_id.is_valid()) throw std::runtime_error("SiDetectorElement: Invalid identifier");
+
+  // Set booleans for wether we are pixel/sct barrel/endcap
+  m_isPixel = getIdHelper()->is_pixel(m_id);
+  if (!m_isPixel && !getIdHelper()->is_sct(m_id)){
+    if(msgLvl(MSG::WARNING)) msg(MSG::WARNING) << "Element id is not for pixel or SCT" << endreq;
+  }
+
+  // Set IdHash. Also set m_isBarrel.
+  m_isDBM=false; 
+  if (isPixel()) {
+    const PixelID* pixelId = dynamic_cast<const PixelID *>(getIdHelper());
+    if(pixelId){
+      m_isBarrel = pixelId->is_barrel(m_id);
+      m_idHash = pixelId->wafer_hash(m_id);
+
+      if(pixelId->is_dbm(m_id)){
+	m_isBarrel=false; 
+	m_isDBM=true; 
+      } 
+    }
+  } else {
+    const SCT_ID* sctId = dynamic_cast<const SCT_ID *>(getIdHelper()); 
+    if(sctId){
+      m_isBarrel = sctId->is_barrel(m_id);
+      m_idHash = sctId->wafer_hash(m_id);
+    }
+  }
+  
+  if (!m_idHash.is_valid()) throw std::runtime_error("SiDetectorElement: Unable to set IdentifierHash");
+
+  // Increase the reference count of the SiDetectorDesign objects.
+  m_design->ref();
+
+  // Increase the reference count of the SiCommonItems objects.
+  m_commonItems->ref();
+
+  // Should we reference count the geophysvol as well?
+
+}
+
+
+// Destructor:
+SiDetectorElement::~SiDetectorElement()
+{
+  delete m_surface;
+
+  // The design is reference counted so that it will not be deleted until the last element is deleted.
+  m_design->unref();
+
+  m_commonItems->unref();
+
+}
+
+void 
+SiDetectorElement::updateCache() const
+{
+
+  m_cacheValid = true;
+
+  bool firstTimeTmp = m_firstTime;
+  m_firstTime = false;
+  
+  const HepGeom::Transform3D & geoTransform = transformHit();
+
+  m_centerCLHEP = geoTransform * HepGeom::Point3D<double>(0,0,0);
+  
+  m_center = Amg::Vector3D(m_centerCLHEP[0],m_centerCLHEP[1],m_centerCLHEP[2]);
+  
+  //
+  // Determine directions depth, eta and phi axis in reconstruction local frame
+  // ie depth away from interaction point
+  //    phi in direction of increasing phi
+  //    eta in direction of increasing z in barrel, and increasing r in endcap
+  //
+    
+  // depthAxis, phiAxis, and etaAxis are defined to be x,y,z respectively for all detectors for hit local frame.
+  // depthAxis, phiAxis, and etaAxis are defined to be z,x,y respectively for all detectors for reco local frame.
+  static const HepGeom::Vector3D<double> localAxes[3] = {
+    HepGeom::Vector3D<double>(1,0,0),
+    HepGeom::Vector3D<double>(0,1,0),
+    HepGeom::Vector3D<double>(0,0,1)
+  };
+
+  static const HepGeom::Vector3D<double> & localHitPhiAxis = localAxes[hitPhi];     // Defined to be same as y axis
+  static const HepGeom::Vector3D<double> & localHitEtaAxis = localAxes[hitEta];     // Defined to be same as z axis
+  static const HepGeom::Vector3D<double> & localHitDepthAxis = localAxes[hitDepth]; // Defined to be same as x axis
+  
+  static const HepGeom::Vector3D<double> & localRecoPhiAxis = localAxes[distPhi];     // Defined to be same as x axis
+  static const HepGeom::Vector3D<double> & localRecoEtaAxis = localAxes[distEta];     // Defined to be same as y axis
+  static const HepGeom::Vector3D<double> & localRecoDepthAxis = localAxes[distDepth]; // Defined to be same as z axis
+  
+  // We only need to calculate the rough orientation once.
+  //For it to change would require extreme unrealistic misalignment changes.
+  if (firstTimeTmp) {
+    // Determine the unit vectors in global frame
+    HepGeom::Vector3D<double> globalDepthAxis(geoTransform * localHitDepthAxis); 
+    HepGeom::Vector3D<double> globalPhiAxis  (geoTransform * localHitPhiAxis); 
+    HepGeom::Vector3D<double> globalEtaAxis  (geoTransform * localHitEtaAxis); 
+    
+    // Set the nominal eta,phi,normal and check the actual ones are close to these and determine the sign.
+  
+    // unit radial vector 
+    HepGeom::Vector3D<double> unitR(m_center.x(), m_center.y(), 0);
+    // TODO: Check if r = 0.
+    unitR.setMag(1);
+  
+    HepGeom::Vector3D<double> nominalEta;
+    HepGeom::Vector3D<double> nominalNormal;
+    HepGeom::Vector3D<double> nominalPhi(-unitR.y(), unitR.x(), 0);
+  
+    // In Barrel like geometry, the etaAxis is along increasing z, and normal is in increasing radial direction.
+    // In Endcap like geometry, the etaAxis is along increasing r, and normal is in decreasing z direction,
+    // We base whether it is barrel like or endcap like by the orientation of the local z axis of the 
+    // the element. This allows the use of endcap identifiers in a TB setup. A warning message is issued however if
+    // the orientation and identifier are not consistent (ie a barrel like orientation with an endcap identifier).
+
+    bool barrelLike = true;
+    nominalEta.setZ(1);
+    if (std::abs(globalEtaAxis.dot(nominalEta)) < 0.5) { // Check that it is in roughly the right direction.
+      barrelLike = false;
+    }   
+
+    if (isBarrel() && !barrelLike) {      
+      if(msgLvl(MSG::WARNING)) msg(MSG::WARNING) << "Element has endcap like orientation with barrel identifier." 
+						 << endreq;
+    } else if (!isBarrel() && barrelLike) {
+      if(msgLvl(MSG::WARNING)) msg(MSG::WARNING) << "Element has barrel like orientation with endcap identifier."
+						 << endreq;
+    }
+    
+    if (barrelLike) {
+      nominalEta.setZ(1);
+      nominalNormal =  unitR;
+    } else { // endcap like
+      nominalNormal.setZ(-1);
+      nominalEta = unitR; 
+    }
+
+    // Determine if axes are to have there directions swapped.
+
+    //
+    // Depth axis.
+    //
+    double depthDir = globalDepthAxis.dot(nominalNormal);
+    m_depthDirection = true;
+    if (depthDir < 0) {
+      if (m_design->depthSymmetric()) {
+	m_depthDirection = false;
+      } else {
+	if(msgLvl(MSG::WARNING)) msg(MSG::WARNING) << "Unable to swap local depth axis." << endreq;
+      }
+    }
+    if (std::abs(depthDir) < 0.5) { // Check that it is in roughly the right direction.
+      msg(MSG::ERROR) << "Orientation of local depth axis does not follow correct convention." << endreq;
+      // throw std::runtime_error("Orientation of local depth axis does not follow correct convention.");
+      m_depthDirection = true; // Don't swap.
+    }
+    
+    //
+    // Phi axis
+    //
+    double phiDir = globalPhiAxis.dot(nominalPhi);
+    m_phiDirection = true;
+    if (phiDir < 0) {
+      if (m_design->phiSymmetric()) {
+	m_phiDirection = false;
+      } else {
+	if(msgLvl(MSG::WARNING)) msg(MSG::WARNING) << "Unable to swap local xPhi axis." << endreq;
+      }
+    }
+    
+    if (std::abs(phiDir) < 0.5) { // Check that it is in roughly the right direction.
+      msg(MSG::ERROR) << "Orientation of local xPhi axis does not follow correct convention." << endreq;
+      // throw std::runtime_error("Orientation of local xPhi axis does not follow correct convention.");
+      m_phiDirection = true; // Don't swap.
+    }
+    
+    //
+    // Eta axis
+    //
+    double etaDir = globalEtaAxis.dot(nominalEta);
+    m_etaDirection = true;
+    if (etaDir < 0) {
+      if (m_design->etaSymmetric()) {
+	m_etaDirection = false;
+      } else {
+	if(msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "Unable to swap local xEta axis." << endreq;
+      }
+    }
+    if (std::abs(etaDir) < 0.5) { // Check that it is in roughly the right direction.
+      msg(MSG::ERROR) << "Orientation of local xEta axis does not follow correct convention." << endreq;
+      // throw std::runtime_error("Orientation of local xEta axis does not follow correct convention.");
+      m_etaDirection = true; // Don't swap
+    }   
+  } // end if (m_firstTime)
+  
+
+  m_transformCLHEP = geoTransform * recoToHitTransform();
+  //m_transform = m_commonItems->solenoidFrame() * geoTransform * recoToHitTransform();
+  m_transform = Amg::CLHEPTransformToEigen(m_transformCLHEP);
+  
+  // Check that local frame is right-handed. (ie transform has no reflection)
+  // This can be done by checking that the determinant is >0.
+  if (firstTimeTmp) { // Only need to check this once.
+    HepGeom::Transform3D & t = m_transformCLHEP;
+    double det = t(0,0) * (t(1,1)*t(2,2) - t(1,2)*t(2,1)) -
+                 t(0,1) * (t(1,0)*t(2,2) - t(1,2)*t(2,0)) +
+                 t(0,2) * (t(1,0)*t(2,1) - t(1,1)*t(2,0));
+    if (det < 0) {
+      if (m_design->depthSymmetric()) {
+	if(msgLvl(MSG::DEBUG))  
+	  msg(MSG::DEBUG) << "Local frame is left-handed, Swapping depth axis to make it right handed." 
+			  << endreq;
+	m_depthDirection = !m_depthDirection;
+	m_transformCLHEP = geoTransform * recoToHitTransform();
+	 m_transform = Amg::CLHEPTransformToEigen(m_transformCLHEP);
+	//m_transform = m_commonItems->solenoidFrame() * geoTransform * recoToHitTransform();
+       } else {
+	 if(msgLvl(MSG::WARNING)) msg(MSG::WARNING) << "Local frame is left-handed." << endreq;
+      }
+    }
+  }
+  
+  
+  // Initialize various cached members
+  // The unit vectors
+  m_normalCLHEP = m_transformCLHEP * localRecoDepthAxis;
+  m_normal = Amg::Vector3D( m_normalCLHEP[0], m_normalCLHEP[1], m_normalCLHEP[2]);
+  
+
+  m_phiAxisCLHEP = m_transformCLHEP * localRecoPhiAxis;
+  m_etaAxisCLHEP = m_transformCLHEP * localRecoEtaAxis;
+
+  m_phiAxis = Amg::Vector3D(m_phiAxisCLHEP[0],m_phiAxisCLHEP[1],m_phiAxisCLHEP[2]);
+  m_etaAxis = Amg::Vector3D(m_etaAxisCLHEP[0],m_etaAxisCLHEP[1],m_etaAxisCLHEP[2]);
+
+  getExtent(m_minR, m_maxR, m_minZ, m_maxZ, m_minPhi, m_maxPhi);
+
+  // Determin isStereo
+  if (firstTimeTmp) {
+    if (isSCT() && m_otherSide) {
+      double sinStereoThis = std::abs(sinStereo());
+      double sinStereoOther = std::abs(m_otherSide->sinStereo());
+      if (sinStereoThis == sinStereoOther) {
+	// If they happend to be equal then set side0 as axial and side1 as stereo.
+	const SCT_ID* sctId = dynamic_cast<const SCT_ID *>(getIdHelper()); 
+        if(sctId){
+	  int side = sctId->side(m_id);
+	  m_isStereo = (side == 1);
+	}
+      } else {
+	// set the stereo side as the one with largest absolute sinStereo. 
+	m_isStereo = (sinStereoThis > sinStereoOther);
+      }
+    } else {
+      m_isStereo = false;
+    }
+  }    
+  
+}
+
+
+void 
+SiDetectorElement::updateConditionsCache() const
+{
+  m_conditionsCacheValid = true;
+
+  // 
+  // Lorentz Angle related stuff
+  // 
+
+  if (m_commonItems->lorentzAngleSvc()) {
+    m_tanLorentzAnglePhi = m_commonItems->lorentzAngleSvc()->getTanLorentzAngle(m_idHash);
+    m_tanLorentzAngleEta = m_commonItems->lorentzAngleSvc()->getTanLorentzAngleEta(m_idHash);
+    m_lorentzCorrection = m_commonItems->lorentzAngleSvc()->getLorentzShift(m_idHash);
+  } else {
+    // Set to zero
+    m_tanLorentzAnglePhi = 0;
+    m_tanLorentzAngleEta = 0;
+    m_lorentzCorrection =  0;
+  }
+}
+
+
+const HepGeom::Transform3D &
+SiDetectorElement::transformHit() const
+{
+  return getMaterialGeom()->getAbsoluteTransform();
+}
+
+const Amg::Transform3D &
+SiDetectorElement::transform() const
+{
+  if (!m_cacheValid) updateCache();
+  return m_transform;
+}
+
+const HepGeom::Transform3D &
+SiDetectorElement::transformCLHEP() const
+{
+  //if (!m_cacheValid) updateCache();
+  //return m_transform;
+  //stuff to get the CLHEP version of the local to global transform.
+  if (!m_cacheValid) updateCache();
+  return m_transformCLHEP;
+
+}
+const HepGeom::Transform3D 
+SiDetectorElement::defTransformCLHEP() const
+{
+  return getMaterialGeom()->getDefAbsoluteTransform() * recoToHitTransform();
+}  
+   
+const Amg::Transform3D 
+SiDetectorElement::defTransform() const
+{
+  HepGeom::Transform3D tmpTransform =  getMaterialGeom()->getDefAbsoluteTransform() * recoToHitTransform();
+  return Amg::CLHEPTransformToEigen(tmpTransform);
+}
+
+const HepGeom::Transform3D 
+SiDetectorElement::recoToHitTransform() const
+{
+
+  // Determine the reconstruction local (LocalPosition) to global transform.
+
+  if (m_firstTime) updateCache();
+
+  // global = transform * recoLocal
+  //        = transfromHit * hitLocal
+  //        = transformHit * recoToHitTransform * recoLocal
+  // recoToHitTransform takes recoLocal to hitLocal
+  // x,y,z -> y,z,x 
+  // equiv to a rotation around Y of 90 deg followed by a rotation around X of 90deg
+  // 
+  // recoToHit is static as it needs to be calculated once only.
+  // We use the HepGeom::Transform3D constructor which takes one coordinates system to another where the
+  // coordinate system is defined by it center and two axes.
+  // distPhi, distEta are the reco local axes and hitPhi and hitEta are the hit local axes.
+  // It assume phi, eta, depth makes a right handed system which is the case.
+  static const HepGeom::Vector3D<double> localAxes[3] = {
+    HepGeom::Vector3D<double>(1,0,0),
+    HepGeom::Vector3D<double>(0,1,0),
+    HepGeom::Vector3D<double>(0,0,1)
+  };
+  static const HepGeom::Transform3D recoToHit(HepGeom::Point3D<double>(0,0,0),localAxes[distPhi],localAxes[distEta],
+					HepGeom::Point3D<double>(0,0,0),localAxes[hitPhi],localAxes[hitEta]);
+  
+  // Swap direction of axis as appropriate
+  CLHEP::Hep3Vector scale(1,1,1);
+  if (!m_phiDirection)   scale[distPhi]   = -1;
+  if (!m_etaDirection)   scale[distEta]   = -1;
+  if (!m_depthDirection) scale[distDepth] = -1;
+  return recoToHit * HepGeom::Scale3D(scale[0],scale[1],scale[2]);
+}
+
+const Amg::Transform3D &
+SiDetectorElement::moduleTransform() const
+{
+  return  (isModuleFrame()) ?  transform() : m_otherSide->transform();
+}
+
+  Amg::Transform3D
+  SiDetectorElement::defModuleTransform() const
+{
+ return  (isModuleFrame()) ? defTransform() : m_otherSide->defTransform();
+}  
+
+
+// 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();
+  }
+}
+
+Amg::Transform3D 
+SiDetectorElement::localToModuleTransform() const
+{
+  if (isModuleFrame()) {
+    return Amg::Transform3D(); // Identity
+  } else {
+    return  m_otherSide->transform().inverse() * transform();
+  }
+}
+      
+
+bool 
+SiDetectorElement::isModuleFrame() const
+{
+  // The module frame is the axial side.
+  // NB isStereo returns false for the pixel and so
+  // isModuleFrame is always true for the pixel.
+
+  return !isStereo();
+}
+
+
+const Amg::Vector3D & 
+SiDetectorElement::center() const
+{
+  if (!m_cacheValid) updateCache();
+  return m_center;
+}
+
+const Amg::Vector3D & 
+SiDetectorElement::normal() const
+{
+  if (!m_cacheValid) updateCache();
+  return m_normal;
+}
+
+const HepGeom::Vector3D<double> & 
+SiDetectorElement::etaAxisCLHEP() const
+{
+  if (!m_cacheValid) updateCache();
+  return m_etaAxisCLHEP;
+}
+
+const HepGeom::Vector3D<double> & 
+SiDetectorElement::phiAxisCLHEP() const
+{
+  if (!m_cacheValid) updateCache();
+  return m_phiAxisCLHEP;
+}
+
+const Amg::Vector3D & 
+SiDetectorElement::etaAxis() const
+{
+  if (!m_cacheValid) updateCache();
+  return m_etaAxis;
+}
+
+const Amg::Vector3D & 
+SiDetectorElement::phiAxis() const
+{
+  if (!m_cacheValid) updateCache();
+  return m_phiAxis;
+}
+
+Amg::Vector2D
+SiDetectorElement::hitLocalToLocal(double xEta, double xPhi) const  // Will change order to phi,eta
+{
+  if (!m_cacheValid) updateCache(); 
+  if (!m_etaDirection) xEta = -xEta;
+  if (!m_phiDirection) xPhi = -xPhi;
+  return Amg::Vector2D(xPhi, xEta);
+}
+
+HepGeom::Point3D<double>
+SiDetectorElement::hitLocalToLocal3D(const HepGeom::Point3D<double> & hitPosition) const
+{
+  // Equiv to transform().inverse * transformHit() * hitPosition
+  if (!m_cacheValid) updateCache(); 
+  double xDepth = hitPosition[hitDepth];
+  double xPhi = hitPosition[hitPhi];
+  double xEta = hitPosition[hitEta];
+  if (!m_depthDirection) xDepth = -xDepth;
+  if (!m_phiDirection) xPhi = -xPhi;
+  if (!m_etaDirection) xEta = -xEta;
+  return HepGeom::Point3D<double>(xPhi, xEta, xDepth);
+}
+
+
+bool SiDetectorElement::isPixel() const
+{
+  return m_isPixel;
+}
+
+bool SiDetectorElement::isSCT() const
+{
+  return !m_isPixel;
+}
+
+bool SiDetectorElement::isBarrel() const
+{
+  return m_isBarrel;
+}
+
+bool SiDetectorElement::isDBM() const 
+{ 
+  return m_isDBM; 
+} 
+
+bool SiDetectorElement::isBlayer() const
+{
+  if (isPixel() && isBarrel()) {
+    const PixelID* p_pixelId = static_cast<const PixelID *>(getIdHelper());
+    return (0==p_pixelId->layer_disk(m_id));
+  } else {
+    return false;
+  }
+} 
+
+bool SiDetectorElement::isInnermostPixelLayer() const
+{
+  if (isPixel() && isBarrel()) {
+    const PixelID* p_pixelId = static_cast<const PixelID *>(getIdHelper());
+    return (0==p_pixelId->layer_disk(m_id));
+  } else {
+    return false;
+  }
+}  
+
+bool SiDetectorElement::isNextToInnermostPixelLayer() const
+{
+  if (isPixel() && isBarrel()) {
+    const PixelID* p_pixelId = static_cast<const PixelID *>(getIdHelper());
+    return (1==p_pixelId->layer_disk(m_id));
+  } else {
+    return false;
+  }
+}  
+
+
+  Amg::Vector2D SiDetectorElement::correctLocalPosition(const Amg::Vector2D &position) const
+{
+  Amg::Vector2D correctedPosition(position);
+  correctedPosition[distPhi] += getLorentzCorrection();
+  return correctedPosition;
+}
+
+// compute sin(tilt angle) at center:
+double SiDetectorElement::sinTilt() const
+{
+  if (!m_cacheValid) updateCache();
+
+  // Tilt is defined as the angle between a refVector and the sensor normal.
+  // In barrel refVector = unit vector radial.
+  // in endcap it is assumed there is no tilt.
+  // sinTilt = (refVector cross normal) . z
+
+  // tilt angle is not defined for the endcap
+  if (isEndcap()) return 0;
+  
+  // Angle between normal and radial vector.
+  // HepGeom::Vector3D<double> refVector(m_center.x(), m_center.y(), 0);
+  // return (refVector.cross(m_normal)).z()/refVector.mag();
+  // or the equivalent
+  return (m_center.x() * m_normal.y() - m_center.y() * m_normal.x()) / m_center.perp();
+}
+
+  double SiDetectorElement::sinTilt(const Amg::Vector2D &localPos) const
+{
+  if (!m_cacheValid) updateCache();
+
+  // tilt angle is not defined for the endcap
+  if (isEndcap()) return 0;
+
+  HepGeom::Point3D<double> point=globalPositionCLHEP(localPos);
+  return sinTilt(point);
+}
+
+double SiDetectorElement::sinTilt(const HepGeom::Point3D<double> &globalPos) const
+{ 
+  if (!m_cacheValid) updateCache();
+
+  // It is assumed that the global position is already in the plane of the element.
+
+  // tilt angle is not defined for the endcap
+  if (isEndcap()) return 0;
+ 
+  // Angle between normal and radial vector.
+  //HepGeom::Vector3D<double> refVector(globalPos.x(), globalPos.y(), 0);
+  //return (refVector.cross(m_normal)).z()/refVector.mag();
+  // or the equivalent
+  return (globalPos.x() * m_normal.y() - globalPos.y() * m_normal.x()) / globalPos.perp();
+}
+
+double SiDetectorElement::sinStereo() const
+{
+
+  if (!m_cacheValid) updateCache();
+
+  // Stereo is the angle between a refVector and a vector along the strip/pixel in eta direction.
+  // I'm not sure how the sign should be defined. I've defined it here
+  // with rotation sense respect to normal,
+  // where normal is away from IP in barrel and in -ve z direction in endcap
+
+  // In Barrel refVector = unit vector along z axis,
+  // in endcap refVector = unit vector radial.
+  //
+  // sinStereo = (refVector cross stripAxis) . normal
+  //           = (refVector cross etaAxis) . normal
+  //           = refVector . (etaAxis cross normal)
+  //           = refVector . phiAxis  
+  //
+  // in Barrel we use
+  // sinStereo = refVector . phiAxis
+  //           = phiAxis.z()
+  //
+  // in endcap we use
+  // sinStereo = (refVector cross etaAxis) . normal
+  //           = -(center cross etaAxis) . zAxis
+  //           = (etaAxis cross center). z() 
+
+  double sinStereo;
+  if (isBarrel()) {
+    sinStereo = m_phiAxis.z();
+  } else { // endcap
+    sinStereo = (m_center.y() * m_etaAxis.x() - m_center.x() * m_etaAxis.y()) / m_center.perp();
+  }      
+  return sinStereo;
+}
+
+  double SiDetectorElement::sinStereo(const Amg::Vector2D &localPos) const
+{
+  if (!m_cacheValid) updateCache();
+
+  HepGeom::Point3D<double> point=globalPositionCLHEP(localPos);
+  return sinStereo(point);
+}
+
+double SiDetectorElement::sinStereo(const HepGeom::Point3D<double> &globalPos) const
+{
+  //
+  // sinStereo =  (refVector cross stripAxis) . normal
+  //
+
+  if (!m_cacheValid) updateCache();
+
+  double sinStereo;
+  if (isBarrel()) {
+    if (m_design->shape() != InDetDD::Trapezoid) {
+      sinStereo = m_phiAxis.z();
+    } else { // trapezoid
+      assert (minWidth() != maxWidth());
+      double radius = width() * length() / (maxWidth() - minWidth());
+      HepGeom::Vector3D<double> stripAxis = radius * m_etaAxisCLHEP + globalPos - m_centerCLHEP;
+      sinStereo = (stripAxis.x() * m_normal.y() - stripAxis.y() * m_normal.x()) / stripAxis.mag();
+    }
+  } else { // endcap
+    if (m_design->shape() != InDetDD::Trapezoid) {
+      sinStereo = (globalPos.y() * m_etaAxis.x() - globalPos.x() * m_etaAxis.y()) / globalPos.perp();
+    } else { // trapezoid      
+      // double radius   = m_center.perp(); // Really want nominal r.
+      assert (minWidth() != maxWidth());
+      double radius = width() * length() / (maxWidth() - minWidth());
+      // HepGeom::Vector3D<double> stripAxis = radius * m_etaAxis + globalPos - m_center;
+      // Only need projection in xy plane.
+      double stripAxisX  = globalPos.x() - m_center.x() + m_etaAxis.x()*radius;
+      double stripAxisY  = globalPos.y() - m_center.y() + m_etaAxis.y()*radius;
+      double norm  = 1./(radius*sqrt(stripAxisX*stripAxisX + stripAxisY*stripAxisY));
+      sinStereo  = norm * (stripAxisX * globalPos.y() - stripAxisY * globalPos.x());
+    }
+  }
+  return sinStereo;
+}
+
+bool 
+SiDetectorElement::isStereo() const 
+{
+  if (m_firstTime) updateCache();
+  return m_isStereo;
+}
+
+
+double 
+SiDetectorElement::sinStereoLocal(const Amg::Vector2D &localPos) const
+{
+  // The equation below will work for rectangle detectors as well in which 
+  // case it will return 0. But we return zero immediately as there is no point doing the calculation.
+  if (m_design->shape() == InDetDD::Box) return 0;
+  double oneOverRadius = (maxWidth() - minWidth()) /  (width() * length());
+  double x = localPos[distPhi];
+  double y = localPos[distEta];
+  return -x*oneOverRadius / sqrt( (1+y*oneOverRadius)*(1+y*oneOverRadius) + x*oneOverRadius*x*oneOverRadius );  
+}
+
+
+double 
+SiDetectorElement::sinStereoLocal(const HepGeom::Point3D<double> &globalPos) const
+{
+  return sinStereoLocal(localPosition(globalPos));
+}
+
+// Special method for SCT to retrieve the two ends of a "strip"
+  std::pair<Amg::Vector3D,Amg::Vector3D> SiDetectorElement::endsOfStrip(const Amg::Vector2D &position) const
+{
+  const std::pair<Amg::Vector2D,Amg::Vector2D> localEnds=
+    m_design->endsOfStrip(position);
+  return std::pair<Amg::Vector3D,Amg::Vector3D >(globalPosition(localEnds.first),
+					  globalPosition(localEnds.second));
+}
+
+
+const Trk::Surface & 
+SiDetectorElement::surface() const
+{
+  if (!m_surface) m_surface = new Trk::PlaneSurface(*this);
+  return *m_surface;
+}
+  
+const Trk::SurfaceBounds & 
+SiDetectorElement::bounds() const
+{
+  return m_design->bounds();
+}
+  
+// Get min/max or r, z,and phi
+void SiDetectorElement::getExtent(double &rMin, double &rMax, 
+	       double &zMin, double &zMax, 
+	       double &phiMin, double &phiMax) const
+{
+
+  HepGeom::Point3D<double> corners[4];
+  getCorners(corners);
+
+  bool first = true; 
+
+  double phiOffset = 0.;
+
+  for (int i = 0; i < 4; i++) {
+
+    HepGeom::Point3D<double> globalPoint = globalPosition(corners[i]);
+
+    double rPoint = globalPoint.perp();
+    double zPoint = globalPoint.z();
+    double phiPoint = globalPoint.phi();
+    
+    // Use first point to initializa min/max values.
+    if (first) {
+
+      // Put phi in a range so that we are not near -180/+180 division.
+      // Do this by adding an offset if phi > 90 CLHEP::deg or < -90 CLHEP::deg. 
+      // This offset is later removed.
+      if (phiPoint < -0.5 * M_PI) {
+	phiOffset = -0.5 * M_PI;
+      } else if  (phiPoint > 0.5 * M_PI) {
+	phiOffset = 0.5 * M_PI;
+      }
+      phiMin = phiMax = phiPoint - phiOffset;
+      rMin = rMax = rPoint;
+      zMin = zMax = zPoint;
+
+    } else {
+      phiPoint -= phiOffset;
+      // put phi back in -M_PI < phi < +M_PI range
+      if (phiPoint < -M_PI) phiPoint += 2. * M_PI; 
+      if (phiPoint > M_PI)  phiPoint -= 2. * M_PI; 
+      phiMin = std::min(phiMin, phiPoint);
+      phiMax = std::max(phiMax, phiPoint);
+      rMin = std::min(rMin, rPoint);
+      rMax = std::max(rMax, rPoint);
+      zMin = std::min(zMin, zPoint);
+      zMax = std::max(zMax, zPoint);
+    }
+    first = false;
+  }
+
+  // put phi back in -M_PI < phi < +M_PI range	  
+  phiMin += phiOffset;
+  phiMax += phiOffset;
+  if (phiMin < -M_PI) phiMin += 2. * M_PI; 
+  if (phiMin > M_PI)  phiMin -= 2. * M_PI; 
+  if (phiMax < -M_PI) phiMax += 2. * M_PI; 
+  if (phiMax > M_PI)  phiMax -= 2. * M_PI; 
+}
+
+
+
+// Get eta/phi extent. Returns min/max eta and phi and r (for barrel)
+// or z (for endcap) Takes as input the vertex spread in z (+-deltaZ).
+// Gets 4 corners of the sensor and calculates eta phi for each corner
+// for both +/- vertex spread.  The returned phi is between -M_PI and M_PI
+// with the direction minPhi to maxPhi always in the positive sense,
+// so if the element extends across the -180/180 boundary then minPhi will
+// be greater than maxPhi.
+void SiDetectorElement::getEtaPhiRegion(double deltaZ, double &etaMin, double &etaMax, double &phiMin, 
+					double &phiMax, double &rz) const
+{
+  if (!m_cacheValid) updateCache();
+
+  HepGeom::Point3D<double> corners[4];
+  getCorners(corners);
+
+  bool first = true; 
+
+  double phiOffset = 0.;
+
+  for (int i = 0; i < 4; i++) {
+    double etaMinPoint;
+    double etaMaxPoint;
+    double phiPoint;
+
+    // Get the eta phi value for this corner.
+    getEtaPhiPoint(corners[i], deltaZ, etaMinPoint, etaMaxPoint, phiPoint);
+
+    if (first) { // Use the first point to initialize the min/max values.
+
+      // Put phi in a range so that we are not near -180/+180 division.
+      // Do this by adding an offset if phi > 90 CLHEP::deg or < -90 CLHEP::deg. 
+      // This offset is later removed.
+      if (phiPoint < -0.5 * M_PI) {
+	phiOffset = -0.5 * M_PI;
+      } else if  (phiPoint > 0.5 * M_PI) {
+	phiOffset = 0.5 * M_PI;
+      }
+      phiMin = phiMax = phiPoint - phiOffset;
+      etaMin = etaMinPoint;
+      etaMax = etaMaxPoint;
+    } else {
+      phiPoint -= phiOffset;
+      // put phi back in -M_PI < phi < +M_PI range
+      if (phiPoint < -M_PI) phiPoint += 2. * M_PI; 
+      if (phiPoint > M_PI)  phiPoint -= 2. * M_PI; 
+      phiMin = std::min(phiMin, phiPoint);
+      phiMax = std::max(phiMax, phiPoint);
+      etaMin = std::min(etaMin, etaMinPoint);
+      etaMax = std::max(etaMax, etaMaxPoint);
+    }
+    first = false;
+  }
+
+  // put phi back in -M_PI < phi < +M_PI range	  
+  phiMin += phiOffset;
+  phiMax += phiOffset;
+  if (phiMin < -M_PI) phiMin += 2. * M_PI; 
+  if (phiMin > M_PI)  phiMin -= 2. * M_PI; 
+  if (phiMax < -M_PI) phiMax += 2. * M_PI; 
+  if (phiMax > M_PI)  phiMax -= 2. * M_PI; 
+
+  // Calculate rz = r (barrel) or z (endcap)
+  // Use center of sensor ((0,0,0) in local coordinates) for determining this.
+  //  HepGeom::Point3D<double> globalCenter = globalPosition(HepGeom::Point3D<double>(0,0,0));
+  if (isBarrel()) {
+    rz = center().perp(); // r
+  } else {
+    rz = center().z();  // z
+  }
+
+}	
+
+// Gets eta phi for a point given in local coordinates. deltaZ is specified to
+// account for the vertex spread. phi is independent of this vertex
+// spread. etaMax will correspond to zMin (-deltaZ) and etaMin will
+// correspond to zMax (+deltaZ).
+void SiDetectorElement::getEtaPhiPoint(const HepGeom::Point3D<double> & point, double deltaZ, 
+				       double &etaMin, double &etaMax, double &phi) const
+{
+  // Get the point in global coordinates.
+  HepGeom::Point3D<double> globalPoint = globalPosition(point);
+
+  double r = globalPoint.perp();
+  double z = globalPoint.z();
+  
+  double thetaMin = atan2(r,(z + deltaZ));
+  etaMax = -log(tan(0.5 * thetaMin));
+  double thetaMax = atan2(r,(z - deltaZ));
+  etaMin = -log(tan(0.5 * thetaMax));
+  
+  phi = globalPoint.phi();
+}
+
+void SiDetectorElement::getCorners(HepGeom::Point3D<double> *corners) const
+{
+  if (!m_cacheValid) updateCache();
+
+  // This makes the assumption that the forward SCT detectors are orientated such that 
+  // the positive etaAxis corresponds to the top of the detector where the width is largest.
+  // This is currently always the case.
+  // For the SCT barrel and pixel detectors minWidth and maxWidth are the same and so should 
+  // work for all orientations.
+
+  double minWidth = m_design->minWidth();
+  double maxWidth = m_design->maxWidth();
+  double length   = m_design->length();
+  
+  // Lower left
+  corners[0][distPhi] = -0.5 * minWidth;
+  corners[0][distEta] = -0.5 * length;
+  corners[0][distDepth] = 0.;
+
+  // Lower right
+  corners[1][distPhi] =  0.5 * minWidth;
+  corners[1][distEta] = -0.5 * length;
+  corners[1][distDepth] = 0.;
+
+  // Upper Right
+  corners[2][distPhi] = 0.5 * maxWidth;
+  corners[2][distEta] = 0.5 * length;
+  corners[2][distDepth] = 0.;
+
+  // Upper left
+  corners[3][distPhi] = -0.5 * maxWidth;
+  corners[3][distEta] =  0.5 * length;
+  corners[3][distDepth] = 0.;
+}
+
+SiIntersect
+SiDetectorElement::inDetector(const Amg::Vector2D & localPosition, 
+					  double phiTol, double etaTol) const
+{
+  return m_design->inDetector(localPosition, phiTol, etaTol);
+}
+
+  
+SiIntersect 
+SiDetectorElement::inDetector(const HepGeom::Point3D<double> & globalPosition, double phiTol, double etaTol) const
+{
+  return m_design->inDetector(localPosition(globalPosition), phiTol, etaTol);
+}
+
+bool 
+SiDetectorElement::nearBondGap(Amg::Vector2D localPosition, double etaTol) const
+{
+  return m_design->nearBondGap(localPosition, etaTol);
+}
+
+bool
+SiDetectorElement::nearBondGap(HepGeom::Point3D<double> globalPosition, double etaTol) const
+{
+  return m_design->nearBondGap(localPosition(globalPosition), etaTol);
+}  
+
+
+  Amg::Vector2D
+SiDetectorElement::localPositionOfCell(const SiCellId &cellId) const
+{
+  Amg::Vector2D pos(m_design->localPositionOfCell(cellId));
+  return correctLocalPosition(pos);
+}
+
+Amg::Vector2D
+SiDetectorElement::localPositionOfCell(const Identifier & id) const
+{
+  SiCellId cellId = cellIdFromIdentifier(id);
+  Amg::Vector2D pos(m_design->localPositionOfCell(cellId));
+  return correctLocalPosition(pos);
+}
+
+Amg::Vector2D
+SiDetectorElement::rawLocalPositionOfCell(const SiCellId &cellId) const
+{
+  return m_design->localPositionOfCell(cellId);
+}
+
+Amg::Vector2D
+SiDetectorElement::rawLocalPositionOfCell(const Identifier & id) const
+{
+  SiCellId cellId = cellIdFromIdentifier(id);
+  return m_design->localPositionOfCell(cellId);
+}
+
+int 
+SiDetectorElement::numberOfConnectedCells(const SiCellId cellId) const
+{
+  SiReadoutCellId readoutId = m_design->readoutIdOfCell(cellId);
+  return m_design->numberOfConnectedCells(readoutId);
+}
+
+SiCellId 
+SiDetectorElement::connectedCell(const SiCellId cellId, int number) const
+{
+  SiReadoutCellId readoutId = m_design->readoutIdOfCell(cellId);
+  return m_design->connectedCell(readoutId, number);
+}
+
+
+SiCellId 
+SiDetectorElement::cellIdOfPosition(const Amg::Vector2D &localPosition) const
+{
+  return m_design->cellIdOfPosition(localPosition);
+}
+
+Identifier
+SiDetectorElement::identifierOfPosition(const Amg::Vector2D &localPosition) const
+{
+  SiCellId cellId = m_design->cellIdOfPosition(localPosition);
+  return identifierFromCellId(cellId);
+}
+
+Identifier 
+SiDetectorElement::identifierFromCellId(const SiCellId & cellId) const
+{
+  Identifier id; // Will be initialized in an invalid state.
+
+  // If something fails it returns the id in an invalid state.
+
+  if (cellId.isValid()) {
+
+    if (isPixel()){
+      const PixelID * pixelIdHelper = static_cast<const PixelID *>(getIdHelper());
+      if (pixelIdHelper) {
+	id = pixelIdHelper->pixel_id(m_id, cellId.phiIndex(), cellId.etaIndex());
+      }
+    } else {
+      const SCT_ID * sctIdHelper = static_cast<const SCT_ID *>(getIdHelper());
+      if (sctIdHelper) {
+	id = sctIdHelper->strip_id(m_id, cellId.strip());
+      }
+    }
+  }
+
+  return id; 
+}
+
+SiCellId   
+SiDetectorElement::cellIdFromIdentifier(const Identifier & identifier) const
+{
+  SiCellId cellId; // Initialized in invalid state.
+
+  // If something fails it returns the cellId in an invalid state.
+
+  if (identifier.is_valid()) {
+  
+    if (isPixel()){
+      const PixelID * pixelIdHelper = static_cast<const PixelID *>(getIdHelper());
+      if (pixelIdHelper) {
+	cellId = SiCellId(pixelIdHelper->phi_index(identifier), pixelIdHelper->eta_index(identifier));
+      }
+    } else {
+      const SCT_ID * sctIdHelper = static_cast<const SCT_ID *>(getIdHelper());
+      if (sctIdHelper) {
+	cellId =  SiCellId(sctIdHelper->strip(identifier));
+      }
+    }
+  }
+  
+  return cellId;
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDetectorManager.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDetectorManager.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..f58d896a5f6be0317f4622fb2341503bb57d2aa8
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDetectorManager.cxx
@@ -0,0 +1,191 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+
+#include "GeoPrimitives/CLHEPtoEigenConverter.h"
+
+#include "InDetReadoutGeometry/SiDetectorManager.h"
+#include "AtlasDetDescr/AtlasDetectorID.h"
+#include "IdDictDetDescr/IdDictManager.h"
+#include "StoreGate/StoreGateSvc.h"
+
+#include "GeoModelKernel/GeoXF.h"
+#include "CLHEP/GenericFunctions/Variable.hh"
+#include "GeoModelKernel/GeoAlignableTransform.h"
+#include "DetDescrConditions/AlignableTransformContainer.h"
+#include "InDetReadoutGeometry/SiDetectorElementCollection.h"
+#include "InDetReadoutGeometry/SiDetectorElement.h"
+#include "InDetReadoutGeometry/ExtendedAlignableTransform.h"
+
+#include <iostream>
+
+namespace InDetDD
+{
+
+    SiDetectorManager::SiDetectorManager(StoreGateSvc * detStore, const std::string & name)
+        : InDetDetectorManager(detStore, name)
+    {
+  // Add default folder
+        addFolder("/Indet/Align");
+    }
+
+    const std::string& SiDetectorManager::tag() const
+    {
+        return m_tag;
+    }
+
+// Non const version needed when it is registered to IOVSvc
+    StatusCode SiDetectorManager::alignmentCallback( IOVSVC_CALLBACK_ARGS_P(I,keys) ) {
+        return align(I,keys);
+    }
+
+    void SiDetectorManager::invalidateAll() const
+    {
+        for (SiDetectorElementCollection::const_iterator element_iter = getDetectorElementBegin();
+        element_iter != getDetectorElementEnd();
+        ++element_iter) {
+
+            if (*element_iter) {
+                (*element_iter)->invalidate();
+            }
+        }
+    }
+
+    void SiDetectorManager::updateAll() const
+    {
+        for (SiDetectorElementCollection::const_iterator element_iter = getDetectorElementBegin();
+        element_iter != getDetectorElementEnd();
+        ++element_iter) {
+            if (*element_iter) {
+                (*element_iter)->updateAllCaches();
+            }
+        }
+    }
+
+
+// Register the call back for this key and the corresponding level in
+// in the hierarchy.
+// DEPRECATED
+    void SiDetectorManager::addKey(const std::string & key, int level)
+    {
+        bool globalDelta = (level != 0); // local delta for level == 0
+        addKey(key, level, globalDelta);
+    }
+
+
+
+// Register the call back for this key and the corresponding level in
+// in the hierarchy. Also specify whether its a global or local delta.
+// DEPRECATED
+    void SiDetectorManager::addKey(const std::string & key, int level, bool globalDelta)
+    {
+        if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "Registering alignmentCallback with key " << key << endreq;
+        const DataHandle<AlignableTransform> transformCollection;  
+        StatusCode sc = m_detStore->regFcn(&SiDetectorManager::alignmentCallback, this, transformCollection, key);
+        if (sc.isFailure()) {
+            if (msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "Unable to register call back using old method. This is OK if you are using COOL." << endreq;
+        }
+        FrameType frame = (globalDelta) ? InDetDD::global : InDetDD::local;
+        addKey(key, level, frame);
+    }
+
+
+    void SiDetectorManager::addKey(const std::string & key, int level, FrameType frame)
+    {
+        addChannel(key, level, frame);
+    }
+
+
+    bool SiDetectorManager::setAlignableTransformLocalDelta(ExtendedAlignableTransform * extXF, 
+                                                            const Amg::Transform3D & localToGlobalXF,
+                                                            const Amg::Transform3D & delta) const
+    {
+        // ATTENTION -------------------------------------------------------- (A.S.)
+        // CLHEP < -- > AMG interface method
+        
+        // Sets the alignable transform delta when the supplied delta is in the local
+        // reconstruction frame
+        
+        // If the default transform to the local recostruction frame is
+        // T = A*B*C*D*E
+        // and the alignable transform is C with delta c and the delat in the local frame is l, then
+        // A*B*C*c*D*E = A*B*C*D*E*l
+        //  c = (D*E) * l * (D*E).inverse()
+        //  c = (A*B*C).inverse * T * l * T.inverse() * (A*B*C) 
+        
+        // To get default transform up and including the alignable transform,
+        // we assume the next volume down is a fullphys volume and so its
+        // transform is the transform we want (ie A*B*C in the above example).
+
+        if (!extXF) return false;
+
+        const GeoVFullPhysVol* child = extXF->child();
+        if (child && extXF->alignableTransform()) {
+            // the definitiv absolut transform is in CLHEP -> do the calculation in CLHEP
+            HepGeom::Transform3D localToGlobalXFCLHEP = Amg::EigenTransformToCLHEP(localToGlobalXF);
+            const HepGeom::Transform3D& transform = child->getDefAbsoluteTransform();
+            // calucluate the corrected delta according to the formula above
+            HepGeom::Transform3D correctedDelta = transform.inverse()*localToGlobalXFCLHEP      // (A*B*C).inverse() * T
+                                                   * Amg::EigenTransformToCLHEP(delta)             // l
+                                                   * localToGlobalXFCLHEP.inverse() * transform;   // T.inverse() * (A*B*C)
+            extXF->alignableTransform()->setDelta(correctedDelta);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    bool SiDetectorManager::setAlignableTransformGlobalDelta(ExtendedAlignableTransform * extXF, 
+                                                             const Amg::Transform3D& delta) const {
+        // ATTENTION -------------------------------------------------------- (A.S.)
+        // CLHEP < -- > AMG interface method
+        
+        // Sets the alignable transform delta when the supplied delta is in the global frame.
+        
+        // If the default transform down to the alignable transform is
+        // T = A*B*C
+        // and the alignable transform is C with delta c and the delta in the global frame is g, then
+        // A*B*C*c = g*A*B*C
+        // T*c = g*T
+        //  c = T.inverse() * g * T
+        
+        // To get default transform up and including the alignable transform,
+        // we assume the next volume down is a fullphys volume and so its
+        // transform is the transform we want (ie T=A*B*C in the above example).
+
+
+        if (!extXF) return false;
+
+        const GeoVFullPhysVol * child = extXF->child();
+        if (child && extXF->alignableTransform()) {
+            // do the calculation in CLHEP  
+            const HepGeom::Transform3D& transform = child->getDefAbsoluteTransform();
+            extXF->alignableTransform()->setDelta(transform.inverse() * Amg::EigenTransformToCLHEP(delta) * transform);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+
+    void SiDetectorManager::addDesign(const SiDetectorDesign * design)
+    {
+        m_designs.push_back(design);
+    }
+
+    int SiDetectorManager::numDesigns() const
+    {
+        return m_designs.size();
+    }
+
+
+    const SiDetectorDesign* SiDetectorManager::getDesign(int i) const
+    {
+        return m_designs[i];
+    }
+
+
+
+
+}// namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDiodesParameters.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDiodesParameters.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..0fdc6da16f0d1dbb49e9183c9d9c8a4e94cd8aa9
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiDiodesParameters.cxx
@@ -0,0 +1,47 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiDiodesParameters.cxx
+//   Implementation file for class SiDiodesParameters
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 1.0 14/08/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SiDiodesParameters.h"
+
+namespace InDetDD {
+
+// Implicit constructor:
+SiDiodesParameters::SiDiodesParameters() :
+  m_centre(),
+  m_width()
+{}
+
+// Copy constructor:
+SiDiodesParameters::SiDiodesParameters(const SiDiodesParameters &parameters) :
+  m_centre(parameters.m_centre),
+  m_width(parameters.m_width)
+{}
+
+// Constructor with parameters:
+SiDiodesParameters::SiDiodesParameters(const SiLocalPosition &centre,
+				       const SiLocalPosition &width) :
+  m_centre(centre),
+  m_width(width)
+{}
+
+// Assignment operator:
+SiDiodesParameters &SiDiodesParameters::operator=(const SiDiodesParameters &parameters)
+{
+  if (this!=&parameters) {
+    m_centre=parameters.m_centre;
+    m_width=parameters.m_width;
+  } else {}
+  return *this;
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiLocalPosition.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiLocalPosition.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..79df41ff1e66507ba2c3087d59308508e7d10e6c
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiLocalPosition.cxx
@@ -0,0 +1,114 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///////////////////////////////////////////////////////////////////
+// SiLocalPosition.cxx
+//   Implementation file for class SiLocalPosition
+///////////////////////////////////////////////////////////////////
+// (c) ATLAS Detector software
+///////////////////////////////////////////////////////////////////
+// Version 2.1 01/08/2001 David Calvet
+///////////////////////////////////////////////////////////////////
+
+#include "InDetReadoutGeometry/SiLocalPosition.h"
+
+namespace InDetDD {
+
+// Implicit constructor:
+SiLocalPosition::SiLocalPosition() :
+  m_xEta(0),
+  m_xPhi(0),
+  m_xDepth(0)
+{}
+
+// Copy constructor:
+SiLocalPosition::SiLocalPosition(const SiLocalPosition &position) :
+  m_xEta(position.m_xEta),
+  m_xPhi(position.m_xPhi),
+  m_xDepth(position.m_xDepth)
+{}
+
+// Constructor with parameters:
+SiLocalPosition::SiLocalPosition(const double xEta,const double xPhi,
+				 const double xDepth) :
+  m_xEta(xEta),
+  m_xPhi(xPhi),
+  m_xDepth(xDepth)
+{}
+
+SiLocalPosition::SiLocalPosition(const Amg::Vector2D &position)
+  : m_xEta(position[Trk::distEta]),
+    m_xPhi(position[Trk::distPhi]),
+    m_xDepth(0)
+{}
+  
+
+SiLocalPosition::operator Amg::Vector2D(void) const
+{
+  return Amg::Vector2D(m_xPhi, m_xEta);
+}
+
+// Assignment operator:
+SiLocalPosition &SiLocalPosition::operator=(const SiLocalPosition &position)
+{
+  if (this!=&position) {
+    m_xEta=position.m_xEta;
+    m_xPhi=position.m_xPhi;
+    m_xDepth=position.m_xDepth;
+  } else {}
+  return *this;
+}
+
+// addition of positions:
+SiLocalPosition &SiLocalPosition::operator+=(const SiLocalPosition &position)
+{
+  m_xEta+=position.m_xEta;
+  m_xPhi+=position.m_xPhi;
+  m_xDepth+=position.m_xDepth;  
+  return *this;
+}
+
+// scaling:
+SiLocalPosition &SiLocalPosition::operator*=(const double factor)
+{
+  m_xEta*=factor;
+  m_xPhi*=factor;
+  m_xDepth*=factor;
+  return *this;
+}
+
+// scaling:
+SiLocalPosition &SiLocalPosition::operator/=(const double factor)
+{
+  if (0!=factor) {
+    m_xEta/=factor;
+    m_xPhi/=factor;
+    m_xDepth/=factor;
+  } else {}
+  return *this;
+}
+
+SiLocalPosition operator+(const SiLocalPosition &position1,
+			  const SiLocalPosition &position2)
+{
+  SiLocalPosition result(position1);
+  result+=position2;
+  return result;
+}
+
+SiLocalPosition operator*(const SiLocalPosition &position,const double factor)
+{
+  SiLocalPosition result(position);
+  result*=factor;
+  return result;
+}
+
+SiLocalPosition operator/(const SiLocalPosition &position,const double factor)
+{
+  SiLocalPosition result(position);
+  result/=factor;
+  return result;
+}
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiNumerology.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiNumerology.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..d3eb9ec5e6fd613552046ad0e71b28a6513a9407
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/SiNumerology.cxx
@@ -0,0 +1,120 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/SiNumerology.h"
+
+
+namespace InDetDD {
+
+SiNumerology::SiNumerology()
+  : m_numLayers(0),
+    m_numDisks(0),
+    m_maxPhiCells(0),
+    m_maxEtaCells(0),
+    m_maxNumBarrelEta(0),
+    m_maxNumEndcapRings(0),
+    m_maxNumBarrelPhiModules(0),
+    m_maxNumEndcapPhiModules(0),
+    m_numDisksDBM(0), 
+    m_numBarrelDBM(0), 
+    m_maxNumEndcapPhiModulesDBM(0) 
+{}
+  
+
+void SiNumerology::setNumLayers(int nLayers)
+{
+  m_phiModulesForLayer.resize(nLayers);
+  m_etaModulesForLayer.resize(nLayers);
+  m_numLayers = nLayers;
+}
+
+    
+void SiNumerology::setNumDisks(int nDisks)
+{
+  m_numDisks = nDisks;
+  m_ringsForDisk.resize(nDisks);
+  m_phiModulesForDiskRing.resize(nDisks);
+}
+
+void SiNumerology::setNumRingsForDisk(int disk, int nRings)
+{ 
+  m_ringsForDisk[disk] = nRings;
+  m_phiModulesForDiskRing[disk].resize(nRings);
+  m_maxNumEndcapRings = std::max(m_maxNumEndcapRings, nRings);
+}
+
+void SiNumerology::setNumPhiModulesForDiskRing(int disk, int ring, int nPhiModules)
+{
+  m_phiModulesForDiskRing[disk][ring] = nPhiModules;
+  m_maxNumEndcapPhiModules = std::max(m_maxNumEndcapPhiModules, nPhiModules);
+}
+
+void SiNumerology::setNumPhiModulesForLayer(int layer, int nPhiModules)
+{
+  m_phiModulesForLayer[layer] = nPhiModules;      
+  m_maxNumBarrelPhiModules = std::max(m_maxNumBarrelPhiModules, nPhiModules);
+}
+
+void SiNumerology::setNumEtaModulesForLayer(int layer, int nEtaModules)
+{
+  m_etaModulesForLayer[layer] = nEtaModules;
+  m_maxNumBarrelEta = std::max(m_maxNumBarrelEta, nEtaModules);
+}
+
+void SiNumerology::setMaxNumPhiCells(int cells)
+{
+  m_maxPhiCells = std::max(m_maxPhiCells,cells);
+}
+
+void SiNumerology::setMaxNumEtaCells(int cells)
+{
+  m_maxEtaCells = std::max(m_maxEtaCells,cells);
+}
+ 
+ 
+void SiNumerology::addBarrel(int id)
+{
+  m_barrelIds.push_back(id);
+}
+
+void SiNumerology::addEndcap(int id)
+{
+  m_endcapIds.push_back(id);
+}
+
+// DBM  
+void SiNumerology::setNumDisksDBM(int nDisks) 
+{ 
+  m_numDisksDBM = nDisks; 
+  if(nDisks>0){ 
+    m_phiModulesForDiskRingDBM.resize(nDisks); 
+    for(int disk=0; disk<nDisks; disk++) 
+      m_phiModulesForDiskRingDBM[disk].resize(1); 
+    return; 
+  } 
+   
+  m_endcapIdsDBM.clear(); 
+  m_phiModulesForDiskRingDBM.clear(); 
+  m_maxNumEndcapPhiModulesDBM = 0; 
+  m_phiModulesForDiskRingDBM.clear();   
+ 
+} 
+ 
+void SiNumerology::setNumBarrelDBM(int nBarrel) 
+{ 
+  m_numBarrelDBM = nBarrel; 
+} 
+ 
+void SiNumerology::setNumPhiModulesForDiskRingDBM(int disk, int ring, int nPhiModules) 
+{ 
+  m_phiModulesForDiskRingDBM[disk][ring] = nPhiModules; 
+  m_maxNumEndcapPhiModulesDBM = std::max(m_maxNumEndcapPhiModules, nPhiModules); 
+} 
+ 
+void SiNumerology::addEndcapDBM(int id) 
+{ 
+  m_endcapIdsDBM.push_back(id); 
+} 
+	
+} // End namespace
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BarrelCode.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BarrelCode.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..75818558cab462de7856602545a0f3b8d4cf1933
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BarrelCode.cxx
@@ -0,0 +1,72 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/TRT_BarrelCode.h"
+#include <string>
+#include <sstream>
+
+namespace InDetDD {
+//
+// Mask
+//
+const int TRT_BarrelCode::Z_MASK           = 0x00000001;    // lowest six bits
+const int TRT_BarrelCode::MODULE_MASK      = 0x00000003;    // lowest two
+const int TRT_BarrelCode::PHI_MASK         = 0x0000001F;    // lowest five
+const int TRT_BarrelCode::STRAWLAYER_MASK  = 0x0000001F;    // lowest five
+
+//
+// Shifts
+//
+const int TRT_BarrelCode::Z_SHIFT           = 0;
+const int TRT_BarrelCode::MODULE_SHIFT      = 1;
+const int TRT_BarrelCode::PHI_SHIFT         = 3;
+const int TRT_BarrelCode::STRAWLAYER_SHIFT  = 8;
+
+
+
+
+
+TRT_BarrelCode::TRT_BarrelCode()
+{
+  _key = 0;
+}
+
+TRT_BarrelCode::TRT_BarrelCode(unsigned isPos, unsigned moduleIndex, unsigned phiIndex, unsigned strawLayerIndex)
+  :
+  _key ((( isPos        & Z_MASK )             << Z_SHIFT)      | 
+	(( moduleIndex     & MODULE_MASK )     << MODULE_SHIFT) | 
+	(( phiIndex        & PHI_MASK )        << PHI_SHIFT)    | 
+	(( strawLayerIndex & STRAWLAYER_MASK ) << STRAWLAYER_SHIFT))
+{
+}
+
+TRT_BarrelCode::TRT_BarrelCode(const TRT_BarrelCode &right)
+{
+  _key = right.getKey();
+}
+
+
+
+
+TRT_BarrelCode::~TRT_BarrelCode()
+{
+}
+
+
+const TRT_BarrelCode & TRT_BarrelCode::operator=(const TRT_BarrelCode &right)
+{
+  _key = right.getKey();
+  return *this;
+}
+
+
+
+std::string TRT_BarrelCode::getName() const {
+
+  std::ostringstream outputStream;
+  outputStream << this;
+  return outputStream.str();
+}
+
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BarrelDescriptor.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BarrelDescriptor.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..2205aacf289eb5301d8e79ef58c1e5a21094595a
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BarrelDescriptor.cxx
@@ -0,0 +1,53 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/TRT_BarrelDescriptor.h"
+
+#include "TrkSurfaces/CylinderBounds.h"
+
+#include "CLHEP/Units/SystemOfUnits.h"
+
+namespace InDetDD {
+
+TRT_BarrelDescriptor::TRT_BarrelDescriptor()
+  : _length(0),
+    _zDead(0),
+    _zPos(0),
+    m_innerTubeRadius(2*CLHEP::mm), // FIXME: Hardwired for now!!
+    _f(NULL),
+    _o(0),
+    m_bounds(0)
+
+{
+}
+
+
+TRT_BarrelDescriptor::~TRT_BarrelDescriptor()
+{
+  delete m_bounds;
+}
+
+
+void TRT_BarrelDescriptor::addStraw(double xPos, double yPos) {
+
+  _x.push_back(xPos);
+  _y.push_back(yPos);
+
+}
+
+
+void TRT_BarrelDescriptor::setStrawTransformField(const GeoXF::Function *xf, size_t offsetInto) {
+  _f=xf;
+  _o=offsetInto;
+}
+
+const Trk::SurfaceBounds & 
+TRT_BarrelDescriptor::strawBounds() const
+{
+  if (!m_bounds) m_bounds = new Trk::CylinderBounds(m_innerTubeRadius, 0.5*_length);
+  return *m_bounds;
+}
+
+
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BarrelElement.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BarrelElement.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..bb3d0af903c03618de9384de315fd7b47edd9a8c
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BarrelElement.cxx
@@ -0,0 +1,240 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Identifier/Identifier.h"
+#include "InDetReadoutGeometry/SurfaceCache.h"
+#include "InDetReadoutGeometry/TRT_BarrelElement.h"
+#include "InDetReadoutGeometry/TRT_Conditions.h"
+
+#include "TrkSurfaces/RectangleBounds.h"
+#include "TrkSurfaces/PlaneSurface.h"
+
+#include "InDetIdentifier/TRT_ID.h"
+
+#include "TRT_ConditionsData/ExpandedIdentifier.h"
+#include "TRT_ConditionsData/StrawDxContainer.h"
+
+namespace InDetDD {
+
+TRT_BarrelElement::TRT_BarrelElement(const GeoVFullPhysVol *volume, 
+				     const TRT_BarrelDescriptor *descriptor,
+				     bool isPositive, 
+				     unsigned int modIndex, 
+				     unsigned int phiIndex, 
+				     unsigned int strawLayIndex, 
+				     const TRT_ID * idHelper,
+				     const TRT_Conditions * conditions)
+  :
+  TRT_BaseElement(volume, 
+		  idHelper->layer_id((isPositive ? 1:-1), phiIndex, modIndex, strawLayIndex),
+		  idHelper, conditions),
+  _code(isPositive,modIndex,phiIndex,strawLayIndex),
+  _descriptor(descriptor),
+  _nextInPhi(NULL),
+  _previousInPhi(NULL),
+  _nextInR(NULL),
+  _previousInR(NULL),
+  m_surface(0)
+		      
+{
+  _descriptor->ref();
+}
+
+
+TRT_BarrelElement::~TRT_BarrelElement()
+{
+  _descriptor->unref();
+  delete m_surface;
+}
+
+
+const TRT_BarrelConditions * TRT_BarrelElement::getConditionsData() const
+{
+  return NULL;
+}
+
+const TRT_BarrelDescriptor * TRT_BarrelElement::getDescriptor() const
+{
+  return _descriptor;
+}
+
+void  TRT_BarrelElement::setNextInPhi(const TRT_BarrelElement *element)
+{
+  _nextInPhi=element;
+}
+
+void  TRT_BarrelElement::setPreviousInPhi(const TRT_BarrelElement *element)
+{
+  _previousInPhi=element;
+}
+
+void  TRT_BarrelElement::setNextInR(const TRT_BarrelElement *element)
+{
+  _nextInR=element;
+}
+
+void  TRT_BarrelElement::setPreviousInR(const TRT_BarrelElement *element)
+{
+  _previousInR=element;
+}
+
+
+
+HepGeom::Transform3D TRT_BarrelElement::calculateStrawTransform(int straw) const 
+{
+  // NB The tranformation to a straw is reconstructed here precisely as
+  // it was ... hopefully... in the factory.  One could eliminate this 
+  // requirement and make the code a little more robust in this regard but
+  // at the cost of doubling the descriptors.  (One descriptor now suffices
+  // for both positive and negative endcaps).
+  //std::cout << "In calculateStrawTransform" << std::endl;
+
+  const GeoXF::Function *f= _descriptor->getStrawTransform();
+  if (f) {
+    size_t offsetInto = _descriptor->getStrawTransformOffset();
+    double zPos = -_descriptor->strawZPos();
+    double zAng =  _code.isPosZ() ? M_PI : 0;
+    return  getMaterialGeom()->getAbsoluteTransform()*((*f)(straw+offsetInto))
+      * HepGeom::RotateY3D(zAng)*HepGeom::TranslateZ3D(zPos)
+      * calculateLocalStrawTransform(straw);
+    ////return  conditions()->solenoidFrame() 
+    ////  * getMaterialGeom()->getAbsoluteTransform()*((*f)(straw+offsetInto))
+    ////  * HepGeom::RotateY3D(zAng)*HepGeom::TranslateZ3D(zPos)
+    ////  * calculateLocalStrawTransform(straw);
+ } else {
+    std::cout << "calculateStrawTransform:  f is 0 !!!!" << std::endl;
+    return HepGeom::Transform3D();
+  }
+}
+
+HepGeom::Transform3D TRT_BarrelElement::calculateLocalStrawTransform(int straw) const
+{
+  const TRTCond::StrawDxContainer* container = conditions()->dxContainer();
+  HepGeom::Transform3D rc ;
+  if(!container) {
+    // std::cout << " TRT_BarrelElement: no local transform found " << std::endl;
+  } else {
+    // important note: dx1 moves the 'negative' wire endpoint end dx2
+    // the 'positive' wire endpoint in the local straw frame. In the
+    // global frame, 'dx1' corresponds to the readout side and 'dx2'
+    // to the wire joint side for both sides of the barrel.
+
+    int bec = getCode().isPosZ() ? +1 : -1 ;
+    int layer = getCode().getModuleIndex();
+    int phimodule = getCode().getPhiIndex();
+    int strawlayer = getCode().getStrawLayerIndex();
+    TRTCond::ExpandedIdentifier id = TRTCond::ExpandedIdentifier
+      (bec,layer,phimodule,strawlayer,straw,TRTCond::ExpandedIdentifier::STRAW);
+    double dx1 = container->getDx1(id);
+    double dx2 = container->getDx2(id);
+    double ang = (dx2-dx1)/strawLength();
+    double dx = (dx2+dx1)/2.;
+    rc = HepGeom::TranslateX3D(dx)*HepGeom::RotateY3D(ang) ;
+  }
+  return rc ;
+}
+
+
+HepGeom::Transform3D TRT_BarrelElement::defStrawTransform(int straw) const 
+{
+  // Same as calculateStrawTransform, except we use getDefAbsoluteTransform()
+  // rather than  getAbsoluteTransform()
+
+  // NB The tranformation to a straw is reconstructed here precisely as
+  // it was ... hopefully... in the factory.  One could eliminate this 
+  // requirement and make the code a little more robust in this regard but
+  // at the cost of doubling the descriptors.  (One descriptor now suffices
+  // for both positive and negative endcaps).
+
+  const GeoXF::Function *f= _descriptor->getStrawTransform();
+  if (f) {
+    size_t offsetInto = _descriptor->getStrawTransformOffset();
+    double zPos = -_descriptor->strawZPos();
+    double zAng =  _code.isPosZ() ? M_PI : 0;
+    return getMaterialGeom()->getDefAbsoluteTransform()*((*f)(straw+offsetInto))* HepGeom::RotateY3D(zAng)*HepGeom::TranslateZ3D(zPos);
+  } else {
+    std::cout << "calculateStrawTransform:  f is 0 !!!!" << std::endl;
+    return HepGeom::Transform3D();
+  }
+  
+}
+
+ 
+const Trk::SurfaceBounds& TRT_BarrelElement::strawBounds() const 
+{
+  return _descriptor->strawBounds();
+}
+
+const Trk::Surface& TRT_BarrelElement::elementSurface() const 
+{
+  if (!m_surface) m_surface = new Trk::PlaneSurface(*this);
+  return *m_surface;
+}
+   
+void TRT_BarrelElement::createSurfaceCache() const
+{
+  // Calculate the surface from the two end straws.
+  int firstStraw = 0;
+  int lastStraw = nStraws() - 1;
+
+  const Amg::Vector3D& centerFirstStraw = center(m_idHelper->straw_id(identify(), firstStraw));
+  const Amg::Vector3D& centerLastStraw  = center(m_idHelper->straw_id(identify(), lastStraw));
+
+  // Calculate center as the average position of the end straws.
+  Amg::Vector3D* center = new Amg::Vector3D(0.5*(centerFirstStraw+centerLastStraw));
+  
+  Amg::Vector3D  phiAxis = centerLastStraw - centerFirstStraw;
+  double width = phiAxis.mag();
+  phiAxis = phiAxis.normalized();
+  double elementWidth = width + 2 * _descriptor->innerTubeRadius(); // Add the straw tube radius
+  
+  // Get local z-axis. This is roughly in +ve global z direction  (exactly if no misalignment) 
+  // We could probably use any straw for this but we average the first and last straw and renormalize
+  // to a unit vector.
+  Amg::Vector3D etaAxis = 0.5*(strawAxis(firstStraw) + strawAxis(lastStraw));
+  etaAxis = etaAxis.normalized();
+
+  // Calculate normal. This will point away from the beam line based
+  // on the assumption that the straw numbering goes in the direction
+  // of increasing phi and the straw axis is in +ve z direction.
+  Amg::Vector3D* normal = new Amg::Vector3D(phiAxis.cross( etaAxis ));  // phi cross z
+
+  // Transform from local to global. 
+  // local x axis -> phiAxis
+  // local y axis -> etaAxis
+  // local z axis -> cross product of local x and local y
+  // translation -> center
+
+  // This constructor takes three points in the two coordinate systems.
+  Amg::Transform3D* transform = new Amg::Transform3D();
+  
+  Amg::RotationMatrix3D rotation;
+  rotation.col(0) = phiAxis;
+  rotation.col(1) = etaAxis;
+  rotation.col(2) = (*normal);
+
+  (*transform)  = Amg::Translation3D(*center) * rotation;
+    
+  // create the element bounds
+  Trk::RectangleBounds * elementBounds = new Trk::RectangleBounds(0.5*elementWidth, 0.5*strawLength());
+  // create the surface cache
+  m_surfaceCache = new SurfaceCache(transform, center, normal, elementBounds);
+  // creaete the surface (only if needed, links are still ok even if cache update)
+  if (!m_surface) m_surface = new Trk::PlaneSurface(*this);
+
+}
+
+
+int TRT_BarrelElement::strawDirection() const
+{
+  // Return +1 if the straw local axis is in the same direction as the z axis, -1 otherwise.
+  // The straw axis by convention goes in the direction away from the readout.
+  // So for -ve endcap this is the positive z direction (we return +1) and in the 
+  // +ve endcap its in the -ve z direction (we return -1).
+  // 
+  return !(_code.isPosZ()) ? +1 : -1;
+}
+
+
+} // end namespace
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BaseElement.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BaseElement.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..f1510c83cca30261e194a29a61e69ca62aec00da
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_BaseElement.cxx
@@ -0,0 +1,340 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/SurfaceCache.h"
+#include "InDetReadoutGeometry/TRT_BaseElement.h"
+#include "InDetReadoutGeometry/TRT_Conditions.h"
+
+#include "CLHEP/Geometry/Transform3D.h"
+#include "CLHEP/Geometry/Point3D.h"
+#include "CLHEP/Geometry/Vector3D.h"
+#include "GeoPrimitives/CLHEPtoEigenConverter.h"
+
+#include "InDetIdentifier/TRT_ID.h"
+
+#include "TrkSurfaces/StraightLineSurface.h"
+#include "TrkSurfaces/Surface.h"
+
+#include <vector>
+
+namespace InDetDD {
+
+
+    TRT_BaseElement::TRT_BaseElement(const GeoVFullPhysVol *volume, const Identifier & id, const TRT_ID * idHelper, const TRT_Conditions * conditions) :
+        Trk::TrkDetElementBase(volume),
+        m_id(id),
+        m_idHelper(idHelper),
+        m_conditions(conditions),
+        m_strawSurfaces(0),
+        m_strawSurfacesCache(0),
+        m_surfaceCache(0)
+    {
+        m_idHash = m_idHelper->straw_layer_hash(id);  
+        m_conditions->ref();
+    }
+
+    Identifier TRT_BaseElement::identify() const
+    {
+        return m_id;
+    }
+
+    IdentifierHash TRT_BaseElement::identifyHash() const
+    {
+        return m_idHash;
+    }
+
+    // [0] GeoModel / CLHEP Access
+    const HepGeom::Transform3D TRT_BaseElement::getAbsoluteTransform(int straw) const 
+    {
+        return Amg::EigenTransformToCLHEP(strawTransform(straw));
+    }
+
+    // [A] description of the current detector element : Amg first, then CLHEP converted methods
+    const Trk::Surface& TRT_BaseElement::surface() const
+    {
+        return elementSurface();
+    }
+    
+    const Trk::SurfaceBounds& TRT_BaseElement::bounds() const
+    {
+        if (!m_surfaceCache) createSurfaceCache();
+        return *(m_surfaceCache->bounds());
+    }
+    
+    const Amg::Transform3D& TRT_BaseElement::transform() const
+    {	
+        if (!m_surfaceCache) createSurfaceCache();
+        return *(m_surfaceCache->transform());
+    }    
+
+
+    const Amg::Vector3D& TRT_BaseElement::center() const
+    {  
+        if (!m_surfaceCache) createSurfaceCache();
+        return *(m_surfaceCache->center());
+    }
+    
+    const Amg::Vector3D& TRT_BaseElement::normal() const
+    {
+        if (!m_surfaceCache) createSurfaceCache();
+        return *(m_surfaceCache->normal());
+    }
+    
+    // [B] Description of the individual straws
+    const Trk::Surface&  TRT_BaseElement::surface(const Identifier& id) const
+    {
+        int straw = m_idHelper->straw(id);
+        // Create vector of all straws.
+        if (!m_strawSurfaces) 
+            m_strawSurfaces = new std::vector<Trk::StraightLineSurface*>(nStraws(), 0);
+        Trk::Surface * surfacePtr = (*m_strawSurfaces)[straw];
+        if (!surfacePtr) {
+            createSurfaceCache(id);
+            surfacePtr = (*m_strawSurfaces)[straw];
+        }
+        return *surfacePtr;
+    }
+
+    const Trk::SurfaceBounds& TRT_BaseElement::bounds(const Identifier&) const 
+    {
+        return strawBounds();
+    }
+
+    const Amg::Transform3D& TRT_BaseElement::transform(const Identifier & id) const 
+    {
+        int straw = m_idHelper->straw(id);
+        if (!m_strawSurfacesCache) m_strawSurfacesCache = new std::vector<SurfaceCache*>(nStraws(), 0);
+        SurfaceCache* sCachePtr = (*m_strawSurfacesCache)[straw];
+        if (!sCachePtr) {
+            createSurfaceCache(id);
+            sCachePtr = (*m_strawSurfacesCache)[straw];
+        }
+        // forward the transform of the cache
+        return *(sCachePtr->transform());
+    }       
+
+    const Amg::Transform3D& TRT_BaseElement::strawTransform(unsigned int straw) const 
+    {
+        if (!m_strawSurfacesCache) m_strawSurfacesCache = new std::vector<SurfaceCache*>(nStraws(), 0);
+        SurfaceCache* sCachePtr = (*m_strawSurfacesCache)[straw];
+        if (!sCachePtr) {
+            Identifier id =  m_idHelper->straw_id(identify(), straw);
+            createSurfaceCache(id);
+            sCachePtr = (*m_strawSurfacesCache)[straw];
+        }
+        // forward the transform of the cache
+        return *(sCachePtr->transform());
+    }
+
+
+    const Amg::Vector3D& TRT_BaseElement::normal(const Identifier&) const
+    {
+       // Not sure if the normal of the straw is ever used.
+       // nor is there a well defined normal.
+       // This wont be corrected for alignments.
+       // Just return the element normal
+       return normal();
+    }
+
+    const Amg::Vector3D& TRT_BaseElement::center(const Identifier & id) const 
+    {
+        int straw = m_idHelper->straw(id);
+        if (!m_strawSurfacesCache) m_strawSurfacesCache = new std::vector<SurfaceCache*>(nStraws(), 0);
+        SurfaceCache* sCachePtr = (*m_strawSurfacesCache)[straw];
+        if (!sCachePtr) {
+            createSurfaceCache(id);
+            sCachePtr = (*m_strawSurfacesCache)[straw];
+        }
+        // forward the transform of the cache
+        return *(sCachePtr->center());
+    }
+    
+    const Trk::StraightLineSurface& TRT_BaseElement::strawSurface(int straw) const
+    {
+        // Create vector of all straws.
+        if (!m_strawSurfaces) 
+            m_strawSurfaces      = new std::vector<Trk::StraightLineSurface *>(nStraws(), 0);
+        Trk::StraightLineSurface* surfacePtr = (*m_strawSurfaces)[straw];
+        if (!surfacePtr) {
+            // get the straw identifier to the given straw number and element identifier
+            Identifier id =  m_idHelper->straw_id(identify(), straw);
+            createSurfaceCache(id);
+            surfacePtr = (*m_strawSurfaces)[straw];
+        }
+        return *surfacePtr;
+    }
+
+    const Amg::Transform3D& TRT_BaseElement::strawTransform(int straw) const 
+    {
+       if (!m_strawSurfacesCache) m_strawSurfacesCache = new std::vector<SurfaceCache*>(nStraws(), 0);
+       SurfaceCache* sCachePtr = (*m_strawSurfacesCache)[straw];
+       if (!sCachePtr) {
+           Identifier id =  m_idHelper->straw_id(identify(), straw);
+           createSurfaceCache(id);
+           sCachePtr = (*m_strawSurfacesCache)[straw];
+       }
+       // forward the transform of the cache
+       return *(sCachePtr->transform());
+    }
+    
+    const Amg::Vector3D& TRT_BaseElement::strawCenter(int straw) const 
+    {
+        if (!m_strawSurfacesCache) m_strawSurfacesCache = new std::vector<SurfaceCache*>(nStraws(), 0);
+        SurfaceCache* sCachePtr = (*m_strawSurfacesCache)[straw];
+        if (!sCachePtr) {
+            Identifier id =  m_idHelper->straw_id(identify(), straw);
+            createSurfaceCache(id);
+            sCachePtr = (*m_strawSurfacesCache)[straw];
+        }
+        // forward the transform of the cache
+        return *(sCachePtr->center());
+    }
+    
+    Amg::Vector3D TRT_BaseElement::strawAxis(int straw) const
+    {
+        return ( strawTransform(straw).linear()*Amg::Vector3D::UnitZ()*strawDirection() );
+    }
+
+    /// ----- can be removed after full Amg migration ----------------------- (start)
+    // [A] in CLHEP
+    
+    const HepGeom::Transform3D TRT_BaseElement::transformCLHEP() const
+    {	
+        return Amg::EigenTransformToCLHEP((*m_surfaceCache->transform()));
+    }
+
+    const HepGeom::Point3D<double> TRT_BaseElement::centerCLHEP() const
+    {
+        
+        const Amg::Vector3D& cCenter = center();
+        return HepGeom::Point3D<double>(cCenter.x(),cCenter.y(),cCenter.z());
+    }
+    
+    const HepGeom::Vector3D<double> TRT_BaseElement::normalCLHEP() const
+    {
+        const Amg::Vector3D& cNormal = normal();
+        return HepGeom::Vector3D<double>(cNormal.x(),cNormal.y(),cNormal.z());
+    }
+
+    // [B] in CLHEP
+    
+    const HepGeom::Transform3D TRT_BaseElement::transformCLHEP(const Identifier & id) const 
+    {
+        return Amg::EigenTransformToCLHEP(transform(id));
+    }
+    
+    const HepGeom::Point3D<double> TRT_BaseElement::centerCLHEP(const Identifier & id) const 
+    {
+        const Amg::Vector3D cCenter = center(id);
+        return HepGeom::Point3D<double>(cCenter.x(),cCenter.y(),cCenter.z());
+    }
+    
+    const HepGeom::Vector3D<double> TRT_BaseElement::normalCLHEP(const Identifier&) const
+    {
+        // Not sure if the normal of the straw is ever used.
+        // nor is there a well defined normal.
+        // This wont be corrected for alignments.
+        // Just return the element normal
+        return normalCLHEP();
+    }
+
+    /// ----- can be removed after full Amg migration -----------------------  (end)
+
+
+    void TRT_BaseElement::createSurfaceCache(Identifier id) const
+    {
+
+      // should not happen, but worth the protection
+      if (!m_strawSurfacesCache) m_strawSurfacesCache = new std::vector<SurfaceCache*>(nStraws(),0);
+      if (!m_strawSurfaces) m_strawSurfaces = new std::vector<Trk::StraightLineSurface*>(nStraws(), 0);
+
+      int straw =  m_idHelper->straw(id);
+
+      // get the StrawTransform from GeoModel 
+      HepGeom::Transform3D cStrawTransform = calculateStrawTransform(straw);
+
+      // convert neccessary parts to Amg
+      Amg::Transform3D* sTransform = new Amg::Transform3D(Amg::CLHEPTransformToEigen(cStrawTransform));
+      Amg::Vector3D*    sCenter    = new Amg::Vector3D(sTransform->translation());
+
+      // create the surface cache & fill it
+      SurfaceCache* sSurfaceCache     = new SurfaceCache(sTransform, sCenter, 0, 0);
+      (*m_strawSurfacesCache)[straw]  = sSurfaceCache;
+      
+      // creaete the surface only if needed (the links are still intact)
+      if (!(*m_strawSurfaces)[straw]){
+          Trk::StraightLineSurface* sSurface = new Trk::StraightLineSurface(*this, id);
+          (*m_strawSurfaces)[straw] = sSurface;
+          
+      }
+    }
+
+
+    void TRT_BaseElement::invalidate() const
+    {
+        // Invalidate the caches
+        // Call and barrel or endcap specific invalidation
+        invalidateOther();
+        // Its enough to delete and zero the caches.
+        deleteCache();
+    }
+
+    void TRT_BaseElement::deleteCache() const
+    {
+        // invalidates the cache, surface object can still live
+
+        // for all straws
+        if (m_strawSurfacesCache) {
+            for (size_t i=0; i<m_strawSurfacesCache->size(); i++) {
+                delete (*m_strawSurfacesCache)[i];
+                (*m_strawSurfacesCache)[i] = 0;
+            }
+        }
+        delete m_strawSurfacesCache;
+        m_strawSurfacesCache = 0;
+
+        // for the element surface
+        delete m_surfaceCache;
+        m_surfaceCache = 0;
+    }
+
+
+    void TRT_BaseElement::updateAllCaches() const
+    {
+        // delete the caches first
+        deleteCache();
+        // Strawlayer caches
+        if (!m_surfaceCache) createSurfaceCache();
+        // Loop over all straws and request items that get cached.
+        for (unsigned int iStraw=0; iStraw < nStraws(); iStraw++) {
+            Identifier strawId = m_idHelper->straw_id(identify(),iStraw);
+            createSurfaceCache(strawId);
+        }
+
+    }
+
+    const TRT_Conditions* TRT_BaseElement::conditions() const
+    {
+        return m_conditions;
+    }
+
+
+
+    TRT_BaseElement::~TRT_BaseElement()
+    {
+        // delete the information about the straws
+        if (m_strawSurfaces) {
+            for (size_t i=0; i<m_strawSurfaces->size(); i++) {
+                delete (*m_strawSurfaces)[i];
+            }
+        }
+        delete m_strawSurfaces;
+        deleteCache();
+        
+        m_conditions->unref();
+
+    }
+
+
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_Conditions.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_Conditions.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..ac5974f9876776e127434bf86cdca341ced76359
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_Conditions.cxx
@@ -0,0 +1,37 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/TRT_Conditions.h"
+
+namespace InDetDD {
+
+TRT_Conditions::TRT_Conditions()
+  : m_dxContainer(0)
+{}
+
+const TRTCond::StrawDxContainer* 
+TRT_Conditions::dxContainer() const
+{
+  return m_dxContainer;
+}
+
+void 
+TRT_Conditions::setDxContainer(const TRTCond::StrawDxContainer* container)
+{
+  m_dxContainer = container;
+}
+
+const HepGeom::Transform3D &
+TRT_Conditions::solenoidFrame() const
+{
+  return m_solenoidFrame;
+}
+ 
+void 
+TRT_Conditions::setSolenoidFrame(const HepGeom::Transform3D & frame)
+{
+  m_solenoidFrame = frame;
+}
+
+} // end namespace
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_DetectorManager.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_DetectorManager.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..be2a82378f2af97735f83c6e09d0e93d4ec6d2c4
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_DetectorManager.cxx
@@ -0,0 +1,642 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/TRT_DetectorManager.h"
+#include "InDetReadoutGeometry/TRT_Numerology.h"
+#include "InDetReadoutGeometry/TRT_BarrelCode.h"
+#include "InDetReadoutGeometry/TRT_EndcapCode.h"
+#include "InDetReadoutGeometry/TRT_BarrelElement.h"
+#include "InDetReadoutGeometry/TRT_EndcapElement.h"
+#include "InDetReadoutGeometry/ExtendedAlignableTransform.h"
+#include "InDetReadoutGeometry/InDetDD_Defs.h"
+#include "InDetReadoutGeometry/TRT_Conditions.h"
+
+#include "GeoModelKernel/GeoXF.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
+
+#include "GeoPrimitives/CLHEPtoEigenConverter.h"
+
+#include "DetDescrConditions/AlignableTransform.h"
+#include "DetDescrConditions/AlignableTransformContainer.h"
+
+#include "StoreGate/StoreGateSvc.h"
+
+#include "GaudiKernel/Bootstrap.h"
+#include "GaudiKernel/ISvcLocator.h"
+
+#include "TRT_ConditionsData/StrawDxContainer.h"
+
+namespace InDetDD {
+
+    const int FIRST_HIGHER_LEVEL = 1;
+
+    TRT_DetectorManager::TRT_DetectorManager(StoreGateSvc * detStore)
+        :InDetDetectorManager(detStore, "TRT"),
+        _numerology(new TRT_Numerology()),
+        m_idHelper(NULL),
+        _ownsIdHelper(false),
+        m_gasType(unknown),
+        m_digvers(9999),
+        m_digversname("ERROR:DIGVERSNOTSET!"),
+        m_conditions(0)
+    {
+
+    // If detstore no passed then get it from bootstrap.
+        if (m_detStore == 0) {
+            StatusCode sc = Gaudi::svcLocator()->service("DetectorStore", m_detStore); 
+            if (sc.isFailure()) msg(MSG::ERROR) << "Could not locate DetectorStore" << endreq;
+        }
+
+    //
+    // NULL out barrel and endcap arrays:
+    //
+        for (unsigned int ec=0;ec<2;ec++) {
+            for (unsigned int mod=0;mod<NMODMAX;mod++) {
+                for (unsigned int phi=0; phi<NPHIMAX;phi++) {
+                    for (unsigned int sLay=0;sLay<NSTRAWLAYMAXBR;sLay++) {
+                        barrelArray[ec][mod][phi][sLay]=NULL;
+                    }
+                }
+            }
+        }
+        for (unsigned int ec=0;ec<2;ec++) {
+            for (unsigned int whe=0;whe<NWHEELMAX;whe++) {
+                for (unsigned int sLay=0;sLay<NSTRAWLAYMAXEC;sLay++) {
+                    for(unsigned int phi=0;phi<NPHIMAX;phi++) {
+                        endcapArray[ec][whe][sLay][phi]=NULL;
+                    }
+                }
+            }
+        }
+        _barrelXF[0]=_barrelXF[1]=_barrelXF[2]=NULL;
+        _endcapXF[0]=_endcapXF[1]=_endcapXF[2]=NULL;
+    }
+
+
+
+    TRT_Numerology * TRT_DetectorManager::getNumerology() {
+        return _numerology;
+    }
+
+    const TRT_Numerology * TRT_DetectorManager::getNumerology() const {
+        return _numerology;
+    }
+
+    TRT_DetectorManager::~TRT_DetectorManager()
+    {
+        for (size_t i=0;i<volume.size();i++) {
+            volume[i]->unref();
+        }
+        for (unsigned int ec=0;ec<2;ec++) {
+            for (unsigned int mod=0;mod<NMODMAX;mod++) {
+                for (unsigned int phi=0; phi<NPHIMAX;phi++) {
+                    for (unsigned int sLay=0;sLay<NSTRAWLAYMAXBR;sLay++) {
+                        delete barrelArray[ec][mod][phi][sLay];
+                    }
+                }
+            }
+        }
+        for (unsigned int ec=0;ec<2;ec++) {
+            for (unsigned int whe=0;whe<NWHEELMAX;whe++) {
+                for (unsigned int sLay=0;sLay<NSTRAWLAYMAXEC;sLay++) {
+                    for(unsigned int phi=0;phi<NPHIMAX;phi++) {
+                        delete endcapArray[ec][whe][sLay][phi];
+                    }
+                }
+            }
+        }
+        delete _numerology;
+        if (_ownsIdHelper)    delete m_idHelper;
+        for (int i=0;i<3;i++) delete _barrelXF[i];
+        for (int i=0;i<3;i++) delete _endcapXF[i];
+
+
+        for (unsigned int i = 0; i < m_alignableTransforms.size(); i++) {
+            AlignableTransformMap& m = m_alignableTransforms[i];
+            for (AlignableTransformMap::iterator j = m.begin(); j != m.end(); ++j) {
+                delete j->second;
+            }
+        }
+
+        if (m_conditions) m_conditions->unref();
+
+    }
+
+
+    unsigned int TRT_DetectorManager::getNumTreeTops() const
+    {
+        return volume.size(); 
+    }
+
+    PVConstLink TRT_DetectorManager::getTreeTop(unsigned int i) const
+    {
+        return volume[i];
+    }
+
+    void  TRT_DetectorManager::addTreeTop(PVLink vol){
+        vol->ref();
+        volume.push_back(vol);
+    }
+
+    // Manage the barrel elements:
+    void TRT_DetectorManager::manageBarrelElement(TRT_BarrelElement *barrel) {
+
+        if ( barrelArray
+            [barrel->getCode().isPosZ()]
+            [barrel->getCode().getModuleIndex()]
+            [barrel->getCode().getPhiIndex()]
+            [barrel->getCode().getStrawLayerIndex()] ) {
+
+            //Element already added - complain!
+            if(msgLvl(MSG::DEBUG)) msg(MSG::DEBUG) << "manageBarrelElement: Overriding existing element"<<endreq;
+        };
+
+        barrelArray
+            [barrel->getCode().isPosZ()]
+            [barrel->getCode().getModuleIndex()]
+            [barrel->getCode().getPhiIndex()]
+            [barrel->getCode().getStrawLayerIndex()]
+            =barrel;
+
+        // Add the barrel element to the hash vector:
+        if (m_idHelper) {
+            Identifier id = m_idHelper->layer_id(barrel->getCode().isPosZ() ? +1 : -1,
+                barrel->getCode().getPhiIndex(),
+                barrel->getCode().getModuleIndex(),
+                barrel->getCode().getStrawLayerIndex());
+            IdentifierHash hashId = m_idHelper->straw_layer_hash(id);
+            if (hashId.is_valid()) {
+                if (m_elements.size() <= hashId) {
+                    m_elements.resize(static_cast<unsigned int>(hashId) + 1);
+                }
+                if (m_elements[hashId]) {
+                    //Element already added - complain!
+                    if(msgLvl(MSG::DEBUG)) 
+                        msg(MSG::DEBUG) << "manageBarrelElement: Overriding existing element for hashID"<<endreq;
+                }
+                m_elements[hashId]=barrel;
+            } else {
+                msg(MSG::WARNING) << "manageBarrelElement: Invalid identifier" << endreq;	
+            }
+
+        }
+
+    }
+
+  // Manage the endcap elements:
+    void TRT_DetectorManager::manageEndcapElement(TRT_EndcapElement *endcap) {
+
+        if ( endcapArray
+            [endcap->getCode().isPosZ()]
+            [endcap->getCode().getWheelIndex()]
+            [endcap->getCode().getStrawLayerIndex()]
+        [endcap->getCode().getPhiIndex()] ) {
+
+            //Element already added - complain!
+            if(msgLvl(MSG::DEBUG)) 
+                msg(MSG::DEBUG) << "manageEndcapElement: Overriding existing element"<<endreq;
+        };
+
+        endcapArray
+            [endcap->getCode().isPosZ()]
+            [endcap->getCode().getWheelIndex()]
+            [endcap->getCode().getStrawLayerIndex()]
+            [endcap->getCode().getPhiIndex()]
+            =endcap;
+
+        if (m_idHelper) {
+            Identifier id = m_idHelper->layer_id(endcap->getCode().isPosZ() ? +2 : -2,
+                endcap->getCode().getPhiIndex(),
+                endcap->getCode().getWheelIndex(),
+                endcap->getCode().getStrawLayerIndex());
+
+            IdentifierHash hashId = m_idHelper->straw_layer_hash(id);
+            if (hashId.is_valid()) {
+                if (m_elements.size() <= hashId) {
+                    m_elements.resize(static_cast<unsigned int>(hashId) + 1);
+                }
+                if (m_elements[hashId]) {
+                    //Element already added - complain!
+                    if(msgLvl(MSG::DEBUG))
+                        msg(MSG::DEBUG) << "manageEndcapElement: Overriding existing element for hashID"<<endreq;
+                }
+                m_elements[hashId]=endcap;
+            } else {
+                msg(MSG::WARNING) << "manageEndcapElement: Invalid identifier" << endreq;	    
+            }
+        }
+    }
+
+    const TRT_BarrelElement *TRT_DetectorManager::getBarrelElement(unsigned int positive,               
+                                                                   unsigned int moduleIndex,            
+                                                                   unsigned int phiIndex,               
+                                                                   unsigned int strawLayerIndex) const {
+        if ( positive >= 2 || moduleIndex >= NMODMAX
+            || phiIndex>=NPHIMAX || strawLayerIndex >= NSTRAWLAYMAXBR) return 0;
+
+        return barrelArray[positive][moduleIndex][phiIndex][strawLayerIndex];
+    }
+
+
+
+    TRT_BarrelElement *TRT_DetectorManager::getBarrelElement(unsigned int positive,               
+        unsigned int moduleIndex,            
+        unsigned int phiIndex,               
+        unsigned int strawLayerIndex){
+        if ( positive >= 2 || moduleIndex >= NMODMAX
+            || phiIndex>=NPHIMAX || strawLayerIndex >= NSTRAWLAYMAXBR) return 0;
+
+        return barrelArray[positive][moduleIndex][phiIndex][strawLayerIndex];
+    }
+
+
+
+
+
+    const TRT_EndcapElement *TRT_DetectorManager::getEndcapElement(unsigned int positive,               
+        unsigned int wheelIndex,             
+        unsigned int strawLayerIndex,
+        unsigned int phiIndex) const {
+
+        if ( positive >= 2 || wheelIndex >= NWHEELMAX
+            || phiIndex>=NPHIMAX || strawLayerIndex >= NSTRAWLAYMAXEC) return 0;
+
+        return endcapArray[positive][wheelIndex][strawLayerIndex][phiIndex];
+    }
+
+
+    TRT_EndcapElement *TRT_DetectorManager::getEndcapElement(unsigned int positive,               
+        unsigned int wheelIndex,             
+        unsigned int strawLayerIndex,
+        unsigned int phiIndex) {
+
+        if ( positive >= 2 || wheelIndex >= NWHEELMAX
+            || phiIndex>=NPHIMAX || strawLayerIndex >= NSTRAWLAYMAXEC) return 0;
+
+        return endcapArray[positive][wheelIndex][strawLayerIndex][phiIndex];
+    }
+
+    const TRT_ID *TRT_DetectorManager::getIdHelper() const {
+        return m_idHelper;
+    }
+
+
+    void TRT_DetectorManager::setIdHelper(const TRT_ID *idHelper, bool owns) {
+        m_idHelper=idHelper;
+        _ownsIdHelper=owns;
+    }
+
+
+
+    const TRT_BaseElement *TRT_DetectorManager::getElement(Identifier id) const {
+        // Make sure it is a straw_layer id
+        Identifier strawLayerId = m_idHelper->layer_id(id);
+        IdentifierHash hashId = m_idHelper->straw_layer_hash(strawLayerId);  
+        if (hashId>=m_elements.size()) return 0;
+        return m_elements[hashId];
+    }
+
+    const TRT_BaseElement *TRT_DetectorManager::getElement(IdentifierHash id) const {
+        if (id>=m_elements.size()) return 0;
+        return m_elements[id];
+    }
+
+
+    const TRT_DetElementCollection * TRT_DetectorManager::getDetectorElementCollection() const {
+        return &m_elements;
+    }
+
+    TRT_DetElementCollection::const_iterator TRT_DetectorManager::getDetectorElementBegin() const {
+        return m_elements.begin();
+    }
+
+    TRT_DetElementCollection::const_iterator TRT_DetectorManager::getDetectorElementEnd() const {
+        return m_elements.end();
+    }
+
+
+    void TRT_DetectorManager::setBarrelTransformField(size_t i, const GeoXF::Function * f){
+        if (_barrelXF[i]!=f)  delete  _barrelXF[i];
+        _barrelXF[i] = f;
+    }                                      
+
+    const GeoXF::Function * TRT_DetectorManager::barrelTransformField(size_t i) const {
+        return _barrelXF[i];
+    }
+
+    void TRT_DetectorManager::setEndcapTransformField(size_t i, const GeoXF::Function *f) {                                      
+        if (_endcapXF[i]!=f) delete  _endcapXF[i];
+        _endcapXF[i]=f;
+    }
+
+    const GeoXF::Function *TRT_DetectorManager::endcapTransformField(size_t i) const{
+        return _endcapXF[i];
+    }                           
+
+
+    TRT_DetectorManager::ActiveGasType TRT_DetectorManager::gasType() const
+    {
+        return m_gasType;
+    }
+
+    void TRT_DetectorManager::setGasType(const ActiveGasType & activeGasType)
+    {
+        m_gasType = activeGasType;
+    }
+
+    unsigned int TRT_DetectorManager::digitizationVersion() const
+    {
+        return m_digvers;
+    }
+
+    std::string TRT_DetectorManager::digitizationVersionName() const
+    {
+        return m_digversname;
+    }
+
+    void TRT_DetectorManager::setDigitizationVersion(const unsigned int & dv, const std::string& name )
+    {
+        m_digvers = dv; m_digversname = name;
+    }
+
+    // Register the call back for this key and the corresponding level in
+    // in the hierarchy.
+    // DEPRECATED
+    void TRT_DetectorManager::addKey(const std::string & key, int level)
+    {
+        if(msgLvl(MSG::DEBUG))
+            msg(MSG::DEBUG) << "Registering alignmentCallback with key " << key << ", at level " << level 
+            << endreq;
+
+        const DataHandle<AlignableTransform> transformCollection;  
+        m_detStore->regFcn(&TRT_DetectorManager::alignmentCallback, this, transformCollection, key);
+        addKey(key, level, InDetDD::other);
+    }
+
+    void TRT_DetectorManager::addKey(const std::string & key, int level, FrameType frame)
+    {
+        addChannel(key, level, frame);
+    }
+
+    void TRT_DetectorManager::addAlignableTransform (int level,
+                                                     const Identifier &id, 
+                                                     GeoAlignableTransform *transform,
+                                                     const GeoVPhysVol * child,
+                                                     const GeoVPhysVol * frameVol)
+    {
+        if (m_idHelper) {
+            // Check if child and frame are actually full physical volumes.
+            // if they are non zero.
+            const GeoVFullPhysVol * childFPV = 0;
+            if (child) {
+                childFPV = dynamic_cast<const GeoVFullPhysVol *>(child);
+            }
+            const GeoVFullPhysVol * frameFPV = 0; 
+            if (frameVol) {
+                frameFPV = dynamic_cast<const GeoVFullPhysVol *>(frameVol);
+            }
+            if (child && !childFPV) { 
+                msg(MSG::ERROR) 
+                    << "Child of alignable transform is not a full physical volume" 
+                    << endreq;
+            } else if (frameVol && !frameFPV) {
+                msg(MSG::ERROR) 
+                    << "Frame for alignable transform is not a full physical volume" 
+                    << endreq;
+            } else {
+                addAlignableTransform (level, id, transform, childFPV, frameFPV);
+            }
+        }
+    }
+
+    void TRT_DetectorManager::addAlignableTransform (int level,
+                                                     const Identifier &id, 
+                                                     GeoAlignableTransform *transform,
+                                                     const GeoVFullPhysVol *child,
+                                                     const GeoVFullPhysVol *frameVol)
+    {
+        if (m_idHelper) {
+            if (level == 0) {
+                // Nothing implemented. Reserved in case we want alignable straws.
+            } else {
+
+                ExtendedAlignableTransform * extAlignableTransform = new ExtendedAlignableTransform(transform, child, frameVol);
+                if(msgLvl(MSG::VERBOSE)) {
+                    msg(MSG::VERBOSE) << "TRT: Adding alignment at level " << level << " " << m_idHelper->show_to_string(id);
+                    if (child && !frameVol) {
+                        msg(MSG::VERBOSE) << " using global frame";
+                    } else if (!child || child == frameVol ) {
+                        msg(MSG::VERBOSE) << " using local frame";
+                    } else {
+                        msg(MSG::VERBOSE) << " using other frame";
+                    }
+                    msg(MSG::VERBOSE) << endreq;
+                }
+                // Save in map
+                int index = level - FIRST_HIGHER_LEVEL; // level 0 treated separately.
+                if (index >= static_cast<int>(m_alignableTransforms.size())) m_alignableTransforms.resize(index+1); 
+                m_alignableTransforms[index][id] = extAlignableTransform;
+            }  
+        }
+    }
+
+    bool TRT_DetectorManager::setAlignableTransformDelta(int level, 
+                                                         const Identifier & id, 
+                                                         const Amg::Transform3D & delta,
+                                                         FrameType frame) const
+    {
+        if (level == 0) {
+      // Nothing implemented. Reserved in case we want alignable straws
+            return false;
+        } else {
+
+            int index = level - FIRST_HIGHER_LEVEL; // level 0 treated separately.
+            if (index  >=  static_cast<int>(m_alignableTransforms.size())) return false;
+
+            // We retrieve it from a map. 
+            AlignableTransformMap::const_iterator iter;    
+            iter = m_alignableTransforms[index].find(id);
+            if (iter == m_alignableTransforms[index].end()) return false;          
+
+            return setAlignableTransformAnyFrameDelta(iter->second, delta, frame);
+
+        }
+    }
+
+    bool TRT_DetectorManager::setAlignableTransformAnyFrameDelta(ExtendedAlignableTransform * extXF, 
+                                                                 const Amg::Transform3D & delta,
+                                                                 FrameType frame) const
+    {
+    //---------------------
+    // For Local:
+    //---------------------
+    // The geomodel alignable transform delta is already a local delta so we just pass it directly
+
+    //---------------------
+    // For global frame
+    //---------------------
+    // Sets the alignable transform delta when the supplied delta is in the global frame.
+
+    // If the default transform down to the alignable transform is
+    // T = A*B*C
+    // and the alignable transform is C with delta c and the delta in the global frame is g, then
+    // A*B*C*c = g*A*B*C
+    // T*c = g*T
+    //  c = T.inverse() * g * T
+
+    // To get default transform up and including the alignable transform,
+    // we assume the next volume down is a fullphys volume and so its
+    // transform is the transform we want (ie T=A*B*C in the above example).
+
+    //---------------------
+    // For Other frame
+    //---------------------
+    // Sets the alignable transform delta when the supplied delta is in the frame of the
+    // volume "frameVol".
+
+    // If the default transform down to the alignable transform is
+    // T = A*B*C
+    // and the alignable transform is C with delta c and the delta g is expressed in the frame A, then
+    // A*B*C*c = A*g*B*C
+    // c = (BC).inverse * g * (BC)
+    // BC = A.inverse() * T
+    // C = T.inverse() * A * g * A.inverse() * T
+
+    // To get default transform up and including the alignable transform,
+    // we assume the next volume down is a fullphys volume and so its
+    // transform is the transform we want (ie T=A*B*C in the above example).
+    // The Transform to the frame is T = A which we get from the fullphys volume frameVol.
+
+        if (!extXF) return false;
+        if (!extXF->alignableTransform()) return false;
+
+        const GeoVFullPhysVol * child = extXF->child();
+        const GeoVFullPhysVol * frameVol = extXF->frame();
+
+        FrameType newFrame = frame;    
+        // If frame is other then check if "other" is actually local or global
+        if (frame == InDetDD::other) {
+            if (child && !frameVol) {
+                // frame = 0 indicates to use global frame
+                newFrame =  InDetDD::global;
+            } else if (!child || child == frameVol){
+                // if child is 0 or the they are the same volumes then its local
+                newFrame =  InDetDD::local;
+            } // else its "other" already.
+        }  
+
+        if (newFrame == InDetDD::global)  { // Global
+            if (!child) {
+                msg(MSG::ERROR) << "global frame specified, but child == 0" << endreq;
+            } else {
+                const HepGeom::Transform3D & childXF = child->getDefAbsoluteTransform();
+                extXF->alignableTransform()->setDelta(childXF.inverse() * Amg::EigenTransformToCLHEP(delta) * childXF);
+            }
+
+        } else if (frame == InDetDD::local) { // Local
+            // if its a local frame then no transform necessary. We set it directly.
+            extXF->alignableTransform()->setDelta(Amg::EigenTransformToCLHEP(delta));
+
+        } else { // Other frame
+            // if child or frame is zero it will have been set to local or global above
+            const HepGeom::Transform3D & xfChild = child->getDefAbsoluteTransform();
+            const HepGeom::Transform3D & xfFrame = frameVol->getDefAbsoluteTransform();
+            extXF->alignableTransform()->setDelta(xfChild.inverse() * xfFrame * Amg::EigenTransformToCLHEP(delta) * xfFrame.inverse() * xfChild);
+        }
+
+        return true;
+    }
+
+
+    StatusCode TRT_DetectorManager::alignmentCallback( IOVSVC_CALLBACK_ARGS_P(I,keys) )
+    {
+        return align(I, keys);
+    }
+
+
+  // We invalidate all the elements if at least one alignment changed.
+    void TRT_DetectorManager::invalidateAll() const
+    {  
+        for (TRT_DetElementCollection::const_iterator element_iter = getDetectorElementBegin();
+        element_iter != getDetectorElementEnd();
+        ++element_iter) {
+
+            if (*element_iter) {
+                (*element_iter)->invalidate();
+            }
+        }
+    }
+
+    void TRT_DetectorManager::updateAll() const
+    {  
+        for (TRT_DetElementCollection::const_iterator element_iter = getDetectorElementBegin();
+        element_iter != getDetectorElementEnd();
+        ++element_iter) {
+
+            if (*element_iter) {
+                (*element_iter)->updateAllCaches();
+            }
+        }
+    }
+
+
+    bool TRT_DetectorManager::identifierBelongs(const Identifier & id) const
+    {
+        return getIdHelper()->is_trt(id);
+    }
+
+
+    bool TRT_DetectorManager::processSpecialAlignment(const std::string & key) const
+    {
+        if(msgLvl(MSG::DEBUG))
+            msg(MSG::DEBUG) << "Processing TRT fine alignment." << endreq;
+
+        const TRTCond::StrawDxContainer* container = 0;
+        StatusCode sc = StatusCode::FAILURE;
+        if (m_detStore->contains<TRTCond::StrawDxContainer>(key)) {
+            sc = m_detStore->retrieve(container, key);
+        }
+
+        if (sc.isFailure()) {
+            if (msgLvl(MSG::INFO))
+                msg(MSG::INFO) << "Cannot find StrawDxContainer for key "
+                << key << " - no fine alignment " << endreq;
+            throw std::runtime_error("Unable to apply TRT fine alignment. This is normal for simulation");
+      //return false;
+        } else {
+
+      // Loop trough all barrel elements and pass container.
+
+            m_conditions->setDxContainer(container);
+
+            for (TRT_DetElementCollection::const_iterator element_iter = getDetectorElementBegin();
+            element_iter != getDetectorElementEnd();
+            ++element_iter) {
+                const TRT_BaseElement * element = *element_iter;
+                if (element) {
+                    element->invalidate();
+                }
+            }
+            return false; // we return false as we have already invalidated the elements
+        }
+    }
+
+
+    void TRT_DetectorManager::setConditions(TRT_Conditions * conditions)
+    {
+    // Should only be set once.
+        if (m_conditions) {
+            msg(MSG::WARNING) << "TRT_DetectorManager: Attempt to reset TRT_Conditions" << endreq;
+            return;
+        }
+        m_conditions = conditions;
+        m_conditions->ref();
+    }
+
+    const TRT_Conditions* TRT_DetectorManager::conditions() const
+    {
+        return m_conditions;
+    }
+
+} // namespace InDetDD
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_EndcapCode.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_EndcapCode.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..b9e32123d79e7e30f3467a96f7ae0fabd7120a7f
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_EndcapCode.cxx
@@ -0,0 +1,69 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/TRT_EndcapCode.h"
+#include <string>
+#include <sstream>
+
+namespace InDetDD {
+
+//
+// Mask
+//
+const int TRT_EndcapCode::Z_MASK           = 0x00000001;    // lowest six bits
+const int TRT_EndcapCode::WHEEL_MASK       = 0x0000001F;    // lowest five
+const int TRT_EndcapCode::STRAWLAYER_MASK  = 0x0000001F;    // lowest five
+const int TRT_EndcapCode::PHIPOS_MASK      = 0x0000001F; 
+
+//
+// Shifts
+//
+const int TRT_EndcapCode::Z_SHIFT           = 0;
+const int TRT_EndcapCode::WHEEL_SHIFT       = 1;
+const int TRT_EndcapCode::STRAWLAYER_SHIFT  = 6;
+const int TRT_EndcapCode::PHIPOS_SHIFT      = 11;
+
+TRT_EndcapCode::TRT_EndcapCode()
+{
+  _key = 0;
+}
+
+TRT_EndcapCode::TRT_EndcapCode(unsigned isPos, unsigned wheelIndex, unsigned strawLayerIndex, unsigned int phiIndex)
+  :
+  _key ((( isPos           & Z_MASK )          << Z_SHIFT)          | 
+	(( wheelIndex      & WHEEL_MASK )      << WHEEL_SHIFT)      | 
+	(( strawLayerIndex & STRAWLAYER_MASK ) << STRAWLAYER_SHIFT) |
+	(( phiIndex        & PHIPOS_MASK )     << PHIPOS_SHIFT))
+{
+}
+
+TRT_EndcapCode::TRT_EndcapCode(const TRT_EndcapCode &right)
+{
+  _key = right.getKey();
+}
+
+
+
+
+TRT_EndcapCode::~TRT_EndcapCode()
+{
+}
+
+
+const TRT_EndcapCode & TRT_EndcapCode::operator=(const TRT_EndcapCode &right)
+{
+  _key = right.getKey();
+  return *this;
+}
+
+
+
+std::string TRT_EndcapCode::getName() const {
+
+  std::ostringstream outputStream;
+  outputStream << this;
+  return outputStream.str();
+}
+
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_EndcapDescriptor.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_EndcapDescriptor.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..4f22b1133299fef0ddf8af9dfb5f35f8978eb039
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_EndcapDescriptor.cxx
@@ -0,0 +1,71 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/TRT_EndcapDescriptor.h"
+
+#include "TrkSurfaces/CylinderBounds.h"
+
+#include "CLHEP/Units/SystemOfUnits.h"
+
+namespace InDetDD {
+
+
+
+TRT_EndcapDescriptor::TRT_EndcapDescriptor():
+  _nStraws(0),
+  _strawPitch(0),
+  _startPhi(0),
+  _strawLength(0),
+  _innerRadius(0),
+  m_innerTubeRadius(2*CLHEP::mm),  // FIXME: Hardwired for now!!
+  _f(NULL),
+  _o(0),
+  m_bounds(0)
+{
+
+}
+
+
+TRT_EndcapDescriptor::~TRT_EndcapDescriptor()
+{
+  delete m_bounds;
+}
+
+
+
+void TRT_EndcapDescriptor::setStrawTransformField(const GeoXF::Function *xf, size_t offsetInto) {
+  _f=xf;
+  _o=offsetInto;
+}
+
+
+
+unsigned int  &TRT_EndcapDescriptor::nStraws() {
+  return _nStraws;
+}
+
+double & TRT_EndcapDescriptor::strawPitch() {
+  return _strawPitch;
+}
+
+double & TRT_EndcapDescriptor::startPhi() {
+  return _startPhi;
+}
+  
+double & TRT_EndcapDescriptor::strawLength() {
+  return _strawLength;
+}
+  
+double &  TRT_EndcapDescriptor::innerRadius() {
+  return _innerRadius;
+}
+
+const Trk::SurfaceBounds & 
+TRT_EndcapDescriptor::strawBounds() const
+{
+  if (!m_bounds) m_bounds = new Trk::CylinderBounds(m_innerTubeRadius, 0.5*_strawLength);
+  return *m_bounds;
+}
+
+}
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_EndcapElement.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_EndcapElement.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..c9c905884c9b72624a7585871f14531e0082500e
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_EndcapElement.cxx
@@ -0,0 +1,260 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/TRT_EndcapElement.h"
+#include "InDetReadoutGeometry/SurfaceCache.h"
+#include "InDetReadoutGeometry/TRT_Conditions.h"
+
+#include "InDetIdentifier/TRT_ID.h"
+#include "Identifier/Identifier.h"
+
+#include "GeoPrimitives/GeoPrimitives.h"
+#include "GeoPrimitives/CLHEPtoEigenConverter.h"
+
+#include "CLHEP/Geometry/Transform3D.h"
+
+#include "TrkSurfaces/DiscBounds.h"
+#include "TrkSurfaces/DiscSurface.h"
+
+#include "TRT_ConditionsData/ExpandedIdentifier.h"
+#include "TRT_ConditionsData/StrawDxContainer.h"
+
+
+namespace InDetDD {
+
+    TRT_EndcapElement::TRT_EndcapElement(const GeoVFullPhysVol *volume, 
+                                         const TRT_EndcapDescriptor *descriptor, 
+                                         bool isPositive, 
+                                         unsigned int wheelIndex, 
+                                         unsigned int strawLayIndex, 
+                                         unsigned int phiIndex,
+                                         const TRT_ID * idHelper,
+                                         const TRT_Conditions * conditions) :
+        TRT_BaseElement(volume,
+        idHelper->layer_id((isPositive ? 2:-2), phiIndex, wheelIndex, strawLayIndex),
+        idHelper, conditions),
+        _code(isPositive,wheelIndex,strawLayIndex,phiIndex),
+        _descriptor(descriptor),
+        _nextInZ(NULL),
+        _previousInZ(NULL),
+        m_surface(0)
+
+    {
+        _descriptor->ref();
+    }
+
+
+    TRT_EndcapElement::~TRT_EndcapElement()
+    {
+        _descriptor->unref();
+        delete m_surface;
+    }
+
+    unsigned int TRT_EndcapElement::nStraws() const
+    {
+        return _descriptor->nStraws();
+    }
+
+    const double & TRT_EndcapElement::strawLength() const
+    {
+        return _descriptor->strawLength();
+    }  
+
+
+    const TRT_EndcapConditions * TRT_EndcapElement::getConditionsData() const
+    {
+        return NULL;
+    }
+
+    const TRT_EndcapDescriptor * TRT_EndcapElement::getDescriptor() const
+    {
+        return _descriptor;
+    }
+
+    void TRT_EndcapElement::setNextInZ(const TRT_EndcapElement *element)
+    {
+        _nextInZ=element;
+    }
+
+    void TRT_EndcapElement::setPreviousInZ(const TRT_EndcapElement *element)
+    {
+        _previousInZ=element;
+    }
+
+
+    HepGeom::Transform3D TRT_EndcapElement::calculateStrawTransform(int straw) const 
+    {
+        // NB The tranformation to a straw is reconstructed here precisely as
+        // it was ... hopefully... in the factory.  One could eliminate this 
+        // requirement and make the code a little more robust in this regard but
+        // at the cost of doubling the descriptors.  (One descriptor now suffices
+        // for both positive and negative endcaps).
+        const GeoXF::Function *f= _descriptor->getStrawTransform();
+
+        if (f) {
+            int istraw = _code.isPosZ() ? straw : _descriptor->nStraws()-1 - straw;
+
+            size_t offsetInto = _descriptor->getStrawTransformOffset();
+
+            return getMaterialGeom()->getAbsoluteTransform()*((*f)(istraw+offsetInto)) * calculateLocalStrawTransform(straw);
+            ////return conditions()->solenoidFrame() 
+            ////  * getMaterialGeom()->getAbsoluteTransform()*((*f)(istraw+offsetInto));
+
+        } else {
+
+            // Will not work properly with alignments.
+            std::cout << "ALTERNATIVE METHOD" << std::endl;
+
+            double phi = _descriptor->startPhi() +  _descriptor->strawPitch() * straw;
+            double r = _descriptor->innerRadius() + 0.5 * _descriptor->strawLength() ;
+            CLHEP::Hep3Vector pos(r*cos(phi), r*sin(phi), (getMaterialGeom()->getAbsoluteTransform()*HepGeom::Point3D<double>()).z());
+            CLHEP::HepRotation rot;
+            // Axis (in local (0,0,1)) points towards beam axis.
+            rot.rotateY(-0.5*M_PI); // Make it point along -ve X.
+            rot.rotateZ(phi);
+            return HepGeom::Transform3D(rot, pos);
+        }
+
+    }
+
+    // The L3 Alignment 
+    HepGeom::Transform3D TRT_EndcapElement::calculateLocalStrawTransform(int straw) const
+    {
+        const TRTCond::StrawDxContainer* container = conditions()->dxContainer();
+        HepGeom::Transform3D rc ;
+        if (container) {
+
+            // important note: dx1 moves the 'negative' wire endpoint end dx2
+            // the 'positive' wire endpoint in the local straw frame. 
+            // In the global frame, 'dx1' corresponds to the readout side and 'dx2'
+            // to the side closest the beampipe.
+
+            int bec = getCode().isPosZ() ? +2 : -2 ;
+            int wheel = getCode().getWheelIndex();
+            int phimodule = getCode().getPhiIndex();
+            int strawlayer = getCode().getStrawLayerIndex();
+            TRTCond::ExpandedIdentifier id = TRTCond::ExpandedIdentifier(bec
+                ,wheel
+                ,phimodule
+                ,strawlayer
+                ,straw
+                ,TRTCond::ExpandedIdentifier::STRAW);
+
+            double dx1 = container->getDx1(id);
+            double dx2 = container->getDx2(id);
+            double ang = (dx2-dx1)/strawLength();
+            double dy = -1*(dx2+dx1)/2.;
+
+            // In the local straw frame:
+            //   - the z-axis is along the straw and points toward the beampipe
+            //   - the x-axis is along global-z and away from the interaction point 
+            //          (locX = globZ A-side / locX = -1 *gobZ C-side) 
+            //   - the y-axis is along global phi_hat direction determined by the other 2. 
+            //          (clockwise C-side, counter clockwise A-Side)
+            rc = HepGeom::TranslateY3D(dy)*HepGeom::RotateX3D(ang) ;
+        }
+        return rc ;
+    }
+
+    HepGeom::Transform3D TRT_EndcapElement::defStrawTransform(int straw) const 
+    {
+        // Same as calculateStrawTransform, except we use getDefAbsoluteTransform()
+        // rather than  getAbsoluteTransform()
+        
+        // NB The tranformation to a straw is reconstructed here precisely as
+        // it was ... hopefully... in the factory.  One could eliminate this 
+        // requirement and make the code a little more robust in this regard but
+        // at the cost of doubling the descriptors.  (One descriptor now suffices
+        // for both positive and negative endcaps).
+
+        const GeoXF::Function *f= _descriptor->getStrawTransform();
+
+        if (f) {
+
+            int istraw = _code.isPosZ() ? straw : _descriptor->nStraws()-1 - straw;
+
+            size_t offsetInto = _descriptor->getStrawTransformOffset();
+            return getMaterialGeom()->getDefAbsoluteTransform()*((*f)(istraw+offsetInto));
+
+        } else {
+
+            double phi = _descriptor->startPhi() +  _descriptor->strawPitch() * straw;
+            double r = _descriptor->innerRadius() + 0.5 * _descriptor->strawLength() ;
+            CLHEP::Hep3Vector pos(r*cos(phi), r*sin(phi), (getMaterialGeom()->getDefAbsoluteTransform()*HepGeom::Point3D<double>()).z());
+            CLHEP::HepRotation rot;
+            rot.rotateY(-0.5*M_PI); // Make it point along -ve X.
+            rot.rotateZ(phi);
+            return HepGeom::Transform3D(rot, pos);
+        }
+
+    }
+
+    const Trk::SurfaceBounds& TRT_EndcapElement::strawBounds() const
+    {
+        return _descriptor->strawBounds();
+    }
+
+    const Trk::Surface& TRT_EndcapElement::elementSurface() const 
+    {
+        if (!m_surface) m_surface = new Trk::DiscSurface(*this);
+        return *m_surface;
+    }
+
+    void TRT_EndcapElement::createSurfaceCache() const
+    {
+        // Calculate the surface 
+        double phiCenter = _descriptor->startPhi() +  _descriptor->strawPitch() * 0.5*(nStraws()-1);
+        double phiHalfWidth = 0.5 * _descriptor->strawPitch() * nStraws();
+        double rMin = _descriptor->innerRadius();
+        double rMax = rMin +_descriptor->strawLength();
+
+        // The transform of the endcap is a translation in z for no
+        // misalignement. For the -ve endcap there is also a 180deg rotation
+        // around the y axis. getAbsoluteTransform() will also include the
+        // misalignment.  
+        //
+        // To get the transform of the element we have to first rotate
+        // around z to the phi center of the element.  We want the local z
+        // to point in the same direction for both endcaps (approximately
+        // global z axis). For the negative endcap we therefore have to
+        // rotate 180 CLHEP::deg around the Y axis.
+        
+        // We need to rotate to phi center before we apply the
+        // misalignment. However, in the negative endcap the the phi
+        // location is inverted (due to 180 rotation around y axis). This is
+        // taken care of by the extra 180 CLHEP::deg rotation around Y that we do
+        // to get the z axis pointing in the correct direction.
+
+        Amg::Transform3D * transform = 0;
+        if  (_code.isPosZ())
+            transform = new Amg::Transform3D(Amg::CLHEPTransformToEigen( (getMaterialGeom()->getAbsoluteTransform() * HepGeom::RotateZ3D(phiCenter))));
+        else
+            transform = new Amg::Transform3D(Amg::CLHEPTransformToEigen( (getMaterialGeom()->getAbsoluteTransform() * HepGeom::RotateY3D(180*CLHEP::deg) * HepGeom::RotateZ3D(phiCenter))));
+
+        // create the igredients and the cache
+        Trk::DiscBounds* bounds = new Trk::DiscBounds(rMin, rMax, phiHalfWidth);
+        Amg::Vector3D*  center = new Amg::Vector3D(transform->translation());
+        Amg::Vector3D*  normal = new Amg::Vector3D(transform->rotation().col(2));
+        m_surfaceCache = new SurfaceCache(transform, center, normal, bounds);
+        // create the surface if needed 
+        if (!m_surface) m_surface = new Trk::DiscSurface(*this);
+
+    }
+
+
+
+    int TRT_EndcapElement::strawDirection() const
+    {
+  // Return +1 if the straw local axis is in the same direction as increasing eta direction,
+  //  -1 otherwise.
+  // The straw axis by convention goes in the direction away from the readout. This is
+  // towards the beam pipe. For +ve endcap it is what we want. For -ve endcap it is oppposite.
+  // 
+  // 
+        return (_code.isPosZ()) ? +1 : -1;
+    }
+
+} // end namespace
+
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_Numerology.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_Numerology.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..aa7ee5b73519cf159b5337bdf3efc4bfe65ccb93
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/TRT_Numerology.cxx
@@ -0,0 +1,50 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/TRT_Numerology.h"
+namespace InDetDD {
+
+TRT_Numerology::TRT_Numerology() :
+  _nringBarrel(0),
+  _nphiBarrel(0),
+  _nwheelEndcap(0),
+  _nphiEndcap(0)
+{
+  // Zero out the arrays
+  for (int i = 0; i < 3; i++) {
+    _nlayerBarrel[i] = 0;
+  }
+  for (int j = 0; j < 18; j++) {
+    _nlayerEndcap[j] = 0;
+  }    
+}
+
+TRT_Numerology::~TRT_Numerology() {
+}
+
+void TRT_Numerology::setNBarrelLayers(unsigned int module, unsigned int nLayers) {
+  _nlayerBarrel[module]=nLayers;
+}
+
+void TRT_Numerology::setNEndcapLayers(unsigned int wheel, unsigned int nLayers) {
+  _nlayerEndcap[wheel]=nLayers;
+}
+
+void TRT_Numerology::setNBarrelRings(unsigned int ring) {
+  _nringBarrel = ring;
+}
+
+void TRT_Numerology::setNBarrelPhi(unsigned int phi) {
+  _nphiBarrel = phi;
+}
+
+void TRT_Numerology::setNEndcapWheels(unsigned int wheel) {
+  _nwheelEndcap = wheel;
+}
+
+void TRT_Numerology::setNEndcapPhi(unsigned int phi) {
+  _nphiEndcap = phi;
+}
+}
+
diff --git a/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/Version.cxx b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/Version.cxx
new file mode 100755
index 0000000000000000000000000000000000000000..44e21ba143cb21385b3184623153acd45fcb5594
--- /dev/null
+++ b/InnerDetector/InDetDetDescr/InDetReadoutGeometry/src/Version.cxx
@@ -0,0 +1,121 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "InDetReadoutGeometry/Version.h"
+
+#include <sstream>
+#include <string>
+#include <iomanip>
+
+namespace InDetDD {
+
+Version::Version(const std::string & tag, 
+		 const std::string & name, 
+		 const std::string & layout, 
+		 const std::string & description, 
+		 int major,
+		 int minor,
+		 int patch)
+  : m_tag(tag),
+    m_name(name),
+    m_layout(layout),
+    m_description(description),
+    m_major(major),
+    m_minor(minor),
+    m_patch(patch)
+{}
+
+// For backward compatibility
+Version::Version(const std::string & name, 
+		 const std::string & layout, 
+		 const std::string & description, 
+		 int major,
+		 int minor,
+		 int patch)
+  : m_tag("-"),
+    m_name(name),
+    m_layout(layout),
+    m_description(description),
+    m_major(major),
+    m_minor(minor),
+    m_patch(patch)
+{}
+
+
+
+Version::Version()
+  : m_major(0),
+    m_minor(0),
+    m_patch(0)
+{}
+
+const std::string & 
+Version::tag() const 
+{
+  return m_tag;
+}
+
+const std::string & 
+Version::name() const 
+{
+  return m_name;
+}
+
+const std::string & 
+Version::layout() const 
+{
+  return m_layout;
+}
+
+const std::string & 
+Version::description() const 
+{
+  return m_description;
+}
+
+int 
+Version::majorNum() const 
+{
+  return m_major;
+}
+
+int 
+Version::minorNum() const 
+{
+  return m_minor;
+}
+
+int 
+Version::patchNum() const 
+{
+  return m_patch;
+}
+
+std::string 
+Version::versionNumber() const
+{
+  std::ostringstream ostr;
+  ostr << m_major 
+       << "." << std::setfill('0') << std::setw(2) << m_minor 
+       << "." << std::setfill('0') << std::setw(2) << m_patch;
+  return ostr.str();
+}
+
+std::string  
+Version::fullDescription() const 
+{
+
+  //  Output of the form
+  //  Version: SCT-DC1-00, Name: DC1, Layout: Final, Code Version: 02.01.01, Description: DC1 Geometry
+
+  std::ostringstream ostr;
+  ostr << "Version: " << m_tag << ", Name: " << m_name << ", Layout: " << m_layout 
+       << ", Code Version: " << versionNumber();
+  if (!m_description.empty()) { 
+    ostr << ", Description: " << m_description;
+  }
+  return ostr.str();
+}
+
+} // namespace InDetDD