diff --git a/HighGranularityTimingDetector/HGTD_Conditions/README.md b/HighGranularityTimingDetector/HGTD_Conditions/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0397769e8fc474660ade35b4706a2e2799fd5f80
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_Conditions/README.md
@@ -0,0 +1 @@
+For now this dir holds empty folders representing the future HGTD packages in 21.9
\ No newline at end of file
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/CMakeLists.txt b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..58ae922647c4681f6282a6f3b00c31e76bbad7a7
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/CMakeLists.txt
@@ -0,0 +1,44 @@
+################################################################################
+# Package: HGTD_GeoModel
+################################################################################
+
+# Declare the package name:
+atlas_subdir( HGTD_GeoModel )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaKernel
+                          DetectorDescription/GeoModel/GeoModelUtilities
+                          GaudiKernel
+                          InnerDetector/InDetDetDescr/InDetGeoModelUtils
+                          HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/HGTD_ReadoutGeometry
+                          PRIVATE
+                          Control/SGTools
+                          Control/StoreGate
+                          Database/AthenaPOOL/AthenaPoolUtilities
+                          DetectorDescription/DetDescrCond/DetDescrConditions
+                          InnerDetector/InDetDetDescr/PixelReadoutGeometry
+                          InnerDetector/InDetDetDescr/InDetReadoutGeometry
+                          DetectorDescription/GeoModel/GeoModelInterfaces
+                          DetectorDescription/GeometryDBSvc
+                          DetectorDescription/Identifier )
+
+# External dependencies:
+find_package( Boost COMPONENTS filesystem thread system )
+find_package( CLHEP )
+find_package( Eigen )
+find_package( CORAL COMPONENTS CoralBase CoralKernel RelationalAccess )
+
+# Component(s) in the package:
+atlas_add_library( HGTD_GeoModelLib
+                   src/*.cxx
+                   PUBLIC_HEADERS HGTD_GeoModel
+                   INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}
+                   DEFINITIONS ${CLHEP_DEFINITIONS}
+                   LINK_LIBRARIES ${Boost_LIBRARIES} ${CORAL_LIBRARIES} ${CLHEP_LIBRARIES} AthenaKernel GeoModelUtilities GaudiKernel InDetGeoModelUtils PixelReadoutGeometry InDetReadoutGeometry HGTD_ReadoutGeometryLib StoreGateLib SGtests
+                   PRIVATE_LINK_LIBRARIES SGTools AthenaPoolUtilities DetDescrConditions Identifier )
+
+atlas_add_component( HGTD_GeoModel
+                     src/components/*.cxx
+                     INCLUDE_DIRS ${Boost_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS}
+                     LINK_LIBRARIES ${Boost_LIBRARIES} ${CORAL_LIBRARIES} ${CLHEP_LIBRARIES} AthenaKernel GeoModelUtilities GaudiKernel InDetGeoModelUtils HGTD_ReadoutGeometryLib SGTools AthenaPoolUtilities DetDescrConditions StoreGateLib SGtests Identifier HGTD_GeoModelLib )
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/HGTD_GeoModel/HGTD_DetectorFactory.h b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/HGTD_GeoModel/HGTD_DetectorFactory.h
new file mode 100644
index 0000000000000000000000000000000000000000..eedd7d57499197000e5ed6c94e1e3b7736157884
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/HGTD_GeoModel/HGTD_DetectorFactory.h
@@ -0,0 +1,107 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef HGTD_GEOMODEL_HGTD_DETECTORFACTORY_H
+#define HGTD_GEOMODEL_HGTD_DETECTORFACTORY_H
+//
+//    Main routine to build the GeoModel geometry, and handle the GeometryManager and
+//    DetectorManager.
+//
+#include "StoreGate/DataHandle.h"
+#include "GeoModelKernel/GeoFullPhysVol.h"
+#include "GeoModelInterfaces/StoredMaterialManager.h"
+#include "InDetGeoModelUtils/InDetDetectorFactoryBase.h"
+#include "HGTD_ReadoutGeometry/HGTD_DetectorManager.h"
+
+namespace InDetDD {
+    class AthenaComps;
+    class PixelModuleDesign;
+}
+class GeoPhysVol;
+
+namespace HGTDGeo {
+
+struct HgtdGeoParams {
+    double rMid;
+    double rOuter;
+    double diskRotation;
+    double rowSpaceSide;
+    double rowBacksideInnerShift;
+    double rowBacksideOuterShift;
+    double moduleSpaceInner;
+    double moduleSpaceOuter;
+    double flexSheetSpacing;
+};
+
+struct ModulePosition {
+    double x;
+    double y;
+    double phiRotation;
+    bool flipped;
+    int row;
+    int el_in_row;
+};
+
+struct GeoCylVolParams {
+    std::string name;
+    double rMin;
+    double rMax;
+    double zHalf;
+    double zOffsetLocal;
+    std::string material;
+};
+
+struct GeoBoxVolParams {
+    std::string name;
+    double xHalf;
+    double yHalf;
+    double zHalf;
+    double zOffsetLocal;
+    std::string material;
+};
+
+
+class HGTD_DetectorFactory : public InDetDD::DetectorFactoryBase {
+public:
+    HGTD_DetectorFactory(InDetDD::AthenaComps *athenaComps, bool fullGeo);
+    virtual ~HGTD_DetectorFactory();
+
+    // Creation of geometry:
+    virtual void create(GeoPhysVol *world);
+
+    // Access to the results:
+    virtual HGTD_DetectorManager* getDetectorManager() const;
+
+    void setHGTDBaseline(bool flag) {m_HGTD_isbaseline = flag;}
+
+private:
+    // Copy and assignments operations illegal and so are made private
+    HGTD_DetectorFactory(HGTD_DetectorFactory &right);
+    HGTD_DetectorFactory & operator=(HGTD_DetectorFactory &right);
+
+    GeoFullPhysVol* createEnvelope(bool bPos);
+
+    HGTD_DetectorManager* m_detectorManager;
+    InDetDD::AthenaComps* m_athenaComps;
+
+    bool m_fullGeo;  // true->FULL, false->RECO
+
+    // this is for the HGTD readout definition
+    bool m_HGTD_isbaseline;
+
+    std::map<std::string,GeoCylVolParams> m_cylVolPars;
+    std::map<std::string,GeoBoxVolParams> m_boxVolPars;
+    HgtdGeoParams m_hgtdPars;
+
+    void buildHgtdGeoTDR(const DataHandle<StoredMaterialManager>& matmanager, GeoFullPhysVol* parent, bool bPos);
+    std::vector<ModulePosition> calculateHgtdModulePositionsInQuadrant(int layer);
+    std::vector<ModulePosition> calculateHgtdModulePositionsInRow(int row, bool back = false);
+
+    InDetDD::PixelModuleDesign* createPixelDesign(double thickness, bool isBaseline = true, bool isflipped = false);
+
+};
+
+} // End HGTDGeo namespace
+
+#endif // HGTD_GEOMODEL_HGTD_DETECTORFACTORY_H
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/HGTD_GeoModel/HGTD_DetectorTool.h b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/HGTD_GeoModel/HGTD_DetectorTool.h
new file mode 100644
index 0000000000000000000000000000000000000000..0d6e30591caf9eaa0dcc7f59724b6cb4287c2006
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/HGTD_GeoModel/HGTD_DetectorTool.h
@@ -0,0 +1,58 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef HGTD_GEOMODEL_HGTD_DETECTORTOOL_H
+#define HGTD_GEOMODEL_HGTD_DETECTORTOOL_H
+//
+//    Create an Athena Tool; handle Athena services and Tools needed for 
+//    building the HGTD geometry. Then create the geometry using the HGTD_DetectorFactory.
+//    This is the entry to the HGTD_GeoModel package.
+//
+#include "GeoModelUtilities/GeoModelTool.h"
+// #include "PixelInterfaces/IGeoPixelLayerTool.h"
+#include "GaudiKernel/ServiceHandle.h"
+#include "GaudiKernel/ToolHandle.h"
+
+#include <string>
+
+namespace InDetDD {
+    class AthenaComps;
+}
+
+class HGTD_DetectorManager;
+class IGeoModelSvc;
+class IRDBAccessSvc;
+class IGeometryDBSvc;
+
+/** @class HGTD_DetectorTool
+    @brief HGTD_DetectorTool is a standard GeoModel tool, which calls HGTD_DetectorFactory::create(),
+    stores HGTD_DetectorManager to the Detector Store and also registers a callback function
+    align() which applies misalignments on top of the 'regular' geometry.
+*/
+class HGTD_DetectorTool : public GeoModelTool {
+public:
+    HGTD_DetectorTool(const std::string &type, const std::string &name, const IInterface *parent);
+    virtual ~HGTD_DetectorTool();
+    virtual StatusCode create(StoreGateSvc* detStore);
+    virtual StatusCode clear(StoreGateSvc* detStore);
+    virtual StatusCode registerCallback(StoreGateSvc* detStore);
+    virtual StatusCode align(IOVSVC_CALLBACK_ARGS_P(I,keys));
+
+private:
+    std::string m_detectorName;
+    bool m_alignable;
+    const HGTD_DetectorManager *m_manager;
+    InDetDD::AthenaComps *m_athenaComps;
+    ServiceHandle<IGeoModelSvc> m_geoModelSvc;
+    ServiceHandle<IRDBAccessSvc> m_rdbAccessSvc;
+    ServiceHandle<IGeometryDBSvc> m_geometryDBSvc;
+
+    std::string m_geometryConfig; // FULL, SIMU, RECO
+
+    // this is for the HGTD readout definition
+    bool m_HGTD_isbaseline;
+
+};
+
+#endif // HGTD_GEOMODEL_HGTD_DETECTORTOOL_H
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/HGTD_DetectorFactory.cxx b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/HGTD_DetectorFactory.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..f7995e23fe58774183324073a64916a39ca49aa7
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/HGTD_DetectorFactory.cxx
@@ -0,0 +1,1052 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "HGTD_GeoModel/HGTD_DetectorFactory.h"
+
+#include <string>
+#include <sstream>
+
+#include "StoreGate/StoreGateSvc.h" // For alignment getAlignableFolderType()
+#include "AthenaPoolUtilities/CondAttrListCollection.h"
+#include "DetDescrConditions/AlignableTransformContainer.h"
+
+#include "InDetGeoModelUtils/InDetDDAthenaComps.h"
+#include "GeoModelKernel/GeoNameTag.h"
+#include "GeoModelKernel/GeoTransform.h"
+#include "GeoModelKernel/GeoAlignableTransform.h"
+#include "GeoModelKernel/GeoTorus.h"
+#include "GeoModelKernel/GeoTube.h"
+#include "GeoModelKernel/GeoBox.h"
+#include "GeoModelKernel/GeoPhysVol.h"
+#include "GeoModelKernel/GeoFullPhysVol.h"
+#include "GeoModelInterfaces/IGeoModelSvc.h"
+#include "GeoModelUtilities/DecodeVersionKey.h"
+#include "GeoModelUtilities/StoredPhysVol.h"
+#include "GeoModelUtilities/StoredAlignX.h"
+
+#include "HGTD_ReadoutGeometry/HGTD_DetectorManager.h"
+
+#include "PixelReadoutGeometry/PixelModuleDesign.h"
+#include "PixelReadoutGeometry/PixelDiodeMatrix.h"
+
+#include "RDBAccessSvc/IRDBAccessSvc.h"
+#include "RDBAccessSvc/IRDBRecordset.h"
+#include "RDBAccessSvc/IRDBRecord.h"
+
+using namespace std;
+
+namespace HGTDGeo {
+
+HGTD_DetectorFactory::HGTD_DetectorFactory(InDetDD::AthenaComps* athenaComps, bool fullGeo) :
+    InDetDD::DetectorFactoryBase(athenaComps),
+    m_detectorManager(),
+    m_athenaComps(athenaComps),
+    m_fullGeo(fullGeo),
+    m_HGTD_isbaseline(true)
+{
+//
+//    Create the detector manager
+//
+    m_detectorManager = new HGTD_DetectorManager();
+//
+//    Set Detector Manager HGTD version information
+//
+
+}
+
+HGTD_DetectorFactory::~HGTD_DetectorFactory() {
+    // NB the detector manager (m_detectorManager) is stored in the detector store by the Tool and so we don't delete it.
+}
+
+void HGTD_DetectorFactory::create(GeoPhysVol* world) {
+
+    GeoFullPhysVol* HGTD_EnvelopePos = createEnvelope(true);
+    GeoFullPhysVol* HGTD_EnvelopeNeg = createEnvelope(false);
+
+    world->add(new GeoNameTag("HGTD"));
+
+    // TODO: deal with recording "StoredPhysVol" and "StoredAlignX" (xfHGTDPos + xfHGTDNeg)
+
+    world->add( new GeoNameTag("HGTD_Pos"));
+    world->add(HGTD_EnvelopePos);
+    world->add( new GeoNameTag("HGTD_Neg"));
+    world->add( new GeoTransform(HepGeom::RotateY3D(180.0*CLHEP::deg)));
+    world->add(HGTD_EnvelopeNeg);
+
+    m_detectorManager->addTreeTop(HGTD_EnvelopePos);
+    m_detectorManager->addTreeTop(HGTD_EnvelopeNeg);
+
+}
+
+GeoFullPhysVol* HGTD_DetectorFactory::createEnvelope(bool bPos) {
+
+    // the envelope to be returned
+    GeoFullPhysVol *world_physical_hgtd = nullptr;
+
+    // Get the materials from the material manager:-----------------------------------------------------//
+    //                                                                                                  //
+    DataHandle<StoredMaterialManager> materialManager;
+    if (StatusCode::SUCCESS != detStore()->retrieve(materialManager, std::string("MATERIALS"))) return nullptr;
+
+    std::string AtlasVersion = m_athenaComps->geoModelSvc()->atlasVersion();
+    std::string LArVersion = m_athenaComps->geoModelSvc()->LAr_VersionOverride();
+
+    std::string detectorKey  = LArVersion.empty() ? AtlasVersion : LArVersion;
+    std::string detectorNode = LArVersion.empty() ? "ATLAS" : "LAr";
+
+    //__________________________ HGTD+moderator+JM tube _____________________________________
+    std::string hgtdTag = m_athenaComps->rdbAccessSvc()->getChildTag("HGTD", detectorKey, detectorNode);
+    msg(MSG::INFO) << "HGTD tag read out from the geo db: " << hgtdTag << endmsg;
+
+    // the new geometry
+    bool hgtdTiming    = (hgtdTag.find("Timing") != std::string::npos);
+    bool hgtdPreshower = (hgtdTag.find("Preshower") != std::string::npos);
+    bool hgtdTDR       = (hgtdTag.find("TDR") != std::string::npos);
+    bool hgtdTDR2      = (hgtdTDR && (hgtdTag.find("TDR-00") == std::string::npos)); // if later than HGTD-TDR-00
+
+    // detailed geometry to be used for TDR samples
+    if ( hgtdTDR ) {
+
+        // now extract the relevant parameters from the db, first the tubs, i.e. cylinder-like volumes
+        IRDBRecordset_ptr hgtdTubs   = m_athenaComps->rdbAccessSvc()->getRecordsetPtr("HGTDTubs", detectorKey, detectorNode);
+        for (IRDBRecordset::const_iterator it = hgtdTubs->begin(); it != hgtdTubs->end(); it++) {
+            std::string name = (*it)->getString("TUBE");
+            m_cylVolPars[name] = { name,
+                                   (*it)->getDouble("RMIN"),
+                                   (*it)->getDouble("RMAX"),
+                                   (*it)->getDouble("DZ"),
+                                   (*it)->getDouble("ZPOS"), // only the mother volume has meaningful z position info in the db, rest not used
+                                   (*it)->getString("MATERIAL") };
+
+            msg(MSG::INFO) << "Read " << name << " from db: rMin = " << m_cylVolPars[name].rMin << " mm, rMax = " << m_cylVolPars[name].rMax
+                           << " mm, zHalf = " << m_cylVolPars[name].zHalf << " mm, zOffsetLocal = " << m_cylVolPars[name].zOffsetLocal
+                           << " mm, material = \"" << m_cylVolPars[name].material << "\"" << endmsg;
+        }
+        // then the boxes
+        IRDBRecordset_ptr hgtdBoxes   = m_athenaComps->rdbAccessSvc()->getRecordsetPtr("HGTDBox", detectorKey, detectorNode);
+        for (IRDBRecordset::const_iterator it = hgtdBoxes->begin(); it != hgtdBoxes->end(); it++) {
+            std::string name = (*it)->getString("BOX");
+            m_boxVolPars[name] = { name,
+                                   (*it)->getDouble("DX"),
+                                   (*it)->getDouble("DY"),
+                                   (*it)->getDouble("DZ"),
+                                   (*it)->getDouble("ZPOS"),
+                                   (*it)->getString("MATERIAL") };
+
+            msg(MSG::INFO) << "Read " << name << " from db: xHalf = " << m_boxVolPars[name].xHalf << " mm, yHalf = " << m_boxVolPars[name].yHalf
+                           << " mm, zHalf = " << m_boxVolPars[name].zHalf << " mm, zOffsetLocal = " << m_boxVolPars[name].zOffsetLocal
+                           << " mm, material = \"" << m_boxVolPars[name].material << "\"" << endmsg;
+        }
+
+        // these aren't in the db yet or are incorrect as of now, need to be added by hand for now
+        m_cylVolPars["HGTD::PeriphElec"].zHalf = 1.;
+        m_cylVolPars["HGTD::PeriphElec"].zOffsetLocal = 2.;//space wrt cooling layer
+        m_cylVolPars["HGTD_mother"].rMin= 100;
+        m_cylVolPars["HGTD::ToleranceBack"].rMax= 900;
+        m_cylVolPars["HGTD::InnerRCover"]  = {"HGTD::InnerRCover", 115., 120., 105./2, -10., "sct::CFiberSupport"}; // not yet in db!
+        m_cylVolPars["HGTD::OuterRCover"]  = {"HGTD::OuterRCover", 995., 1000., 82./2, -6.5, "sct::CFiberSupport"}; // not yet in db!
+        m_cylVolPars["HGTD::CoolingTube"] = {"HGTD::CoolingTubes", 0, 0, 2.0, 0, "std::SSteel"};
+        m_cylVolPars["HGTD::CoolingTubeFluid"] = {"HGTD::CoolingTubeFluid", 0, 0, 1.5, 0, "pix::CO2_Liquid"};
+
+        // hack after fix of ASIC thickness (and material) in HGTD-TDR-01 tag (ATLAS-P2-ITK-17-04-02 and later)
+        double moduleSpaceHalfZ = 0.0;
+        if (hgtdTDR2) moduleSpaceHalfZ = 0.225;
+        m_boxVolPars["HGTD::ModuleSpace"] = {"HGTD::ModuleSpace", 11, 20, moduleSpaceHalfZ, 0, "std::Air"};
+
+        // These parameters are not in the db (yet) and don't fit into the cylinder or box structures used above
+        m_hgtdPars = { 320., // rMid
+                       640., // rOuter - only used in one place, and there 20 mm is added to it...
+                       15.,  // diskRotation (in degrees)
+                       1.,   // rowSpaceSide
+                       4.,   // rowBacksideInnerShift
+                       17.,  // rowBacksideOuterShift
+                       1.5,  // moduleSpaceInner
+                       12.5, // moduleSpaceOuter
+                       0.456 // flexSheetSpacing
+                     };
+
+        GeoTube        *world_solid_hgtd    = new GeoTube(m_cylVolPars["HGTD_mother"].rMin, m_cylVolPars["HGTD_mother"].rMax, m_cylVolPars["HGTD_mother"].zHalf);
+        GeoLogVol      *world_logical_hgtd  = new GeoLogVol("HGTD_mother", world_solid_hgtd, materialManager->getMaterial(m_cylVolPars["HGTD_mother"].material));
+        world_physical_hgtd = new GeoFullPhysVol(world_logical_hgtd);
+
+        //now build HGTD
+        buildHgtdGeoTDR(materialManager, world_physical_hgtd, bPos);
+    }
+
+    // older geometries used for EoI and TP samples
+    else if ( hgtdTiming || hgtdPreshower ) {
+        IRDBRecordset_ptr hgtdTubs   = m_athenaComps->rdbAccessSvc()->getRecordsetPtr("HGTDTubs", detectorKey, detectorNode);
+        if (m_fullGeo) {
+            double hgtdToleranceSmall = 0.0;
+            // get the info from the DB
+            IRDBRecordset::const_iterator first = hgtdTubs->begin();
+            IRDBRecordset::const_iterator last = hgtdTubs->end();
+            IRDBRecordset::const_iterator it;
+            // fill the names and the info
+            std::vector <std::string> hgtdName;
+            std::vector <double> hgtdRmin;
+            std::vector <double> hgtdRmax;
+            std::vector <double> hgtdDeltaZ;
+            std::vector <double> hgtdDeltaY;
+            std::vector <std::string> hgtdMaterial;
+
+            // special treatment for mother since we need its position
+            double zposMM = 0.;
+
+            // get indices for the various db entries and fill vectors with the properties in each
+            int iMother            = -1;
+            int iAbsorber          = -1;
+            int iInsulation        = -1;
+            int iCooling           = -1;
+            int iSensor            = -1;
+            int iGlue              = -1;
+            int iPCB               = -1;
+            int iElectronics       = -1;
+            int iHVKapton          = -1;
+            int iMecTolElectronics = -1;
+            int imecTolCooling     = -1;
+            int iColdTubeCoat      = -1;
+            int iColdTube          = -1;
+            int iSupportStruct     = -1;
+
+            for (it=first; it!=last; it++) {
+                hgtdName.push_back((*it)->getString("TUBE"));
+                hgtdRmin.push_back((*it)->getDouble("RMIN"));
+                hgtdRmax.push_back((*it)->getDouble("RMAX"));
+                hgtdDeltaZ.push_back((*it)->getDouble("DZ"));
+                hgtdDeltaY.push_back((*it)->getDouble("DELTAY"));
+                hgtdMaterial.push_back((*it)->getString("MATERIAL"));
+
+                std::string theName = hgtdName[hgtdName.size()-1];
+                if ( theName == "HGTD_mother" ) {
+                    zposMM = (*it)->getDouble("ZPOS");
+                    iMother = it - first;
+                }
+                else if ( theName == "Insulation" ) iInsulation = it - first;
+                else if ( theName == "Cooling" ) iCooling = it - first;
+                else if ( theName == "Sensor" ) iSensor = it - first;
+                else if ( theName == "Glue" ) iGlue = it - first;
+                else if ( theName == "PCB" ) iPCB = it - first;
+                else if ( theName == "Electronics" ) iElectronics = it - first;
+                else if ( theName == "HVKapton" ) iHVKapton = it - first;
+                else if ( theName == "MecTolElectronics" ) iMecTolElectronics = it - first;
+                else if ( theName == "mecTolCooling" ) imecTolCooling = it - first;
+                else if ( theName == "ColdTubeCoat" ) iColdTubeCoat = it - first;
+                else if ( theName == "ColdTube" ) iColdTube = it - first;
+                else if ( theName == "SupportStruct" ) iSupportStruct = it - first;
+                else if ( theName == "Absorber" ) iAbsorber = it - first;
+            }
+            // check if one of the needed entries were not found
+            if (iMother       == -1 || iInsulation  == -1 || iCooling       == -1 || iSensor            == -1 || iGlue          == -1 ||
+                iPCB          == -1 || iElectronics == -1 || iHVKapton      == -1 || iMecTolElectronics == -1 || imecTolCooling == -1 ||
+                iColdTubeCoat == -1 || iColdTube    == -1 || iSupportStruct == -1)
+                throw std::runtime_error("Error in HGTD_DetectorFactory: unable to get all HGTD parameters from the database!");
+            // only require that the absorber entry was found if the hgtdPreshower geo was requested
+            if ( hgtdPreshower && iAbsorber == -1 )
+                throw std::runtime_error("Error in HGTD_DetectorFactory: unable to get HGTD Absorber parameters from the database for the requested preshower!");
+
+            // now we have all values of the requested geometry
+            msg(MSG::DEBUG) << "HGTD mother volume at index " << iMother << " and z = " << zposMM << " mm" << endmsg;
+            msg(MSG::DEBUG) << "HGTD volume i, name, rmin, rmax, DeltaZ, DeltaY and material " << endmsg;
+            for ( unsigned int i=0; i< hgtdName.size(); i++) {
+                msg(MSG::DEBUG) << i << " "
+                                << hgtdName[i] << " "
+                                << hgtdRmin[i] << " "
+                                << hgtdRmax[i] << " "
+                                << hgtdDeltaZ[i] << " "
+                                << hgtdDeltaY[i] << " "
+                                << hgtdMaterial[i] << endmsg;
+            }
+
+            // build the HGTD Mother volume
+            GeoTube     *world_solid_hgtd    = new GeoTube(hgtdRmin[iMother],hgtdRmax[iMother],hgtdDeltaZ[iMother]);
+            GeoMaterial *material_world_hgtd = materialManager->getMaterial(hgtdMaterial[iMother]);
+            GeoLogVol   *world_logical_hgtd  = new GeoLogVol(hgtdName[iMother],world_solid_hgtd,material_world_hgtd);
+            world_physical_hgtd = new GeoFullPhysVol(world_logical_hgtd);
+
+            // construct the detectors from the back to the front
+            std::vector<std::string> hgtdVolName;
+            std::vector<unsigned int> hgtdVolMap;
+            hgtdVolName.push_back("SupportStructHgtd1");     hgtdVolMap.push_back(iSupportStruct);
+            hgtdVolName.push_back("CoolingHgtd4");           hgtdVolMap.push_back(iCooling);
+            hgtdVolName.push_back("mecTolElectronicsHgtd3"); hgtdVolMap.push_back(iMecTolElectronics);
+            hgtdVolName.push_back("ElectronicsHgtd3");       hgtdVolMap.push_back(iElectronics);
+            hgtdVolName.push_back("PCBHgtd3");               hgtdVolMap.push_back(iPCB);
+            hgtdVolName.push_back("GlueHgtd3");              hgtdVolMap.push_back(iGlue);
+            hgtdVolName.push_back("HGTDSiSensor3");          hgtdVolMap.push_back(iSensor);
+            hgtdVolName.push_back("HVKaptonHgtd3");          hgtdVolMap.push_back(iHVKapton);
+            hgtdVolName.push_back("mecTolCoolingHgtd3");     hgtdVolMap.push_back(imecTolCooling);
+            hgtdVolName.push_back("CoolingHgtd3");           hgtdVolMap.push_back(iCooling);
+            if ( hgtdPreshower ) {
+                hgtdVolName.push_back("AbsorberHgtd2");          hgtdVolMap.push_back(iAbsorber);
+            }
+            hgtdVolName.push_back("mecTolElectronicsHgtd2"); hgtdVolMap.push_back(iMecTolElectronics);
+            hgtdVolName.push_back("ElectronicsHgtd2");       hgtdVolMap.push_back(iElectronics);
+            hgtdVolName.push_back("PCBHgtd2");               hgtdVolMap.push_back(iPCB);
+            hgtdVolName.push_back("GlueHgtd2");              hgtdVolMap.push_back(iGlue);
+            hgtdVolName.push_back("HGTDSiSensor2");          hgtdVolMap.push_back(iSensor);
+            hgtdVolName.push_back("HVKaptonHgtd2");          hgtdVolMap.push_back(iHVKapton);
+            hgtdVolName.push_back("mecTolCoolingHgtd2");     hgtdVolMap.push_back(imecTolCooling);
+            hgtdVolName.push_back("CoolingHgtd2");           hgtdVolMap.push_back(iCooling);
+            if ( hgtdPreshower ) {
+                hgtdVolName.push_back("AbsorberHgtd1");          hgtdVolMap.push_back(iAbsorber);
+            }
+            hgtdVolName.push_back("mecTolElectronicsHgtd1"); hgtdVolMap.push_back(iMecTolElectronics);
+            hgtdVolName.push_back("ElectronicsHgtd1");       hgtdVolMap.push_back(iElectronics);
+            hgtdVolName.push_back("PCBHgtd1");               hgtdVolMap.push_back(iPCB);
+            hgtdVolName.push_back("GlueHgtd1");              hgtdVolMap.push_back(iGlue);
+            hgtdVolName.push_back("HGTDSiSensor1");          hgtdVolMap.push_back(iSensor);
+            hgtdVolName.push_back("HVKaptonHgtd1");          hgtdVolMap.push_back(iHVKapton);
+            hgtdVolName.push_back("mecTolCoolingHgtd1");     hgtdVolMap.push_back(imecTolCooling);
+            hgtdVolName.push_back("CoolingHgtd1");           hgtdVolMap.push_back(iCooling);
+            if ( hgtdPreshower ) {
+                hgtdVolName.push_back("AbsorberHgtd0");          hgtdVolMap.push_back(iAbsorber);
+            }
+            hgtdVolName.push_back("mecTolElectronicsHgtd0"); hgtdVolMap.push_back(iMecTolElectronics);
+            hgtdVolName.push_back("ElectronicsHgtd0");       hgtdVolMap.push_back(iElectronics);
+            hgtdVolName.push_back("PCBHgtd0");               hgtdVolMap.push_back(iPCB);
+            hgtdVolName.push_back("GlueHgtd0");              hgtdVolMap.push_back(iGlue);
+            hgtdVolName.push_back("HGTDSiSensor0");          hgtdVolMap.push_back(iSensor);
+            hgtdVolName.push_back("HVKaptonHgtd0");          hgtdVolMap.push_back(iHVKapton);
+            hgtdVolName.push_back("mecTolCoolingHgtd0");     hgtdVolMap.push_back(imecTolCooling);
+            hgtdVolName.push_back("CoolingHgtd0");           hgtdVolMap.push_back(iCooling);
+            hgtdVolName.push_back("SupportStructHgtd0");     hgtdVolMap.push_back(iSupportStruct);
+            hgtdVolName.push_back("InsulationHgtd0");        hgtdVolMap.push_back(iInsulation);
+
+            // build the volumes in the requested order
+            std::vector<GeoMaterial *> hgtdGeoMaterial;
+            std::vector<double>        hgtdLocalZPos;
+            std::vector<GeoTube *>     hgtdSolidVol;
+            std::vector<GeoLogVol *>   hgtdLogVol;
+            std::vector<GeoPhysVol *>  hgtdPhysVol;
+            unsigned int index, indexCoolingVolume;
+            for (unsigned int ii = 0;ii<hgtdVolName.size();ii++) {
+                index     = hgtdVolMap[ii];
+                hgtdGeoMaterial.push_back( materialManager->getMaterial(hgtdMaterial[index]) );
+                // the z coordinate needs special care
+                if (ii== 0 )
+                    hgtdLocalZPos.push_back(hgtdDeltaZ[iMother] - hgtdDeltaZ[index] - hgtdToleranceSmall);
+                else
+                    hgtdLocalZPos.push_back(hgtdLocalZPos[ii-1] - hgtdDeltaZ[ hgtdVolMap[ii-1] ] - hgtdDeltaZ[index] - hgtdToleranceSmall);
+                hgtdSolidVol.push_back( new GeoTube(hgtdRmin[index],hgtdRmax[index],hgtdDeltaZ[index]) );
+                hgtdLogVol.push_back( new GeoLogVol(hgtdVolName[ii],hgtdSolidVol[ii],hgtdGeoMaterial[ii]) );
+                hgtdPhysVol.push_back( new GeoPhysVol(hgtdLogVol[ii]) );
+                world_physical_hgtd->add(new GeoTransform(HepGeom::TranslateZ3D(hgtdLocalZPos[ii])));
+                world_physical_hgtd->add(hgtdPhysVol[ii]);
+
+                // debug print-outs
+                msg(MSG::DEBUG) << "HGTD built volume " << std::setw(24) << hgtdMaterial[index]
+                                << " at position " << std::setw(8) <<  hgtdLocalZPos[ii]
+                                << " with Rmin " << std::setw(8) <<  hgtdRmin[index]
+                                << " Rmax " << std::setw(8) <<  hgtdRmax[index]
+                                << " DeltaZ " << std::setw(8) << hgtdDeltaZ[index] << endmsg;
+            }
+            msg(MSG::DEBUG) << "HGTD Mother DeltaZ " << std::setw(24) << hgtdDeltaZ[iMother] << endmsg;
+
+            // build up the cooling system of HGTD
+
+            // how many of the volumes to fill and at which index?
+            std::vector<unsigned int> cooling_hgtd_collection;
+            unsigned int nCoolingTubes = 0;
+            for (unsigned int i=0; i<hgtdVolMap.size(); i++ ) {
+                if ( (int) hgtdVolMap[i] == iCooling ) {
+                    nCoolingTubes += 1;
+                    cooling_hgtd_collection.push_back(i);
+                }
+            }
+            if ( nCoolingTubes <= 0 ) {
+                throw std::runtime_error("Error in HGTD_DetectorFactory: unable to get HGTD number of cooling tubes!");
+            }
+            msg(MSG::DEBUG) << "HGTD number of cooling volumes: " << nCoolingTubes << endmsg;
+
+            // count the number of cold tubes
+            // the first tube is at y=DeltaY/2
+            unsigned int nColdTubes = ((int) (hgtdRmax[iColdTube] - hgtdDeltaY[iColdTube]/2.)/hgtdDeltaY[iColdTube] + 1);
+            // now count the number of the tubes cut in half:
+            unsigned int nColdTubesHalf = ((int) (hgtdRmin[iColdTube] - hgtdDeltaY[iColdTube]/2.)/hgtdDeltaY[iColdTube] + 1);
+
+            msg(MSG::DEBUG) << "HGTD number of cold tubes " << nColdTubes << endmsg;
+            msg(MSG::DEBUG) << "HGTD number of cold tubes halfs " << nColdTubesHalf << endmsg;
+
+            // now the material
+            GeoMaterial *material_ColdTubeCoat_hgtd = materialManager->getMaterial(hgtdMaterial[iColdTubeCoat]);
+            GeoMaterial *material_ColdTube_hgtd     = materialManager->getMaterial(hgtdMaterial[iColdTube]);
+
+            // position of the cold and coat tubes
+            double ycoord0 = hgtdDeltaY[iColdTubeCoat]/2.0;
+            std::vector<double> xcoord;
+            std::vector<double> ycoord;
+
+            std::vector <double> hgtdColdTubeCoatL;
+            std::vector <double> hgtdColdTubeL;
+
+            std::vector <std::string> hgtdColdTubeCoatName;
+            std::vector <std::string> hgtdColdTubeName;
+
+            double xOfTube, yOfTube, lengthMin, lengthMax, lengthOfTube;
+            // here we fill the calculations (positions, lengths) and names
+            for (unsigned int ii = 0; ii<nColdTubes; ii++) {
+
+                yOfTube = ycoord0 + hgtdDeltaY[iColdTubeCoat]*ii;
+                ycoord.push_back(yOfTube);
+                ycoord.push_back(-yOfTube);
+
+                if (ii < nColdTubesHalf ) {
+                    ycoord.push_back(yOfTube);
+                    ycoord.push_back(-yOfTube);
+
+                    lengthMax = (sqrt(hgtdRmax[iCooling]*hgtdRmax[iCooling] - (yOfTube+hgtdDeltaZ[iColdTubeCoat])*(yOfTube+hgtdDeltaZ[iColdTubeCoat])));
+                    lengthMin = (sqrt(hgtdRmin[iCooling]*hgtdRmin[iCooling] - (yOfTube-hgtdDeltaZ[iColdTubeCoat])*(yOfTube-hgtdDeltaZ[iColdTubeCoat])));
+
+                    xOfTube = lengthMin + (lengthMax - lengthMin)/2.0;
+                    xcoord.push_back(xOfTube);
+                    xcoord.push_back(xOfTube);
+                    xcoord.push_back(-xOfTube);
+                    xcoord.push_back(-xOfTube);
+
+                    lengthOfTube = lengthMax - lengthMin;
+                    hgtdColdTubeCoatL.push_back(lengthOfTube);
+                    hgtdColdTubeCoatL.push_back(lengthOfTube);
+                    hgtdColdTubeCoatL.push_back(lengthOfTube);
+                    hgtdColdTubeCoatL.push_back(lengthOfTube);
+
+                    hgtdColdTubeL.push_back(lengthOfTube);
+                    hgtdColdTubeL.push_back(lengthOfTube);
+                    hgtdColdTubeL.push_back(lengthOfTube);
+                    hgtdColdTubeL.push_back(lengthOfTube);
+
+                    hgtdColdTubeCoatName.push_back( hgtdName[iColdTubeCoat]+"UpR"+std::to_string(ii) );
+                    hgtdColdTubeCoatName.push_back( hgtdName[iColdTubeCoat]+"DownR"+std::to_string(ii) );
+                    hgtdColdTubeCoatName.push_back( hgtdName[iColdTubeCoat]+"UpL"+std::to_string(ii) );
+                    hgtdColdTubeCoatName.push_back( hgtdName[iColdTubeCoat]+"DownL"+std::to_string(ii) );
+
+                    hgtdColdTubeName.push_back( hgtdName[iColdTube]+"UpR"+std::to_string(ii) );
+                    hgtdColdTubeName.push_back( hgtdName[iColdTube]+"DownR"+std::to_string(ii) );
+                    hgtdColdTubeName.push_back( hgtdName[iColdTube]+"UpL"+ std::to_string(ii) );
+                    hgtdColdTubeName.push_back( hgtdName[iColdTube]+"DownL"+std::to_string(ii) );
+                }
+                else {
+                    xOfTube = 0.;
+                    xcoord.push_back(xOfTube);
+                    xcoord.push_back(xOfTube);
+
+                    lengthOfTube = 2*(sqrt(hgtdRmax[iCooling]*hgtdRmax[iCooling]-(yOfTube+hgtdDeltaZ[iColdTubeCoat])*(yOfTube+hgtdDeltaZ[iColdTubeCoat])));
+                    hgtdColdTubeCoatL.push_back(lengthOfTube);
+                    hgtdColdTubeCoatL.push_back(lengthOfTube);
+
+                    hgtdColdTubeL.push_back(lengthOfTube);
+                    hgtdColdTubeL.push_back(lengthOfTube);
+
+                    hgtdColdTubeCoatName.push_back( hgtdName[iColdTubeCoat]+"Up"+std::to_string(ii) );
+                    hgtdColdTubeCoatName.push_back( hgtdName[iColdTubeCoat]+"Down"+std::to_string(ii) );
+
+                    hgtdColdTubeName.push_back( hgtdName[iColdTube]+"Up"+std::to_string(ii) );
+                    hgtdColdTubeName.push_back( hgtdName[iColdTube]+"Down"+std::to_string(ii) );
+                }
+
+            } // for (ii = 0;ii<nColdTubes;ii++){
+
+            msg(MSG::DEBUG) << " index hgtdColdTubeCoatName hgtdColdTubeName xcoordinate ycoordinate LengthOfTube LengthOfCoat " << endmsg;
+            for (unsigned int i=0; i < hgtdColdTubeName.size(); i++) {
+                msg(MSG::DEBUG) << "   " << i
+                                << "   " << hgtdColdTubeCoatName[i]
+                                << "   " << hgtdColdTubeName[i]
+                                << "   " << xcoord[i]
+                                << "   " << ycoord[i]
+                                << "   " << hgtdColdTubeL[i]
+                                << "   " << hgtdColdTubeCoatL[i]
+                                << endmsg;
+            }
+
+            // the volumes
+            std::vector<GeoTube *>    hgtdColdTubeCoatSolidVol;
+            std::vector<GeoTube *>    hgtdColdTubeSolidVol;
+            std::vector<GeoLogVol *>  hgtdColdTubeCoatLogVol;
+            std::vector<GeoLogVol *>  hgtdColdTubeLogVol;
+            std::vector<GeoPhysVol *> hgtdColdTubeCoatPhysVol;
+            std::vector<GeoPhysVol *> hgtdColdTubePhysVol;
+
+            // now we install the volumes
+            for (unsigned int ii = 0;ii < hgtdColdTubeName.size(); ii++) {
+
+                hgtdColdTubeCoatSolidVol.push_back( new GeoTube(0.0,hgtdDeltaZ[iColdTubeCoat],hgtdColdTubeCoatL[ii]/2.0) );
+                hgtdColdTubeSolidVol.push_back(     new GeoTube(0.0,hgtdDeltaZ[iColdTube],hgtdColdTubeL[ii]/2.0) );
+
+                // fill into all Cooling units
+                for (unsigned int jj = 0; jj < nCoolingTubes;jj++) {
+                    // get the index for the cooling volume
+                    indexCoolingVolume = cooling_hgtd_collection[jj];
+                    // get the index of the last entry in the vectors
+                    index = hgtdColdTubeCoatLogVol.size();
+                    //Cold tube coating
+                    hgtdColdTubeCoatLogVol.push_back( new GeoLogVol(hgtdColdTubeCoatName[ii],hgtdColdTubeCoatSolidVol[ii],material_ColdTubeCoat_hgtd) );
+                    hgtdColdTubeCoatPhysVol.push_back( new GeoPhysVol(hgtdColdTubeCoatLogVol[index]) );
+                    // attach the coat to to the Cooling volume
+                    hgtdPhysVol[indexCoolingVolume]->add(new GeoTransform(HepGeom::Transform3D(CLHEP::HepRotationY(M_PI/2), CLHEP::Hep3Vector(xcoord[ii],ycoord[ii],0.0))));
+                    hgtdPhysVol[indexCoolingVolume]->add(hgtdColdTubeCoatPhysVol[index]);
+                    //Cold tube
+                    hgtdColdTubeLogVol.push_back( new GeoLogVol(hgtdColdTubeName[ii],hgtdColdTubeSolidVol[ii],material_ColdTube_hgtd) );
+                    hgtdColdTubePhysVol.push_back( new GeoPhysVol(hgtdColdTubeLogVol[index]) );
+                    // attach the coat
+                    hgtdColdTubeCoatPhysVol[index]->add(new GeoTransform(HepGeom::TranslateZ3D(0.0)));
+                    hgtdColdTubeCoatPhysVol[index]->add(hgtdColdTubePhysVol[index]);
+                } // for (jj = 0;jj<nCoolingTubes;jj++) {
+            } // for (ii = 0;ii<hgtdColdTubeName.size();ii++) {
+
+        } // end of fullgeo
+
+    } // end of hgtdTiming or hgtdPreshower
+
+    return world_physical_hgtd;
+}
+
+void HGTD_DetectorFactory::buildHgtdGeoTDR(const DataHandle<StoredMaterialManager>& matmanager,
+                                           GeoFullPhysVol* HGTDparent, bool /*isPos*/) {
+
+    msg(MSG::INFO) << "**************************************************" << endmsg;
+    msg(MSG::INFO) << "                 Building HGTD                    " << endmsg;
+    msg(MSG::INFO) << "**************************************************" << endmsg;
+
+    // to be calculated from parameters in db using map
+    double motherHalfZ = ((GeoTube*) HGTDparent->getLogVol()->getShape())->getZHalfLength();
+    double modulePackageHalfZtot = 3.5/2+4./2; // including flex - can we not get this from the db numbers? /CO
+
+    double modulePackageHalfZ = 2*m_boxVolPars["HGTD::GlueSensor"].zHalf + m_boxVolPars["HGTDSiSensor0"].zHalf
+                                + m_boxVolPars["HGTD::LGADInactive"].zHalf + m_boxVolPars["HGTD::ASIC"].zHalf
+                                + m_boxVolPars["HGTD::Hybrid"].zHalf + m_boxVolPars["HGTD::ModuleSpace"].zHalf;
+
+    // add volumes by key name to ordered vector, outside in (from larger z to smaller)
+    std::vector<std::string> hgtdVolumes;
+    hgtdVolumes.push_back("HGTD::ModeratorOut"); // Out as in outside the vessel
+    hgtdVolumes.push_back("HGTD::BackCover");
+    hgtdVolumes.push_back("HGTD::ToleranceBack");
+    hgtdVolumes.push_back("HGTD::ModeratorIn"); // In as in inside the vessel
+    hgtdVolumes.push_back("HGTD::ModuleLayer3");
+    hgtdVolumes.push_back("HGTD::SupportPlate");
+    hgtdVolumes.push_back("HGTD::CoolingPlate");
+    hgtdVolumes.push_back("HGTD::SupportPlate");
+    hgtdVolumes.push_back("HGTD::ModuleLayer2");
+    hgtdVolumes.push_back("HGTD::ToleranceMid");
+    hgtdVolumes.push_back("HGTD::ModuleLayer1");
+    hgtdVolumes.push_back("HGTD::SupportPlate");
+    hgtdVolumes.push_back("HGTD::CoolingPlate");
+    hgtdVolumes.push_back("HGTD::SupportPlate");
+    hgtdVolumes.push_back("HGTD::ModuleLayer0");
+    hgtdVolumes.push_back("HGTD::ToleranceFront");
+    hgtdVolumes.push_back("HGTD::FrontCover");
+    // Important - these must come last since they will otherwise shift positions of the previous volumes!
+    hgtdVolumes.push_back("HGTD::InnerRCover"); // don't reorder!
+    hgtdVolumes.push_back("HGTD::OuterRCover"); // don't reorder!
+
+    // Now build up the solid, logical and physical volumes as appropriate (starting from the outermost volume)
+    // We first start with the volumes we'll reuse several times
+
+    //////////////////////////
+    // FLEX PACKAGE VOLUMES //
+    //////////////////////////
+
+    // Flex package volume modeled as 8 concentric flex sheets with progressively larger inner radius
+    // Order of sheets depend on whether package is for front or back of a cooling plate
+    // First calculate the inner radii for the flex sheets
+    GeoCylVolParams packagePars = m_cylVolPars["HGTD::FlexPackage"];
+    GeoCylVolParams flexPars = m_cylVolPars["HGTD::FlexTube"];
+    std::vector<double> flexSheetInnerR;
+    double currentInnerR = 144.; // adding flex sheets from the second sensor (all have the hybrid already)
+    for (int flexSheet = 0; flexSheet < 8; flexSheet++) {
+        flexSheetInnerR.push_back(currentInnerR);
+        // set the inner radius for the next flex sheet, increased by two module heights and two radius-dependent spaces per sheet
+        currentInnerR += m_boxVolPars["HGTDModule0"].xHalf*2 * (2 + 2 * (flexSheet < 4 ? 0.2 : 0.8) );
+    }
+
+    // build up the two flex volumes for front (0) and back (1) sides
+    GeoPhysVol* flexPackagePhysical[2] = {};
+    for (int flexVolume = 0; flexVolume < 2; flexVolume++) {
+
+        std::vector<double> rInner = flexSheetInnerR;
+        if (flexVolume) reverse(rInner.begin(), rInner.end()); // reverse order for backside flex package
+
+        GeoTube*    flexPackageSolid = new GeoTube(packagePars.rMin, packagePars.rMax, packagePars.zHalf);
+        GeoLogVol*  flexPackageLogical = new GeoLogVol(packagePars.name, flexPackageSolid, matmanager->getMaterial(packagePars.material));
+        flexPackagePhysical[flexVolume] = new GeoPhysVol(flexPackageLogical);
+        // build up a volume of flex cables, starting in z at half a flex layer from the edge of the flex package volume
+        double flexZoffset = packagePars.zHalf - flexPars.zHalf;
+        for (int flexSheet = 0; flexSheet < 8; flexSheet++) {
+            GeoTube*    hgtdFlexSolid    = new GeoTube(rInner[flexSheet], flexPars.rMax, flexPars.zHalf);
+            GeoLogVol*  hgtdFlexLogical  = new GeoLogVol("HGTD::FlexTube"+std::to_string(flexSheet),
+                                                         hgtdFlexSolid, matmanager->getMaterial(flexPars.material));
+            GeoPhysVol* hgtdFlexPhysical = new GeoPhysVol(hgtdFlexLogical);
+            flexPackagePhysical[flexVolume]->add(new GeoTransform(HepGeom::TranslateZ3D(flexZoffset)));
+            flexPackagePhysical[flexVolume]->add(hgtdFlexPhysical);
+            // print out a line for each flex layer
+            msg(MSG::INFO) << "Flex layer (" << (flexSheet ? "front" : "back") << ")" << flexSheet << ", Rmin = " << std::setw(5) << rInner[flexSheet]
+                           << " mm, flexZoffset = " << flexZoffset << " mm" << endmsg;
+            flexZoffset = flexZoffset - m_hgtdPars.flexSheetSpacing;
+        }
+
+    }
+
+    ///////////////////
+    // COOLING TUBES //
+    ///////////////////
+
+    // make list of radii of cooling tubes
+    std::vector<double> coolingTubeRadii;
+    double coolingTubeRadius = 130.;
+    coolingTubeRadii.push_back(coolingTubeRadius);
+    for (int i = 0; i < 18; i++) {
+        coolingTubeRadius += (418-130.)/18;
+        coolingTubeRadii.push_back(coolingTubeRadius);
+    }
+    for (int i = 0; i < 12; i++) {
+        coolingTubeRadius += (658-418.)/14;
+        coolingTubeRadii.push_back(coolingTubeRadius);
+    }
+    coolingTubeRadius = 710.;
+    coolingTubeRadii.push_back(coolingTubeRadius);
+    for (int i = 0; i < 7; i++) {
+        coolingTubeRadius += (890-710.)/6;
+        coolingTubeRadii.push_back(coolingTubeRadius);
+    }
+    std::string tmp = "Cooling tubes will be created at the following radii (in mm):";
+    for (size_t i = 0; i << coolingTubeRadii.size(); i++) {
+        tmp += (std::string(" ") + std::to_string(coolingTubeRadii[i]));
+    }
+    msg(MSG::INFO) << tmp << endmsg;
+
+    ///////////////////////////////////
+    // PERIPHERAL ELECTRONICS VOLUME //
+    ///////////////////////////////////
+
+    //build peripheral electronics
+    GeoCylVolParams periphElPars = m_cylVolPars["HGTD::PeriphElec"];
+    GeoTube*    periphElec_solid  = new GeoTube(periphElPars.rMin, periphElPars.rMax, periphElPars.zHalf);
+    GeoLogVol*  periphElec_log    = new GeoLogVol(periphElPars.name, periphElec_solid, matmanager->getMaterial(periphElPars.material));
+    GeoPhysVol* periphElec_phys   = new GeoPhysVol(periphElec_log);
+
+    GeoPhysVol* moduleLayerPhysical[4] = {}; // array of pointers to the physical volumes for the module layers which need special care
+
+    ///////////////////////////////////////////
+    // BUILD UP ALL MAIN VOLUMES IN SEQUENCE //
+    ///////////////////////////////////////////
+
+    // now build up the volumes in the order specified in the vector
+    double zModuleLayerF = 0.;
+    double zModuleLayerB = 0.;
+    for (size_t vol = 0; vol < hgtdVolumes.size(); vol++) {
+
+        std::string v = hgtdVolumes[vol];
+        // calculate local z offsets for each main volume sequentially
+        if (vol == 0) // special treatment for the first one
+            m_cylVolPars[v].zOffsetLocal = motherHalfZ - m_cylVolPars[v].zHalf;
+        // All but the InnerRCover and OuterRCover are placed relative to other components,
+        // but the zOffsetLocal parameter of these two volumes is left as read from the db
+        else if (v.substr(9,16) != "erRCover") {
+            std::string vPrev = hgtdVolumes[vol-1];
+            m_cylVolPars[v].zOffsetLocal = m_cylVolPars[vPrev].zOffsetLocal - m_cylVolPars[vPrev].zHalf - m_cylVolPars[v].zHalf;
+        }
+        GeoTube*    hgtdSubVolumeSolid    = new GeoTube(m_cylVolPars[v].rMin, m_cylVolPars[v].rMax, m_cylVolPars[v].zHalf);
+        GeoLogVol*  hgtdSubVolumeLogical  = new GeoLogVol(m_cylVolPars[v].name, hgtdSubVolumeSolid,
+                                                          matmanager->getMaterial(m_cylVolPars[v].material));
+        GeoPhysVol* hgtdSubVolumePhysical = new GeoPhysVol(hgtdSubVolumeLogical);
+
+        // if building the cooling plate, also add peripheral electronics since position of those are relative to that of cooling plate
+        if (v == "HGTD::CoolingPlate") {
+            double zOffsetPeriphElec = m_cylVolPars[v].zHalf + periphElPars.zOffsetLocal + periphElPars.zHalf;
+            for (int side = 0; side < 2; side++) { // place two, one on each side of cooling plate
+                HGTDparent->add(new GeoTransform(HepGeom::TranslateZ3D(m_cylVolPars[v].zOffsetLocal + pow(-1, side)*zOffsetPeriphElec)));
+                HGTDparent->add(periphElec_phys);
+            }
+
+            // and the CO2 cooling tubes inside the cooling plate
+            for (size_t i = 0; i < coolingTubeRadii.size(); i++) {
+                // msg(MSG::INFO) << "  Will now place cooling tube with R = " << coolingTubeRadii[i] << " mm" << endmsg;
+                // the tube itself
+                GeoTorus* coolingTubeSolid = new GeoTorus(m_cylVolPars["HGTD::CoolingTubeFluid"].zHalf, m_cylVolPars["HGTD::CoolingTube"].zHalf,
+                                                          coolingTubeRadii[i], 0, 2*M_PI);
+                GeoLogVol* coolingTubeLogical = new GeoLogVol("HGTD::CoolingTube", coolingTubeSolid,
+                                                              matmanager->getMaterial(m_cylVolPars["HGTD::CoolingTube"].material));
+                GeoPhysVol* coolingTubePhysical = new GeoPhysVol(coolingTubeLogical);
+                hgtdSubVolumePhysical->add(coolingTubePhysical); // no transformations needed, concentric with cooling plate and centered in z
+                // and the contents, i.e. the cooling fluid
+                GeoTorus* coolingFluidSolid = new GeoTorus(0, m_cylVolPars["HGTD::CoolingTubeFluid"].zHalf,
+                                                           coolingTubeRadii[i], 0, 2*M_PI);
+                GeoLogVol* coolingFluidLogical = new GeoLogVol("HGTD::CoolingFluid", coolingFluidSolid,
+                                                               matmanager->getMaterial(m_cylVolPars["HGTD::CoolingTubeFluid"].material));
+                GeoPhysVol* coolingFluidPhysical = new GeoPhysVol(coolingFluidLogical);
+                hgtdSubVolumePhysical->add(coolingFluidPhysical); // no transformations needed, concentric with cooling plate and centered in z
+            }
+        }
+
+        // module layer
+        if (v.substr(0,17) == "HGTD::ModuleLayer") {
+
+            int layer = atoi(v.substr(17,1).c_str());
+
+            // front and back side layers are treated differently: z position of flex and module layers, and rotation
+            double zFlex = 0.;
+            bool Lside = layer % 2;
+            if (Lside == 0) { // layers 0 and 2
+                zFlex = -modulePackageHalfZtot + m_cylVolPars["HGTD::FlexPackage"].zHalf;
+                zModuleLayerF = modulePackageHalfZtot - modulePackageHalfZ;
+            }
+            else { // layers 1 and 3
+                zFlex = modulePackageHalfZtot - m_cylVolPars["HGTD::FlexPackage"].zHalf;
+                zModuleLayerB = -modulePackageHalfZtot + modulePackageHalfZ;
+            }
+
+            // place flex within module packages, at different positions depending on front or back or cooling plate
+            hgtdSubVolumePhysical->add(new GeoTransform(HepGeom::TranslateZ3D(zFlex)));
+            hgtdSubVolumePhysical->add(flexPackagePhysical[(Lside ? 0 : 1)]);
+
+            // place module layer volumes
+            int rotationSign = (layer <= 1 ? 1 : -1);
+            HGTDparent->add(new GeoTransform(HepGeom::TranslateZ3D(m_cylVolPars[v].zOffsetLocal)*HepGeom::RotateZ3D(rotationSign*m_hgtdPars.diskRotation*CLHEP::deg)));
+            HGTDparent->add(hgtdSubVolumePhysical);
+            moduleLayerPhysical[layer] = hgtdSubVolumePhysical;
+
+        } // end of module package
+
+        else {
+            HGTDparent->add(new GeoTransform(HepGeom::TranslateZ3D(m_cylVolPars[v].zOffsetLocal)));
+            HGTDparent->add(hgtdSubVolumePhysical);
+        }
+
+        // print out info about each main volume in the module layer
+        msg(MSG::INFO) << std::setw(20) << m_cylVolPars[v].name << " ( " << std::setw(20) << m_cylVolPars[v].material
+                       << " ), local z = " << std::setw(6) << m_cylVolPars[v].zOffsetLocal << " mm" << ", Rmin = " <<  std::setw(4) << m_cylVolPars[v].rMin
+                       << " mm, Rmax = " << std::setw(4) << m_cylVolPars[v].rMax << " mm, DZ = " << std::setw(5) << m_cylVolPars[v].zHalf << " mm" << endmsg;
+
+    } // end loop over hgtdVolumes
+
+    ////////////////////
+    // MODULE VOLUMES //
+    ////////////////////
+
+    // create the module --> each for cell and with different names
+    // calculate the positions where modules should be placed in one quadrant
+    std::vector<std::vector<HGTDGeo::ModulePosition> > positions;
+    positions.push_back(calculateHgtdModulePositionsInQuadrant(0)); // front-side module positions
+    positions.push_back(calculateHgtdModulePositionsInQuadrant(1)); // back-side module positions
+
+    // components for the module
+    std::vector<std::string> moduleVolumes;
+    moduleVolumes.push_back("HGTD::GlueAsic");
+    moduleVolumes.push_back("HGTD::ASIC");
+    moduleVolumes.push_back("HGTD::LGADInactive");
+    moduleVolumes.push_back("SensorPlaceHolder"); // replaced below to get the numbered name right
+    moduleVolumes.push_back("HGTD::GlueSensor");
+    moduleVolumes.push_back("HGTD::Hybrid");
+    if (m_boxVolPars["HGTD::ModuleSpace"].zHalf) moduleVolumes.push_back("HGTD::ModuleSpace");
+
+    int layer_offset  = 5;
+
+    // TODO: here used to be the creation of a PixelModuleDesign object, so likely corresponding HGTD object should be made here
+
+    // loop over layers
+    for (int layer = 0; layer < 4; layer++) {
+        // select if you need the front or the back positions
+        int front_back = layer % 2;
+        bool isFront   = (front_back == 0) ? true : false;
+
+        std::vector<std::string> volumes = moduleVolumes;
+        if (not isFront) reverse(volumes.begin(), volumes.end()); // reverse order of components for backside modules
+
+        std::string sensorName = std::string("HGTDSiSensor")+std::to_string(layer);
+        std::string moduleName = std::string("HGTDModule")+std::to_string(layer);
+
+        double moduleHalfWidth  = m_boxVolPars[moduleName].yHalf;
+        double moduleHalfHeight = m_boxVolPars[moduleName].xHalf;
+
+        // select if you need the front or the back positions
+        unsigned int nModules = positions[front_back].size();
+        int   max_rows        = 18;
+
+        // loop over quadrants in the current layer
+        for (int q = 0; q < 4; q++) {
+            // loop over modules in this quadrant
+            for (unsigned int element = 0; element < nModules; element++) {
+                double x   = positions[front_back].at(element).x;
+                double y   = positions[front_back].at(element).y;
+                double rot = positions[front_back].at(element).flipped ? 90. : 0.;
+                double row = positions[front_back].at(element).row;
+
+                double myphi  = atan(y/x);
+                double radius = sqrt(x*x+y*y);
+
+                // module position
+                double myx = radius*cos(q*M_PI*0.5+myphi);
+                double myy = radius*sin(q*M_PI*0.5+myphi);
+
+                // mirror everything if layer 2 or 3
+                double moduleRotation = 0;
+                if (layer > 1) {
+                    myx = -myx;
+                    // need to rotate 180 degrees some modules in q0 and q2
+                    if (q%2 == 0 && row <= 15) moduleRotation = 180;
+                    else if (q%2 == 1 && row > 15) moduleRotation = 180;
+                }
+
+                // these aren't really eta and phi coordinates, misusing names due to borrowing pixel framework
+                int eta = (q*max_rows) + positions[front_back].at(element).row;
+                int phi = positions[front_back].at(element).el_in_row;
+
+                std::string module_string = "_layer_"+std::to_string(layer_offset+layer)+"_"+std::to_string(phi)+"_"+std::to_string(eta);
+
+                double myModuleHalfHeight = moduleHalfHeight;
+                double myModuleHalfWidth  = moduleHalfWidth;
+
+                GeoBox      *moduleSolid    = new GeoBox(myModuleHalfHeight, myModuleHalfWidth, modulePackageHalfZ);
+                GeoLogVol   *moduleLogical  = new GeoLogVol(moduleName+module_string, moduleSolid, matmanager->getMaterial("std::Air"));
+                GeoFullPhysVol* modulePhysical = new GeoFullPhysVol(moduleLogical);
+
+                // print out one module per layer
+                if (element == 0 && q == 0)
+                    msg(MSG::INFO) << "Will now build up an individual HGTD module of layer " << layer << " and quarter " << q << endmsg;
+
+                // loop over components in module
+                for (size_t comp = 0; comp < volumes.size(); comp++) {
+                    if (volumes[comp] == "SensorPlaceHolder") volumes[comp] = sensorName; // replace placeholder
+                    std::string c = volumes[comp];
+                    // calculate local z offsets for each sensor component sequentially, and x offsets for those components that are smaller
+                    if (comp == 0) // special treatment for the first one
+                        m_boxVolPars[c].zOffsetLocal = modulePackageHalfZ - m_boxVolPars[c].zHalf;
+                    else {
+                        std::string cPrev = volumes[comp-1];
+                        m_boxVolPars[c].zOffsetLocal = m_boxVolPars[cPrev].zOffsetLocal - m_boxVolPars[cPrev].zHalf - m_boxVolPars[c].zHalf;
+                    }
+
+                    double comp_halfx = m_boxVolPars[c].xHalf;
+                    double comp_halfy = m_boxVolPars[c].yHalf;
+
+                    double xOffsetLocal = myModuleHalfHeight - comp_halfx; // to make room for wire bond of flex to ASIC which is larger than the sensor
+
+                    GeoBox*     sensorCompSolidVol    = new GeoBox(comp_halfx, comp_halfy, m_boxVolPars[c].zHalf);
+                    std::string attach = (volumes[comp] == sensorName) ? "" : module_string;
+
+                    GeoLogVol*  sensorCompLogicalVol  = new GeoLogVol(m_boxVolPars[c].name+attach, sensorCompSolidVol, matmanager->getMaterial(m_boxVolPars[c].material));
+                    GeoFullPhysVol* sensorCompPhysicalVol = new GeoFullPhysVol(sensorCompLogicalVol);
+
+                    // each SiSensor then has a detector element
+                    // TODO: not adding detector elements yet until a proper solution (not involving pixelBasics) can be implemented
+                    if (volumes[comp] == sensorName) {
+		        // TODO: create identifier, previously done based on endcap_side, layer_offset+layer, "phi", "eta"
+		        // TODO: create detector element and feed it the identifier, design, physical volume of active sensor part, etc
+                        // TODO: add detector element through the detector manager
+                        HepGeom::Transform3D sensorTransform = HepGeom::TranslateZ3D(m_boxVolPars[c].zOffsetLocal)*
+                                                               HepGeom::TranslateX3D(xOffsetLocal);
+                        GeoAlignableTransform* xform = new GeoAlignableTransform(sensorTransform);
+                        modulePhysical->add(xform);
+                        modulePhysical->add(sensorCompPhysicalVol);
+                    } else {
+                        modulePhysical->add(new GeoTransform(HepGeom::TranslateZ3D(m_boxVolPars[c].zOffsetLocal)*HepGeom::TranslateX3D(xOffsetLocal)));
+                        modulePhysical->add(sensorCompPhysicalVol);
+                    }
+
+                    // print out each module component
+                    if (element == 0 && q == 0)
+                        msg(MSG::INFO) << std::setw(20) << m_boxVolPars[c].name << " ( " << std::setw(15) << m_boxVolPars[c].material
+                                       << " ), in-sensor-layer local z = " << std::setw(7) << m_boxVolPars[c].zOffsetLocal << " mm"
+                                       << ", DX = " << std::setw(5) << m_boxVolPars[c].xHalf << " mm"
+                                       << ", DY = " << std::setw(5) << m_boxVolPars[c].yHalf << " mm"
+                                       << ", DZ = " << std::setw(5) << m_boxVolPars[c].zHalf << " mm" << endmsg;
+                } // end of components loop
+
+                double zModule = isFront ? zModuleLayerF : zModuleLayerB;
+                GeoTransform * moduleTransform = new GeoTransform(HepGeom::TranslateZ3D(zModule)*
+                                                                  HepGeom::TranslateX3D(myx)*
+                                                                  HepGeom::TranslateY3D(myy)*
+                                                                  HepGeom::RotateZ3D((rot+q*90+moduleRotation)*CLHEP::deg));
+                moduleLayerPhysical[layer]->add(moduleTransform);
+                moduleLayerPhysical[layer]->add(modulePhysical);
+
+            } //end of modules loop
+            msg(MSG::INFO) << "Done placing modules for quadrant " << q << endmsg;
+
+        } // end of quadrants loop
+        msg(MSG::INFO) << "Done placing modules for layer " << layer << endmsg;
+
+    } // end of layers loop
+
+    msg(MSG::INFO) << "**************************************************" << endmsg;
+    msg(MSG::INFO) << "               Done building HGTD                 " << endmsg;
+    msg(MSG::INFO) << "**************************************************" << endmsg;
+
+}
+
+std::vector<ModulePosition> HGTD_DetectorFactory::calculateHgtdModulePositionsInQuadrant(int layer) {
+    std::vector<ModulePosition> modulePositions;
+    for (size_t row = 0; row < 18; row++) {
+        bool back = (layer % 2);
+        std::vector<ModulePosition> rowModulePositions = calculateHgtdModulePositionsInRow(row, back);
+        modulePositions.insert(modulePositions.end(), rowModulePositions.begin(), rowModulePositions.end());
+    }
+    return modulePositions;
+}
+
+std::vector<ModulePosition> HGTD_DetectorFactory::calculateHgtdModulePositionsInRow(int row, bool back) {
+
+    unsigned int module = 0;
+    std::vector<ModulePosition> modulePositions;
+    double posOfLastPlacedModule = 0.;
+
+    while (true) {
+        //msg(MSG::INTO) << "Will now place module " << module << endmsg;
+        // horizontal rows need care (restart from other edge of quadrant), this variable helps get the inner radius right
+        // in quadrant 0 - ie top right quadrant
+        // row 0 = bottom horizontal row. numbering grows upwards and counterclockwise; row 17=leftmost vertical row
+        // rowForInnerRadius = 0-1 for vertical rows too
+        int rowForInnerRadius = row; // because row 16-17 are equivalent to 0-1 regarding module placement
+        if (row == 17) rowForInnerRadius = 0;
+        if (row == 16) rowForInnerRadius = 1;
+
+        // params needed frequently below
+        double moduleWidth = m_boxVolPars["HGTDModule0"].yHalf*2;
+        double moduleHeight = m_boxVolPars["HGTDModule0"].xHalf*2;
+        double rInner = m_cylVolPars["HGTD::ModuleLayer0"].rMin;
+        double rMid = m_hgtdPars.rMid;
+        double rOuter = m_hgtdPars.rOuter;
+        double rowSpaceSide = m_hgtdPars.rowSpaceSide;
+
+        // x coordinate for vertical rows
+        double rowCenterPos = (moduleWidth + rowSpaceSide)*(rowForInnerRadius + 0.5);
+        // y coordinate for vertical rows
+        double modulePosAlongRow = -99.; // mock value for now
+        // for the first module, pick the right starting point
+        if (module == 0) {
+            // start at inner radius and include any offset for backside.
+            if (rowForInnerRadius < 3) {
+                modulePosAlongRow = sqrt( pow(rInner, 2) - pow((moduleWidth + rowSpaceSide)*rowForInnerRadius, 2) )
+                                    + back*m_hgtdPars.rowBacksideInnerShift + moduleHeight/2;
+            }
+            else { // later modules start at 2*moduleWidth, with offset for the backside
+                double backSpacing = m_hgtdPars.rowBacksideInnerShift;
+                if (back && (rowCenterPos - moduleWidth/2 > rMid)) {
+                    backSpacing = m_hgtdPars.rowBacksideOuterShift;
+                }
+                modulePosAlongRow = 2*(moduleWidth + rowSpaceSide) + moduleHeight/2 + back*backSpacing;
+            }
+        }
+        // the rest of the modules follow sequential, radius-dependent placement rules
+        else {
+            ModulePosition prev = modulePositions.back();
+            double spacing = m_hgtdPars.moduleSpaceInner;
+            // if the previous module was completely outside rMid, increase the spacing
+            // (+1 mm is a needed shift for full coverage - could need tweaking if layout parameters change!)
+            float innermostCornerR = sqrt( pow(prev.y - moduleHeight/2, 2) + pow(prev.x - moduleWidth/2, 2) ) + 1.;
+            if (innermostCornerR > rMid) {
+                spacing = m_hgtdPars.moduleSpaceOuter;
+            }
+            // for the back the large spacing starts as soon as the space would entirely be outside R = 320 mm
+            if (back) {
+                double startOfSpaceAlongRow = sqrt( pow(prev.y + moduleHeight/2, 2) + pow(prev.x - moduleWidth/2, 2)) - 2;
+                if (startOfSpaceAlongRow > rMid) {
+                    spacing = m_hgtdPars.moduleSpaceOuter;
+                }
+            }
+            // correction to the first two spaces on the front side, compensating for the 2 mm introduced at beginning of a row
+            if (!back && rowForInnerRadius < 8 && module < 3) {
+                spacing -= 1.; // should result in 3 mm instead of 4 mm for innermost spaces on rows starting at R = 120
+            }
+            // squeeze in a few more modules at the end of some rows
+            double maxRcut = rOuter+20;
+            if(row == 8 || row == 9 || row == 10) {
+                maxRcut = 661;
+                if(row == 8 && module > 12) spacing -= 4;
+            }
+            else if ( row == 11 && module > 9) {
+                maxRcut = 662;
+                spacing -= 6;
+            }
+            else if (row == 12 && back) {
+                maxRcut = 665;
+            }
+            else if(row == 13 && module > 5) {
+                maxRcut = 666;
+                if (!back && module > 6 ) spacing -= 8.5;
+                else if (back && module > 5) spacing -= 2;
+            }
+            else if (row == 14 && module > 3) {
+                maxRcut = 665;
+                spacing -= 5;
+            }
+            else if (row == 15) {
+                maxRcut = 669;
+                spacing -= 5.5;
+            }
+            modulePosAlongRow = posOfLastPlacedModule + moduleHeight + spacing;
+            // stop if the next module will extend outside the max allowed radius
+            // HC max radius is 665
+            if (sqrt( pow(rowCenterPos + moduleWidth/2, 2) + pow(modulePosAlongRow + moduleHeight/2, 2) ) > maxRcut) {
+                break;
+            }
+        }
+        ModulePosition m = {rowCenterPos, modulePosAlongRow, 0, true, row, (int)module};
+        modulePositions.push_back(m);
+        posOfLastPlacedModule = modulePosAlongRow;
+        module += 1;
+    } // end of loop over modules
+
+    // finally, flip x and y for all modules if this row is horizontal
+    if (row < 16) {
+        // msg(MSG::INFO) << "Flipping x and y for modules in row " << row << endmsg;
+        for (size_t i=0; i < modulePositions.size(); i++) {
+            ModulePosition old = modulePositions[i];
+            ModulePosition rotated = old;
+            rotated.x = old.y;
+            rotated.y = old.x;
+            rotated.flipped = !old.flipped;
+            rotated.row = old.row;
+            rotated.el_in_row = old.el_in_row;
+            modulePositions[i] = rotated;
+        }
+    }
+
+    //std::cout << "row = " << row << std::endl;
+    //for(size_t i=0; i < modulePositions.size(); i++) {
+    //    std::cout << "Module " << i << " at (x,y) = (" << modulePositions[i].x << "," << modulePositions[i].y << ")" << std::endl;
+    //}
+
+    return modulePositions;
+}
+
+InDetDD::PixelModuleDesign* HGTD_DetectorFactory::createPixelDesign(double thickness, bool isBaseline, bool /*isflipped*/) {
+
+    double phiPitch = 1.3; // mm
+    double etaPitch = 1.3; // mm
+
+    int colsPerChip = 30;
+    int rowsPerChip = 15;
+
+    int readout_side = 1;
+
+    if (not isBaseline) {
+        phiPitch = 1.0; // mm
+        etaPitch = 1.0; // mm
+
+        colsPerChip = 39;
+        rowsPerChip = 20;
+    }
+
+    // if (isflipped) std::swap(colsPerChip, rowsPerChip);
+
+    InDetDD::PixelDiodeMatrix* normalCell = new InDetDD::PixelDiodeMatrix(phiPitch, etaPitch);
+    InDetDD::PixelDiodeMatrix* singleRow  = new InDetDD::PixelDiodeMatrix(InDetDD::PixelDiodeMatrix::etaDir, 0, normalCell, colsPerChip, 0);
+    InDetDD::PixelDiodeMatrix* fullMatrix = new InDetDD::PixelDiodeMatrix(InDetDD::PixelDiodeMatrix::phiDir, 0,  singleRow, rowsPerChip, 0);
+
+    int circuitsPhi = 1;
+    int circuitsEta = 1;
+
+    InDetDD::PixelModuleDesign* design = new InDetDD::PixelModuleDesign( thickness, circuitsPhi, circuitsEta,
+                                                                         colsPerChip, rowsPerChip, colsPerChip, rowsPerChip,
+                                                                         fullMatrix, InDetDD::CarrierType::electrons, readout_side);
+
+    return design;
+
+}
+
+HGTD_DetectorManager* HGTD_DetectorFactory::getDetectorManager() const {
+    return m_detectorManager;
+}
+
+} // End HGTDGeo namespace
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/HGTD_DetectorTool.cxx b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/HGTD_DetectorTool.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..db09561b61e0c490a7765359497209db078271fc
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/HGTD_DetectorTool.cxx
@@ -0,0 +1,138 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+// includes
+#include "HGTD_GeoModel/HGTD_DetectorTool.h"
+#include "HGTD_GeoModel/HGTD_DetectorFactory.h"
+#include "HGTD_ReadoutGeometry/HGTD_DetectorManager.h"
+#include "InDetGeoModelUtils/InDetDDAthenaComps.h"
+#include "GeoModelUtilities/GeoModelExperiment.h"
+#include "GeoModelInterfaces/IGeoModelSvc.h"
+#include "GeoModelUtilities/DecodeVersionKey.h"
+#include "StoreGate/StoreGateSvc.h"
+#include "GeometryDBSvc/IGeometryDBSvc.h"
+#include "RDBAccessSvc/IRDBAccessSvc.h"
+#include "RDBAccessSvc/IRDBRecord.h"
+#include "RDBAccessSvc/IRDBRecordset.h"
+#include "DetDescrConditions/AlignableTransformContainer.h"
+
+#include "CLIDSvc/tools/ClassID_traits.h"
+#include "SGTools/DataProxy.h"
+
+HGTD_DetectorTool::HGTD_DetectorTool(const std::string &type,
+                                     const std::string &name,
+                                     const IInterface *parent) :
+    GeoModelTool(type, name, parent),
+    m_detectorName("HGTD"),
+    m_alignable(false),
+    m_manager(0),
+    m_athenaComps(0),
+    m_geoModelSvc("GeoModelSvc", name),
+    m_rdbAccessSvc("RDBAccessSvc", name),
+    m_geometryDBSvc("InDetGeometryDBSvc", name),
+    m_geometryConfig("FULL"),
+    m_HGTD_isbaseline(true)
+{
+//
+// Get parameter values from jobOptions file
+//
+    declareProperty("DetectorName", m_detectorName);
+    declareProperty("Alignable", m_alignable);
+    declareProperty("GeoModelSvc", m_geoModelSvc);
+    declareProperty("RDBAccessSvc", m_rdbAccessSvc);
+    declareProperty("GeometryDBSvc", m_geometryDBSvc);
+    declareProperty("GeometryConfig", m_geometryConfig);
+    declareProperty("HGTD_BaselineReadout", m_HGTD_isbaseline);
+}
+
+HGTD_DetectorTool::~HGTD_DetectorTool() {
+    delete m_athenaComps;
+}
+
+StatusCode HGTD_DetectorTool::create(StoreGateSvc* detStore) {
+//
+//   Retrieve all services except LorentzAngleSvc, which has to be done later
+//
+
+    ATH_CHECK(m_geoModelSvc.retrieve());
+    ATH_CHECK(m_rdbAccessSvc.retrieve());
+    ATH_CHECK(m_geometryDBSvc.retrieve());
+    ATH_CHECK(m_geoModelSvc.retrieve());
+
+    GeoModelExperiment *theExpt;
+    ATH_CHECK(detStore->retrieve(theExpt, "ATLAS"));
+
+//
+//    Get their interfaces to pass to the DetectorFactory
+//
+    m_athenaComps = new InDetDD::AthenaComps("HGTD_GeoModel");
+    m_athenaComps->setDetStore(detStore);
+    m_athenaComps->setGeoModelSvc(&*m_geoModelSvc);
+    m_athenaComps->setRDBAccessSvc(&*m_rdbAccessSvc);
+    m_athenaComps->setGeometryDBSvc(&*m_geometryDBSvc);
+
+//
+//   Get the version and configure things accordingly here
+//
+
+//
+// Create the HGTD_DetectorFactory
+//
+    // The * converts a ConstPVLink to a ref to a GeoVPhysVol
+    // The & takes the address of the GeoVPhysVol
+    GeoPhysVol *world = &*theExpt->getPhysVol();
+    HGTDGeo::HGTD_DetectorFactory theHGTDFactory(m_athenaComps, m_geometryConfig=="FULL");
+    theHGTDFactory.setHGTDBaseline(m_HGTD_isbaseline);
+
+    theHGTDFactory.create(world);
+//
+// Get the manager from the factory and store it in the detector store.
+//
+    m_manager = theHGTDFactory.getDetectorManager();
+
+    if (!m_manager) {
+        msg(MSG::ERROR) << "HGTD_DetectorManager not found; not created in HGTD_DetectorFactory?" << endmsg;
+        return(StatusCode::FAILURE);
+    }
+
+    ATH_CHECK(detStore->record(m_manager, m_manager->getName()));
+    theExpt->addManager(m_manager);
+
+//
+//    And retrieve the LorentzAngleService. Has to be after the symLink just made,
+//    which has to be after the manager is made by the DetectorFactory.
+//
+
+    return StatusCode::SUCCESS;
+}
+
+StatusCode HGTD_DetectorTool::clear(StoreGateSvc* detStore) {
+
+    // Release manager from the detector store
+    SG::DataProxy* _proxy = detStore->proxy(ClassID_traits<HGTD_DetectorManager>::ID(),m_manager->getName());
+    if(_proxy) {
+      _proxy->reset();
+      m_manager = 0;
+    }
+
+    return StatusCode::SUCCESS;
+}
+
+StatusCode HGTD_DetectorTool::registerCallback(StoreGateSvc* /*detStore*/) {
+//
+//    Register call-back for software alignment
+//
+    msg(MSG::WARNING) << "No callback registration has yet been implemented for HGTD, nothing to do!" << endmsg;
+
+    return StatusCode::SUCCESS;
+}
+
+StatusCode HGTD_DetectorTool::align(IOVSVC_CALLBACK_ARGS_P(/*I*/, /*keys*/)) {
+//
+//    The call-back routine, which just calls the real call-back routine from the manager.
+//
+    msg(MSG::WARNING) << "No alignment method in HGTD_DetectorManager implemented yet, nothing to do!" << endmsg;
+
+    return StatusCode::SUCCESS;
+}
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/components/HGTD_GeoModel_entries.cxx b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/components/HGTD_GeoModel_entries.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..96eaf74304985dc22dc9c4a5508996018667bb17
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/components/HGTD_GeoModel_entries.cxx
@@ -0,0 +1,8 @@
+#include "HGTD_GeoModel/HGTD_DetectorTool.h"
+#include "GaudiKernel/DeclareFactoryEntries.h"
+
+DECLARE_TOOL_FACTORY(HGTD_DetectorTool)
+
+DECLARE_FACTORY_ENTRIES(HGTD_GeoModel) {
+    DECLARE_ALGTOOL(HGTD_DetectorTool)
+}
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/components/HGTD_GeoModel_load.cxx b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/components/HGTD_GeoModel_load.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..e6b33833e33904efbc0c10b9d52eecf0c5dfd976
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_GeoModel/src/components/HGTD_GeoModel_load.cxx
@@ -0,0 +1,3 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+LOAD_FACTORY_ENTRIES(HGTD_GeoModel)
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_ReadoutGeometry/CMakeLists.txt b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_ReadoutGeometry/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..54a2db7bfc3557eed984f5d64caea262bec386b2
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_ReadoutGeometry/CMakeLists.txt
@@ -0,0 +1,34 @@
+################################################################################
+# Package: HGTD_ReadoutGeometry
+################################################################################
+
+# Declare the package name:
+atlas_subdir( HGTD_ReadoutGeometry )
+
+# Declare the package's dependencies:
+atlas_depends_on_subdirs( PUBLIC
+                          Control/AthenaKernel
+                          Control/CLIDSvc
+                          Control/SGTools
+                          Control/StoreGate
+                          DetectorDescription/AtlasDetDescr
+                          DetectorDescription/GeoModel/GeoModelKernel
+                          DetectorDescription/GeoPrimitives
+                          DetectorDescription/Identifier
+                          GaudiKernel
+                          PRIVATE
+                          Database/AthenaPOOL/AthenaPoolUtilities
+                          DetectorDescription/IdDictDetDescr )
+
+# External dependencies:
+find_package( CLHEP )
+find_package( Eigen )
+
+# Component(s) in the package:
+atlas_add_library( HGTD_ReadoutGeometryLib
+                   src/*.cxx
+                   PUBLIC_HEADERS HGTD_ReadoutGeometry
+                   INCLUDE_DIRS ${CLHEP_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}
+                   DEFINITIONS ${CLHEP_DEFINITIONS}
+                   LINK_LIBRARIES ${CLHEP_LIBRARIES} ${EIGEN_LIBRARIES} AthenaKernel SGTools AtlasDetDescr GeoModelKernel GeoPrimitives Identifier GaudiKernel StoreGateLib SGtests
+                   PRIVATE_LINK_LIBRARIES AthenaPoolUtilities DetDescrConditions IdDictDetDescr )
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_ReadoutGeometry/HGTD_ReadoutGeometry/HGTD_DetectorManager.h b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_ReadoutGeometry/HGTD_ReadoutGeometry/HGTD_DetectorManager.h
new file mode 100644
index 0000000000000000000000000000000000000000..e1641538c10918d7b2c0ed3c2203c09b5d096f03
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_ReadoutGeometry/HGTD_ReadoutGeometry/HGTD_DetectorManager.h
@@ -0,0 +1,44 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef HGTD_READOUTGEOMETRY_HGTD_DETECTORMANAGER_H
+#define HGTD_READOUTGEOMETRY_HGTD_DETECTORMANAGER_H
+
+#include "GeoPrimitives/GeoPrimitives.h"
+
+#include "GeoModelKernel/GeoVPhysVol.h"
+#include "GeoModelKernel/GeoVDetectorManager.h"
+
+// class StoreGateSvc;
+// class Identifier;
+// class IdentifierHash;
+// class GeoAlignableTransform;
+// class GeoVFullPhysVol;
+// class GeoVPhysVol;
+
+class HGTD_DetectorManager : public GeoVDetectorManager {
+public:
+    HGTD_DetectorManager();
+    virtual ~HGTD_DetectorManager();
+
+    virtual unsigned int getNumTreeTops()           const;
+    virtual PVConstLink  getTreeTop(unsigned int i) const;
+    virtual void addTreeTop (PVLink treeTop);
+
+private:
+    /** Prevent copy and assignment */
+    const HGTD_DetectorManager & operator=(const HGTD_DetectorManager &right);
+    HGTD_DetectorManager(const HGTD_DetectorManager &right);
+
+    // Private member data
+    std::vector<PVLink> m_volume;
+
+};
+
+#ifndef GAUDI_NEUTRAL
+#include "CLIDSvc/CLASS_DEF.h"
+CLASS_DEF(HGTD_DetectorManager, 73488296, 1)
+#endif
+
+#endif // HGTD_READOUTGEOMETRY_HGTD_DETECTORMANAGER_H
diff --git a/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_ReadoutGeometry/src/HGTD_DetectorManager.cxx b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_ReadoutGeometry/src/HGTD_DetectorManager.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..362418f1acd2517d9a2f5bef05d7f82a8610138f
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_DetDescr/HGTD_ReadoutGeometry/src/HGTD_DetectorManager.cxx
@@ -0,0 +1,24 @@
+/*
+  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "HGTD_ReadoutGeometry/HGTD_DetectorManager.h"
+
+HGTD_DetectorManager::HGTD_DetectorManager(){}
+
+HGTD_DetectorManager::~HGTD_DetectorManager(){}
+
+unsigned int HGTD_DetectorManager::getNumTreeTops() const
+{
+    return m_volume.size();
+}
+
+PVConstLink HGTD_DetectorManager::getTreeTop(unsigned int i) const
+{
+    return m_volume[i];
+}
+
+void HGTD_DetectorManager::addTreeTop(PVLink vol){
+    vol->ref();
+    m_volume.push_back(vol);
+}
diff --git a/HighGranularityTimingDetector/HGTD_Digitization/README.md b/HighGranularityTimingDetector/HGTD_Digitization/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0397769e8fc474660ade35b4706a2e2799fd5f80
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_Digitization/README.md
@@ -0,0 +1 @@
+For now this dir holds empty folders representing the future HGTD packages in 21.9
\ No newline at end of file
diff --git a/HighGranularityTimingDetector/HGTD_Reconstruction/README.md b/HighGranularityTimingDetector/HGTD_Reconstruction/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0397769e8fc474660ade35b4706a2e2799fd5f80
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_Reconstruction/README.md
@@ -0,0 +1 @@
+For now this dir holds empty folders representing the future HGTD packages in 21.9
\ No newline at end of file
diff --git a/HighGranularityTimingDetector/HGTD_Simulation/README.md b/HighGranularityTimingDetector/HGTD_Simulation/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0397769e8fc474660ade35b4706a2e2799fd5f80
--- /dev/null
+++ b/HighGranularityTimingDetector/HGTD_Simulation/README.md
@@ -0,0 +1 @@
+For now this dir holds empty folders representing the future HGTD packages in 21.9
\ No newline at end of file
diff --git a/HighGranularityTimingDetector/README.md b/HighGranularityTimingDetector/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..0397769e8fc474660ade35b4706a2e2799fd5f80
--- /dev/null
+++ b/HighGranularityTimingDetector/README.md
@@ -0,0 +1 @@
+For now this dir holds empty folders representing the future HGTD packages in 21.9
\ No newline at end of file