From 89de6d6a3699ee5afcbe9d060d92465b977b7e64 Mon Sep 17 00:00:00 2001
From: Alexandru Bercuci <abercuci@niham.nipne.ro>
Date: Tue, 27 Feb 2024 09:24:44 +0000
Subject: [PATCH] Create geometry of the TRD2D chamber in compiled code.

Move macro code from Create_geometry_* macro to namespace cbm::trd:geo.
Implement the latest modifications to the design of the chamber and FEB as they are proposed for day 1.
---
 core/detectors/trd/CMakeLists.txt           |   4 +-
 core/detectors/trd/CbmTrdBaseLinkDef.h      |  21 +-
 core/detectors/trd/CbmTrdDefs.cxx           |  20 +
 core/detectors/trd/CbmTrdDefs.h             | 180 ++++-
 core/detectors/trd/CbmTrdGeoFactory.cxx     | 700 ++++++++++++++++++++
 core/detectors/trd/CbmTrdGeoFactory.h       | 352 ++++++++++
 core/detectors/trd/CbmTrdGeoSetup.cxx       | 491 ++++++++++++++
 core/detectors/trd/CbmTrdGeoSetup.h         | 204 ++++++
 core/detectors/trd/CbmTrdModuleAbstract.cxx |  28 +-
 core/detectors/trd/CbmTrdModuleAbstract.h   |  77 +--
 core/detectors/trd/CbmTrdParMod.cxx         |   6 +-
 core/detectors/trd/CbmTrdParMod.h           |  23 +-
 core/detectors/trd/CbmTrdParModDigi.cxx     |  13 +-
 core/detectors/trd/CbmTrdParModDigi.h       |  15 +-
 core/detectors/trd/CbmTrdParSpadic.cxx      |  25 +-
 reco/detectors/trd/CbmTrdHitProducer.cxx    |  38 +-
 sim/detectors/trd/CbmTrdDigitizer.cxx       |  39 +-
 17 files changed, 2084 insertions(+), 152 deletions(-)
 create mode 100644 core/detectors/trd/CbmTrdDefs.cxx
 create mode 100644 core/detectors/trd/CbmTrdGeoFactory.cxx
 create mode 100644 core/detectors/trd/CbmTrdGeoFactory.h
 create mode 100644 core/detectors/trd/CbmTrdGeoSetup.cxx
 create mode 100644 core/detectors/trd/CbmTrdGeoSetup.h

diff --git a/core/detectors/trd/CMakeLists.txt b/core/detectors/trd/CMakeLists.txt
index 5b61e9fcad..3855747d70 100644
--- a/core/detectors/trd/CMakeLists.txt
+++ b/core/detectors/trd/CMakeLists.txt
@@ -3,10 +3,13 @@ set(INCLUDE_DIRECTORIES
   )
 
 set(SRCS
+  CbmTrdDefs.cxx
   CbmTrdGas.cxx
   CbmTrdContFact.cxx
   CbmTrdParManager.cxx
   CbmTrdModuleAbstract.cxx
+  CbmTrdGeoFactory.cxx
+  CbmTrdGeoSetup.cxx
   CbmMcbm2020TrdTshiftPar.cxx
   CbmTrdParSet.cxx
   CbmTrdParSetAsic.cxx
@@ -74,6 +77,5 @@ generate_cbm_library()
 
 # Install file which has no corresponding source file
 install(FILES
-        CbmTrdDefs.h
         DESTINATION include
        )
diff --git a/core/detectors/trd/CbmTrdBaseLinkDef.h b/core/detectors/trd/CbmTrdBaseLinkDef.h
index 6f08f8e0b7..b191955c75 100644
--- a/core/detectors/trd/CbmTrdBaseLinkDef.h
+++ b/core/detectors/trd/CbmTrdBaseLinkDef.h
@@ -1,6 +1,6 @@
-/* Copyright (C) 2018-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
-   Authors: Florian Uhlig [committer] */
+   Authors: Florian Uhlig [committer], Alexandru Bercuci */
 
 // $Id: TrdBaseLinkDef.h $
 
@@ -10,11 +10,28 @@
 #pragma link off all classes;
 #pragma link off all functions;
 
+#pragma link C++ namespace cbm::trd;
+#pragma link C++ enum cbm::trd::eAsic;
+#pragma link C++ enum cbm::trd::ePadPlane;
+#pragma link C++ enum cbm::trd::eModuleConfig;
 #pragma link C++ class CbmTrdGas + ;
 #pragma link C++ class CbmTrdContFact + ;
 #pragma link C++ class CbmMcbm2020TrdTshiftPar + ;
 #pragma link C++ class CbmTrdModuleAbstract + ;
 
+#pragma link C++ namespace cbm::trd::geo;
+#pragma link C++ class cbm::trd::geo::ChamberBuilder + ;
+#pragma link C++ class cbm::trd::geo::ChamberBuilder::Component + ;
+#pragma link C++ class cbm::trd::geo::ChamberBuilder::Radiator + ;
+#pragma link C++ class cbm::trd::geo::ChamberBuilder::Window + ;
+#pragma link C++ class cbm::trd::geo::ChamberBuilder::Volume + ;
+#pragma link C++ class cbm::trd::geo::ChamberBuilder::BackPanel + ;
+#pragma link C++ class cbm::trd::geo::ChamberBuilder::FEB + ;
+#pragma link C++ class cbm::trd::geo::SetupManager + ;
+#pragma link C++ class cbm::trd::geo::Setup + ;
+#pragma link C++ class cbm::trd::geo::Setup::Module + ;
+#pragma link C++ class cbm::trd::geo::Setup::Asic + ;
+
 #pragma link C++ class CbmTrdParManager + ;
 #pragma link C++ class CbmTrdParSet + ;
 #pragma link C++ class CbmTrdParSetAsic + ;
diff --git a/core/detectors/trd/CbmTrdDefs.cxx b/core/detectors/trd/CbmTrdDefs.cxx
new file mode 100644
index 0000000000..e1272909d7
--- /dev/null
+++ b/core/detectors/trd/CbmTrdDefs.cxx
@@ -0,0 +1,20 @@
+/* Copyright (C) 2024 Hulubei National Institute of Physics and Nuclear Engineering - Horia Hulubei, Bucharest
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Alexandru Bercuci [committer] */
+
+#include "CbmTrdDefs.h"
+
+using namespace cbm::trd;
+
+bool cbm::trd::HasFaspFEE(uint16_t config) { return TESTBIT(config, eModuleConfig::kFEEtyp); }
+bool cbm::trd::HasSpadicFEE(uint16_t config) { return !HasFaspFEE(config); }
+bool cbm::trd::HasPadPlane2D(uint16_t config) { return TESTBIT(config, eModuleConfig::kPPtyp); }
+bool cbm::trd::HasPadPlane1D(uint16_t config) { return !HasPadPlane2D(config); }
+void cbm::trd::SetFEE(uint16_t config, bool fasp)
+{
+  fasp ? SETBIT(config, eModuleConfig::kFEEtyp) : CLRBIT(config, eModuleConfig::kFEEtyp);
+}
+void cbm::trd::SetPP(uint16_t config, bool twod)
+{
+  twod ? SETBIT(config, eModuleConfig::kPPtyp) : CLRBIT(config, eModuleConfig::kPPtyp);
+}
diff --git a/core/detectors/trd/CbmTrdDefs.h b/core/detectors/trd/CbmTrdDefs.h
index 9940d58857..e8576dce03 100644
--- a/core/detectors/trd/CbmTrdDefs.h
+++ b/core/detectors/trd/CbmTrdDefs.h
@@ -1,6 +1,6 @@
-/* Copyright (C) 2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2020-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
-   Authors: Pascal Raisig, Florian Uhlig [committer] */
+   Authors: Pascal Raisig, Florian Uhlig [committer], Alexandru Bercuci */
 
 /*
  * Purpose: Reference class for global definitions used within the CbmTrd project
@@ -12,17 +12,173 @@
 
 #include "Rtypes.h"
 
-enum class eCbmTrdModuleTypes : Int_t
+namespace cbm::trd
 {
-  kHighChDensitySmallR = 1,
-  kLowChDensitySmallR  = 3,
-  kHighChDensityLargeR = 5,
-  kLowChDensityLargeR  = 7,
-  kMcbmModule =
-    8  // FIXME moduleType 8 has multiple definitions, check if non mCbm definitions are really needed. - PR 03/25/2020
-    ,
-  kNmoduleTypes = 5  // REMARK this number has to be updated by hand!
-};                   ///< Enum for moduleTypes of the rectangular TrdModules as used in geometry files.
+  enum class eAsic : int
+  {
+    kSpadic = 0  ///< SPADIC type definition
+      ,
+    kFasp = 1  ///< FASP ASIC definition
+      ,
+    kNotSet  ///< ASIC not set / recognized
+  };
+  enum class ePadPlane : int
+  {
+    k1d = 0  ///< rectangular 1D case
+      ,
+    k2d = 1  ///< triangular 2D case
+      ,
+    kNotSet  ///< pad=plane not set / recognized
+  };
+  enum class eWindow : int
+  {
+    kThin = 0  ///< 1D case (Al+mylar)
+      ,
+    kThick  ///< 2D case (Kapton + C + HC)
+      ,
+    kNotSet  ///< window not set / recognized
+  };
+  enum class eGas : int
+  {
+    kAr = 0  ///< ArCO2 active gas
+      ,
+    kXe  ///< XeCO2 active gas
+      ,
+    kNotSet  ///< active gas not set / recognized
+  };
+  /** 16 bits bit map for module configuration
+   * [0] - chamber's pad-plane type; 0 rectangular pads, 1 triangular pads, \see SetRO
+   * [1] - chamber's FEE type; 0 SPADIC, 1 FASP, \see SetFEE
+   * [2] -  
+   * [3] -  
+   * [4] -  
+   * [5] -  
+   * [6] -  
+   * [7] -  
+   */
+  enum eModuleConfig
+  {
+    kPPtyp = 0  ///< toggle pad-plane type of the chamber
+      ,
+    kFEEtyp = 1  ///< toggle FEE type for the module
+  };
 
+  enum class eModuleTypes1D : int
+  {
+    kHighChDensitySmallR = 1,
+    kLowChDensitySmallR  = 3,
+    kHighChDensityLargeR = 5,
+    kLowChDensityLargeR  = 7,
+    kMcbmModule =
+      8  // FIXME moduleType 8 has multiple definitions, check if non mCbm definitions are really needed. - PR 03/25/2020
+      ,
+    kNmoduleTypes = 5  // REMARK this number has to be updated by hand!
+  };                   ///< Enum for moduleTypes of the rectangular TrdModules as used in geometry files.
+  struct FEB {
+    int nasic     = 0;  ///< no of asics / feb
+    int nchannels = 0;  ///< no of channels / asic
+    int nmax      = 0;  ///< max no of febs on the module
+  };
+  struct READOUT {
+    int nsec       = 0;     ///< no of sectors on the pad-plane
+    int ncol       = 0;     ///< no of (rectangular - pads) column
+    int nrow       = 0;     ///< no of pad rows
+    int nasic      = 0;     ///< no of ASICs to read-out the pad-plane
+    int ndaq       = 0;     ///< no of concentrators (e.g. CROB) to read-out the pad-plane
+    float sizex    = 0.;    ///< size of active area along wires
+    float sizey[3] = {0.};  ///< size of active area across wires
+  };
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wunused-variable"
+  // array of pad geometries in the TRD1D
+  static READOUT mod1D[9] = {
+    // module type 0 dummy
+    {0, 0, 0, 0, 0, 0., {0., 0., 0.}},
+    // module type 1
+    // number of pads:  80 x 32 = 2560
+    // pad size sector 1:  0.68 cm x  1.75 cm =  1.18 cm2
+    // pad size sector 0:  0.68 cm x  1.50 cm =  1.01 cm2
+    {3, 80, 32, 80, 5, 54., {6.0, 42.0, 6.0}},
+    // module type 2
+    // number of pads:  80 x 16 = 1280
+    // pad size sector 1:  0.68 cm x  3.50 cm =  2.36 cm2
+    // pad size sector 0:  0.68 cm x  3.25 cm =  2.19 cm2
+    {3, 80, 16, 80, 5, 54., {13.0, 28.0, 13.0}},
+    // module type 3
+    // number of pads:  80 x  8 =  640
+    // number of asic:  20
+    // pad size sector 1:  0.68 cm x  6.75 cm =  4.56 cm2
+    // pad size sector 0:  0.68 cm x  6.75 cm =  4.56 cm2
+    {1, 80, 8, 20, 1, 54., {54., 0., 0.}},
+    // module type 4
+    // number of pads:  80 x  8 =  640
+    // pad size sector 1:  0.68 cm x  6.75 cm =  4.56 cm2
+    // pad size sector 0:  0.68 cm x  6.75 cm =  4.56 cm2
+    {1, 80, 8, 20, 1, 54., {54., 0., 0.}},
+    // module type 5
+    // number of pads: 144 x 24 = 3456
+    // number of asic: 36
+    // pad size sector 1:  0.67 cm x  4.00 cm =  2.67 cm2
+    // pad size sector 0:  0.67 cm x  4.00 cm =  2.67 cm2
+    {1, 144, 24, 108, 2, 96., {96.0, 0., 0.}},
+    // module type 6
+    // number of pads: 144 x 16 = 2304
+    // pad size sector 1:  0.67 cm x  6.00 cm =  4.00 cm2
+    // pad size sector 0:  0.67 cm x  6.00 cm =  4.00 cm2
+    {1, 144, 16, 72, 2, 96., {96.0, 0., 0.}},
+    // module type 7
+    // number of pads: 144 x  8 = 1152
+    // number of asic: 36
+    // pad size sector 1:  0.67 cm x 12.00 cm =  8.00 cm2
+    // pad size sector 0:  0.67 cm x 12.00 cm =  8.00 cm2
+    {1, 144, 8, 36, 2, 96., {96.0, 0., 0.}},
+    // module type 8
+    // number of pads: 144 x  4 =  576
+    // pad size sector 1:  0.67 cm x 24.00 cm = 16.00 cm2
+    // pad size sector 0:  0.67 cm x 24.00 cm = 16.00 cm2
+    {1, 144, 4, 18, 1, 96., {96.0, 0., 0.}}};
+
+  // array of pad geometries in the TRD2D
+  static const READOUT mod2D[3] = {
+    // module type 1 (TRD2D @ CBM)
+    // number of pads:  72 x 20 = 1440
+    // pad size:  0.75 cm x  2.70 cm =  2.03 cm2
+    // number of asic:  180
+    // number of crob:  5
+    {1, 72, 20, 180, 5, 54.0, {54.0, 0., 0.}},
+    // module type 9 (TRD2012 @ mCBM)
+    // number of pads:  72 x 20 = 1440
+    // pad size:  0.75 cm x  2.79 cm =  2.03 cm2
+    {1, 72, 20, 180, 5, 54.0, {55.8, 0., 0.}},
+    // module type 10 (TRD2010)
+    // number of pads:  32 x  3 =   96
+    // pad size :  0.72 cm x  2.72 cm =  1.96 cm2
+    {1, 32, 3, 6, 1, 23.04, {8.16, 0., 0.}}};
+
+  static constexpr FEB faspFeb[2] = {
+    {6, 16, 30},  ///< FASPRO v1
+    {12, 16, 15}  ///< FASPRO v2
+  };
+#pragma GCC diagnostic pop
+
+  /** \brief Inquire the FEE read-out type of the module
+   * \return false for SPADIC and true for FASP
+   */
+  bool HasFaspFEE(uint16_t config);
+  bool HasSpadicFEE(uint16_t config);
+  /** \brief Inquire the pad-plane type of the chamber
+   * \return false for TRD-1D and true for TRD-2D
+   */
+  bool HasPadPlane2D(uint16_t config);
+  bool HasPadPlane1D(uint16_t config);
+  /** \brief Define the read-out FEE type of the module
+   * \param[in] set true for FASP and false [default] for SPADIC
+   */
+  void SetFEE(uint16_t config, bool fasp = true);
+  /** \brief Define the pad-plane type of the chamber
+   * \param[in] set true for TRD-2D and false [default] for TRD-1D
+   */
+  void SetPP(uint16_t config, bool twod = true);
+}  // namespace cbm::trd
 
 #endif
diff --git a/core/detectors/trd/CbmTrdGeoFactory.cxx b/core/detectors/trd/CbmTrdGeoFactory.cxx
new file mode 100644
index 0000000000..1c79aaf660
--- /dev/null
+++ b/core/detectors/trd/CbmTrdGeoFactory.cxx
@@ -0,0 +1,700 @@
+/* Copyright (C) 2024 National Institute of Physics and Nuclear Engineering - Horia Hulubei, Bucharest
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Alexandru Bercuci [committer] */
+
+/**
+ * \file CbmTrdGeoFactory.cxx
+ * \brief TRD chamber manager class.
+ * \author Alexandru Bercuci <abercuci@niham.nipne.ro>
+ * \date 01/10/2023
+*/
+#include "CbmTrdGeoFactory.h"
+
+// #include "CbmTrdConstructionDB.h"
+#include "CbmTrdAddress.h"
+
+#include <Logger.h>  // for LOG, Logger
+
+#include <TGeoBBox.h>
+#include <TGeoCompositeShape.h>
+#include <TGeoManager.h>
+#include <TGeoMatrix.h>
+#include <TGeoMedium.h>
+#include <TGeoVolume.h>
+#include <TROOT.h>
+
+#include <cassert>
+using namespace cbm::trd;
+using namespace cbm::trd::geo;
+
+const char* ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kNparts] = {"Radiator", "Window",
+                                                                                          "Volume", "BackPanel", "FEB"};
+//________________________________________________________________________________________
+const TGeoMedium* cbm::trd::geo::GetMaterial(const char* mname)
+{
+  if (fMaterial.find(mname) == fMaterial.end()) {
+    LOG(error) << "GetMaterial(" << mname << ") failed.";
+    return nullptr;
+  }
+  return fMaterial.at(mname);
+}
+
+//__________________________________________________________________
+bool cbm::trd::geo::ReadModuleInfo(const char* modTxt, info_t& info)
+{
+  // parse module info
+  string modName  = modTxt;
+  auto posstart   = modName.find("module") + 6;
+  uint ndigits    = 0;
+  auto partoftype = modName.at(posstart);
+  while (std::isdigit(partoftype) && (ndigits + posstart) < modName.size()) {
+    partoftype = modName.at(posstart + ndigits);
+    ++ndigits;
+  }
+  info.type = stoi(modName.substr(posstart, ndigits));  // 6th element+ module type
+
+  posstart += ndigits;
+  int modCopyNo = stoi(modName.substr(posstart, string::npos));
+  if ((modCopyNo / 100000000) < 0) {
+    LOG(warning) << modTxt << " Module in ancient (< 2013) format. Ask expert.";
+    return false;
+  }
+
+  // >= 2014 format has 9 digits
+  // In TGeoManager numbering starts with 1, so we have to subtract 1.
+  // int modCopy   = ((modCopyNo / 1000000) % 100);  // from module copy number
+  info.id       = (modCopyNo % 1000) - 1;
+  info.superId  = ((modCopyNo / 1000) % 100) - 1;
+  info.rotation = ((modCopyNo / 100000) % 10);  // from module copy number
+  info.address  = CbmTrdAddress::GetAddress(info.superId, info.id, 0, 0, 0);
+  return true;
+}
+
+//__________________________________________________________________
+bool cbm::trd::geo::ReadFebInfo(const char* febTxt, info_t& info)
+{
+  // parse FEB info
+  string febName = febTxt;
+  auto posstart  = febName.find("FEB") + 3;
+  try {
+    info.type      = stoi(febName.substr(posstart, 2));
+    info.superType = info.type / 10;
+    if (info.superType < 0 || info.superType > 2) throw eException::invalid_type;
+    info.type = info.type % 10;
+
+    int febNo = stoi(febName.substr(posstart + 3, string::npos));
+    info.id   = febNo % 100;
+    if (info.superType == 0 && info.id >= faspFeb[info.type].nmax) throw eException::invalid_id;
+    info.superId  = (febNo / 100) % 1000;
+    info.rotation = (febNo / 100000) % 10;
+    if (info.rotation > 1) throw eException::invalid_id;
+  }
+  catch (invalid_argument a) {  // syntax exceptions
+    LOG(error) << "FEB name does not follow syntax rules : \"FEBxy_identifier\", \"x\" = superType, \"y\" = Type. "
+                  "Couldn't initialize.";
+    return false;
+  }
+  catch (eException e) {  // TRD exceptions
+    LOG(error) << "FEB name does not follow syntax rules";
+    switch (e) {
+      case eException::invalid_type: LOG(info) << " : Family type not recognized"; break;
+      case eException::invalid_id: LOG(info) << " : Local id not recognized"; break;
+      default: LOG(info) << " : Un-identified violation."; break;
+    }
+    return false;
+  }
+
+  return true;
+}
+
+//__________________________________________________________________
+int cbm::trd::geo::WriteModuleInfo(info_t* /*info*/)
+{
+  /**  Encryption of module info into the node number
+ * format        : CCRLMMMM
+ * info.address  : not stored, derived from  CbmTrdAddress::GetAddress(ly, mod, 0, 0, 0)
+ * info.superId  : layer_id [L]  
+ * info.id       : mod_id / layer [M]
+ * info.type     : type according to family
+ * info.rotation : rotation in 90deg steps [R]
+ * copy number   : [C]
+ */
+  int modInfo = 0;  //info.id + info.superId * 100;
+  return modInfo;
+}
+
+//__________________________________________________________________
+int cbm::trd::geo::WriteFebInfo(info_t* info)
+{
+  /**  Encryption of FEB info into the node number
+ * format        : RPPPII
+ * info.address  : 
+ * info.superId  : identification of FEB in production DB [P]   
+ * info.id       : identification of FEB placement on the module  [I] 
+ * info.type     : Board version [T]
+ * info.rotation : rotation in 180deg steps [R]
+ * copy number   : not used
+ */
+  if (info == nullptr) {
+    LOG(error) << "WriteFebInfo : Info for FEB is missing";
+    return -1;
+  }
+  if (info->id < 0 || info->superId < 0 || info->rotation < 0) {
+    LOG(warning) << "WriteFebInfo : Info for FEB is incomplete : id=" << info->id << " superId=" << info->superId
+                 << " rotatation=" << info->rotation;
+    return -1;
+  }
+  int febInfo = info->id + 100 * info->superId + 100000 * info->rotation;
+  return febInfo;
+}
+
+//________________________________________________________________________________________
+ChamberBuilder::ChamberBuilder(int typ) : FairTask(Form("module%d", typ))
+{
+  fChmbTyp = typ;
+
+  fMaterial["air"]           = nullptr;
+  fMaterial["TRDpefoam20"]   = nullptr;
+  fMaterial["TRDG10"]        = nullptr;
+  fMaterial["TRDkapton"]     = nullptr;
+  fMaterial["TRDgas"]        = nullptr;
+  fMaterial["TRDcopper"]     = nullptr;
+  fMaterial["TRDaramide"]    = nullptr;
+  fMaterial["TRDcarbon"]     = nullptr;
+  fMaterial["aluminium"]     = nullptr;
+  fMaterial["polypropylene"] = nullptr;
+  fMaterial["silicon"]       = nullptr;
+
+  fComponent[(int) eGeoPart::kRadiator]  = nullptr;
+  fComponent[(int) eGeoPart::kWindow]    = new Window;
+  fComponent[(int) eGeoPart::kVolume]    = new Volume;
+  fComponent[(int) eGeoPart::kBackPanel] = new BackPanel;
+  fComponent[(int) eGeoPart::kFEB]       = nullptr;
+}
+
+//________________________________________________________________________________________
+InitStatus ChamberBuilder::Init()
+{
+  if (HasRadiator()) fComponent[(int) eGeoPart::kRadiator] = new Radiator;
+  if (HasFEB()) fComponent[(int) eGeoPart::kFEB] = new FEB;
+  switch (fChmbTyp) {
+    case 1:
+      LOG(info) << "Init for TRD2D.";
+      SetFEE(fConfig, (bool) eAsic::kFasp);
+      SetPP(fConfig, (bool) ePadPlane::k2d);
+      activeAreaX = activeAreaY = 54;
+      sizeX = sizeY = 57;
+      break;
+    case (int) eModuleTypes1D::kLowChDensitySmallR:
+    case (int) eModuleTypes1D::kHighChDensityLargeR:
+    case (int) eModuleTypes1D::kLowChDensityLargeR:
+      SetFEE(fConfig, (bool) eAsic::kSpadic);
+      SetPP(fConfig, (bool) ePadPlane::k1d);
+      LOG(info) << "Init for TRD1D type " << fChmbTyp << ".";
+      break;
+    default: LOG(fatal) << "Unknown TRD chamber type " << fChmbTyp << ". Abort."; break;
+  }
+
+  // Activate materials od the TRD geometry
+  TGeoManager* gGeoMan = (TGeoManager*) gROOT->FindObject("FAIRGeom");
+  assert(gGeoMan);
+  for (auto& imat : fMaterial) {
+    imat.second = gGeoMan->GetMedium(imat.first.data());
+    assert(imat.second);
+  }
+
+  // Instantiate the construction data base of the TRD system
+  // if (!gDB) {
+  //   assert((gDB = ConstructionDB::Instantiate()));
+  // }
+
+  // Init sub-components
+  for (auto icomp : fComponent) {
+    if (!icomp) continue;
+    auto status = icomp->Init();
+    if (status != kSUCCESS) return status;
+  }
+  return kSUCCESS;
+}
+
+//________________________________________________________________________________________
+void ChamberBuilder::Exec(Option_t*)
+{
+  // estimate total module height and define center
+  int idx(0);
+  double vh[(int) eGeoPart::kNparts];
+  bool kAdd(true);
+  double hOffset(0.), hTot(0.);
+  for (auto icomp : fComponent) {
+    if (!icomp) continue;
+    vh[idx] = icomp->GetHeight();
+    hTot += vh[idx];
+    if (kAdd) {
+      if (idx == (int) eGeoPart::kVolume) {
+        hOffset += vh[idx] / 2;
+        kAdd = false;
+      }
+      else
+        hOffset += vh[idx];
+    }
+    idx++;
+  }
+  // add global z offset
+  hOffset = hTot / 2;
+  fVol    = new TGeoVolume(Form("module%d", fChmbTyp), new TGeoBBox("", sizeX / 2, sizeY / 2, hTot / 2),
+                        cbm::trd::geo::GetMaterial("air"));
+  fVol->SetLineColor(kGreen);
+  fVol->SetTransparency(80);
+
+  // Stack-up all sub-components
+  idx = 0;
+  double hh(-hTot / 2);
+  info_t infoFeb;
+  for (auto icomp : fComponent) {
+    if (!icomp) continue;
+    hh += 0.5 * vh[idx];
+    switch (idx) {
+      case (int) eGeoPart::kFEB: {  // special case for feb multiple placement.
+        // FEB characteristics and identification stored in geometry
+        auto vFeb = new TGeoVolume(icomp->GetName(), new TGeoBBox("", sizeX / 2, sizeY / 2, vh[idx] / 2));
+        for (int ifeb(0), jfeb(0); ifeb < Nfebs; ifeb++) {
+          infoFeb.id       = ifeb;
+          infoFeb.superId  = 0;  // gDB.GetFebId(imod, ifeb);
+          infoFeb.rotation = 0;  // gDB.GetFebRot(imod, ifeb);
+          if ((jfeb = WriteFebInfo(&infoFeb)) < 0) continue;
+          vFeb->AddNode(icomp->fVol, jfeb, new TGeoTranslation("", feb_pos[ifeb][0], feb_pos[ifeb][1], 0.));
+        }
+        fVol->AddNode(vFeb, 1, new TGeoTranslation("", 0, 0, hh));
+      } break;
+      default: fVol->AddNode(icomp->fVol, 1, new TGeoTranslation("", 0., 0., hh)); break;
+    }
+
+    hh += 0.5 * vh[idx++];
+  }
+}
+//________________________________________________________________________________________
+double ChamberBuilder::Component::GetCenter() const
+{
+  if (!fVol) return 0.;
+  double zlo, zhi;
+  fVol->GetShape()->GetAxisRange(3., zlo, zhi);
+  return 0.5 * (zlo + zhi);
+}
+// double ChamberBuilder::Component::GetHeight() const
+// {
+//   if (!fVol) return 0.;
+//   double zlo, zhi, hh = fVol->GetShape()->GetAxisRange(2, zlo, zhi);
+//   return hh;
+// }
+
+//________________________________________________________________________________________
+ChamberBuilder::Window::Window() : Component("Window") { ; }
+
+InitStatus ChamberBuilder::Window::Init()
+{
+  const double hc_size_x  = activeAreaX;
+  const double hc_size_y  = 2 * 0.3 + activeAreaY;
+  const double win_size_x = hc_size_x + 2 * WIN_FrameX_thickness;
+  const double win_size_y = hc_size_y + 2 * WIN_FrameY_thickness;
+
+  // Carbon fiber layers
+  TGeoBBox* winIn_C = new TGeoBBox("winIn_C", win_size_x / 2., win_size_y / 2., winIn_C_thickness / 2.);
+  TGeoVolume* vol_winIn_C =
+    new TGeoVolume("winIn_C", winIn_C, cbm::trd::geo::GetMaterial("TRDcarbon") /*carbonVolMed*/);
+  vol_winIn_C->SetLineColor(kBlack);  //kGray);
+  fHeight = winIn_C_thickness;
+
+  // Honeycomb layer
+  TGeoBBox* winIn_HC       = new TGeoBBox("winIn_HC", hc_size_x / 2., hc_size_y / 2., winIn_HC_thickness / 2.);
+  TGeoVolume* vol_winIn_HC = new TGeoVolume("winIn_HC", winIn_HC, cbm::trd::geo::GetMaterial("TRDaramide"));
+  vol_winIn_HC->SetLineColor(kOrange);
+  fHeight += winIn_HC_thickness;
+
+  // framex
+  TGeoBBox* winIn_fx = new TGeoBBox("winIn_fx", (hc_size_x + 2 * WIN_FrameX_thickness) / 2, WIN_FrameY_thickness / 2,
+                                    winIn_HC_thickness / 2.);
+  TGeoVolume* vol_winIn_fx = new TGeoVolume("winIn_fx", winIn_fx, /*frameVolMed*/ cbm::trd::geo::GetMaterial("TRDG10"));
+  vol_winIn_fx->SetLineColor(kBlue);
+  TGeoBBox* winIn_xout = new TGeoBBox("winIn_xout", hc_size_x / 2 + 2 * WIN_FrameX_thickness, WIN_OutY_thickness / 2,
+                                      winIn_HC_thickness / 2.);
+  TGeoVolume* vol_winIn_xout =
+    new TGeoVolume("winIn_xout", winIn_xout, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_winIn_xout->SetLineColor(kBlue + 2);
+
+  // framey
+  TGeoBBox* winIn_fy       = new TGeoBBox("winIn_fy", WIN_FrameX_thickness / 2, hc_size_y / 2, winIn_HC_thickness / 2.);
+  TGeoVolume* vol_winIn_fy = new TGeoVolume("winIn_fy", winIn_fy, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_winIn_fy->SetLineColor(kCyan);
+  TGeoBBox* winIn_k =
+    new TGeoBBox("winIn_k", WIN_FrameX_thickness / 2, hc_size_y / 2 + WIN_FrameY_thickness, winIn_HC_thickness / 2.);
+  TGeoVolume* vol_winIn_k = new TGeoVolume("winIn_k", winIn_k, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_winIn_k->SetLineColor(kViolet);
+  TGeoBBox* winIn_yout =
+    new TGeoBBox("winIn_yout", WIN_OutX_thickness / 2, hc_size_y / 2 + WIN_FrameY_thickness + WIN_OutY_thickness,
+                 winIn_HC_thickness / 2.);
+  TGeoVolume* vol_winIn_yout =
+    new TGeoVolume("winIn_yout", winIn_yout, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_winIn_yout->SetLineColor(kViolet + 5);
+
+  // Add up all sub-components
+  fVol =
+    new TGeoVolume(GetName(), new TGeoBBox("", sizeX / 2, sizeY / 2, fHeight / 2), cbm::trd::geo::GetMaterial("air"));
+  fVol->SetLineColor(kOrange);
+  fVol->SetTransparency(50);
+
+  double x, y;
+  fHeight = -fHeight / 2 + winIn_HC_thickness / 2;
+  fVol->AddNode(vol_winIn_HC, 1, new TGeoTranslation("", 0., 0., fHeight));
+  y = (hc_size_y + WIN_FrameY_thickness) / 2.;
+  fVol->AddNode(vol_winIn_fx, 1, new TGeoTranslation("", 0., y, fHeight));
+  fVol->AddNode(vol_winIn_fx, 2, new TGeoTranslation("", 0., -y, fHeight));
+  y += 0.5 * (WIN_FrameY_thickness + WIN_OutY_thickness);
+  fVol->AddNode(vol_winIn_xout, 1, new TGeoTranslation("", 0., y, fHeight));
+  fVol->AddNode(vol_winIn_xout, 2, new TGeoTranslation("", 0., -y, fHeight));
+  x = (hc_size_x + WIN_FrameX_thickness) / 2.;
+  fVol->AddNode(vol_winIn_fy, 1, new TGeoTranslation("", x, 0., fHeight));
+  fVol->AddNode(vol_winIn_fy, 2, new TGeoTranslation("", -x, 0., fHeight));
+  x += WIN_FrameX_thickness;
+  fVol->AddNode(vol_winIn_k, 1, new TGeoTranslation("", x, 0., fHeight));
+  fVol->AddNode(vol_winIn_k, 2, new TGeoTranslation("", -x, 0., fHeight));
+  x += 0.5 * (WIN_FrameX_thickness + WIN_OutX_thickness);
+  fVol->AddNode(vol_winIn_yout, 1, new TGeoTranslation("", x, 0., fHeight));
+  fVol->AddNode(vol_winIn_yout, 2, new TGeoTranslation("", -x, 0., fHeight));
+
+  fHeight += 0.5 * (winIn_HC_thickness + winIn_C_thickness);
+  fVol->AddNode(vol_winIn_C, 1, new TGeoTranslation("", 0., 0., fHeight));
+  fHeight += 0.5 * winIn_C_thickness;
+  fHeight *= 2;
+  return kSUCCESS;
+}
+
+//________________________________________________________________________________________
+ChamberBuilder::Volume::Volume() : Component("Volume") { ; }
+
+InitStatus ChamberBuilder::Volume::Init()
+{
+  // Gas. The volume has to be defined only for pads (read-out) area. Take care in the DigiPara definition
+  TGeoBBox* gas       = new TGeoBBox("trd_gas", 0.5 * activeAreaX, 0.5 * activeAreaY, 0.5 * gas_thickness);
+  TGeoVolume* vol_gas = new TGeoVolume("gas", gas, cbm::trd::geo::GetMaterial("TRDgas") /*gasVolMed*/);
+  vol_gas->SetLineColor(kRed);
+  //vol_gas->SetTransparency(80);
+  TGeoBBox* gas_ext       = new TGeoBBox("trd_gas_dstr", 0.5 * activeAreaX, 0.5 * gas_extra, 0.5 * gas_thickness);
+  TGeoVolume* vol_gas_ext = new TGeoVolume("gas_ext", gas_ext, cbm::trd::geo::GetMaterial("TRDgas") /*gasVolMed*/);
+  vol_gas_ext->SetLineColor(kMagenta);
+  //vol_gas_ext->SetTransparency(80);
+  fHeight = gas_thickness;
+
+  const double gas_size_x = activeAreaX;
+  const double gas_size_y = activeAreaY + 2 * gas_extra;
+
+  // framex
+  auto* gas_xin = new TGeoBBox("gas_xin", gas_size_x / 2 + cathode_width, WIN_OutY_thickness / 2, gas_thickness / 2.);
+  auto* vol_gas_xin = new TGeoVolume("gas_xin", gas_xin, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_gas_xin->SetLineColor(kViolet + 5);
+  auto* gas_xout           = new TGeoBBox("gas_xout", gas_size_x / 2 + cathode_width, WIN_OutY_thickness / 2,
+                                (gas_thickness /*+ ridge_height*/) / 2.);
+  TGeoVolume* vol_gas_xout = new TGeoVolume("gas_xout", gas_xout, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_gas_xout->SetLineColor(kViolet + 5);
+  // framey
+  TGeoBBox* gas_k       = new TGeoBBox("gas_k", cathode_width / 2, gas_size_y / 2, ledge_thickness / 2.);
+  TGeoVolume* vol_gas_k = new TGeoVolume("gas_k", gas_k, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_gas_k->SetLineColor(kViolet);
+  TGeoBBox* gas_a       = new TGeoBBox("gas_a", anode_width / 2, gas_size_y / 2, ledge_thickness / 2.);
+  TGeoVolume* vol_gas_a = new TGeoVolume("gas_a", gas_a, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_gas_a->SetLineColor(kViolet + 2);
+  TGeoBBox* gas_d       = new TGeoBBox("gas_d", dist_width / 2, gas_size_y / 2, ledge_thickness / 2.);
+  TGeoVolume* vol_gas_d = new TGeoVolume("gas_d", gas_d, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_gas_d->SetLineColor(kViolet + 4);
+  TGeoBBox* gas_yout       = new TGeoBBox("gas_yout", WIN_OutX_thickness / 2, 2 * WIN_OutY_thickness + gas_size_y / 2,
+                                    (gas_thickness /*+ ridge_height*/) / 2.);
+  TGeoVolume* vol_gas_yout = new TGeoVolume("gas_yout", gas_yout, cbm::trd::geo::GetMaterial("TRDG10") /*frameVolMed*/);
+  vol_gas_yout->SetLineColor(kViolet + 5);
+
+  // Add up all sub-components
+  fVol =
+    new TGeoVolume(GetName(), new TGeoBBox("", sizeX / 2, sizeY / 2, fHeight / 2), cbm::trd::geo::GetMaterial("air"));
+  fVol->SetLineColor(kYellow);
+  fVol->SetTransparency(50);
+
+  double x, y;
+  fHeight = 0.;
+  fVol->AddNode(vol_gas, 0, new TGeoTranslation("", 0., 0., fHeight));
+  x = 0.5 * (gas_size_x + cathode_width);
+  fVol->AddNode(vol_gas_k, 1, new TGeoTranslation("", x, 0., fHeight - ledge_thickness));
+  fVol->AddNode(vol_gas_k, 2, new TGeoTranslation("", -x, 0., fHeight - ledge_thickness));
+  x = 0.5 * (gas_size_x + anode_width);
+  fVol->AddNode(vol_gas_a, 1, new TGeoTranslation("", x, 0., fHeight));
+  fVol->AddNode(vol_gas_a, 2, new TGeoTranslation("", -x, 0., fHeight));
+  x = 0.5 * (gas_size_x + dist_width);
+  fVol->AddNode(vol_gas_d, 1, new TGeoTranslation("", x, 0., fHeight + ledge_thickness));
+  fVol->AddNode(vol_gas_d, 2, new TGeoTranslation("", -x, 0., fHeight + ledge_thickness));
+  x = 0.5 * gas_size_x + cathode_width + 0.5 * WIN_OutX_thickness;
+  fVol->AddNode(vol_gas_yout, 1, new TGeoTranslation("", x, 0., fHeight /* + ridge_height / 2*/));
+  fVol->AddNode(vol_gas_yout, 2, new TGeoTranslation("", -x, 0., fHeight /* + ridge_height / 2*/));
+  y = 0.5 * (activeAreaY + gas_extra);
+  fVol->AddNode(vol_gas_ext, 0, new TGeoTranslation("", 0., y, fHeight));
+  fVol->AddNode(vol_gas_ext, 1, new TGeoTranslation("", 0., -y, fHeight));
+  y += 0.5 * (gas_extra + WIN_OutY_thickness);
+  fVol->AddNode(vol_gas_xin, 1, new TGeoTranslation("", 0, y, fHeight));
+  fVol->AddNode(vol_gas_xin, 2, new TGeoTranslation("", 0, -y, fHeight));
+  y += WIN_OutY_thickness;
+  fVol->AddNode(vol_gas_xout, 1, new TGeoTranslation("", 0, y, fHeight /* + ridge_height / 2*/));
+  fVol->AddNode(vol_gas_xout, 2, new TGeoTranslation("", 0, -y, fHeight /* + ridge_height / 2*/));
+  fHeight += gas_thickness;
+  return kSUCCESS;
+}
+
+//________________________________________________________________________________________
+ChamberBuilder::BackPanel::BackPanel() : Component("BackPanel") { ; }
+InitStatus ChamberBuilder::BackPanel::Init()
+{
+  const double hc_size_x  = activeAreaX;
+  const double hc_size_y  = activeAreaY - 2 * BKP_OutY_correct;
+  const double bkp_size_x = hc_size_x + 2 * BKP_Frame_width;
+  const double bkp_size_y = hc_size_y + 2 * BKP_Frame_width;
+
+  // Pad Copper
+  TGeoBBox* pp       = new TGeoBBox("pp_cu", activeAreaX / 2., activeAreaY / 2., pp_pads_thickness / 2.);
+  TGeoVolume* vol_pp = new TGeoVolume("pp_cu", pp, /*padcopperVolMed*/ cbm::trd::geo::GetMaterial("TRDcopper"));
+  vol_pp->SetLineColor(kBlue);
+  fHeight = pp_pads_thickness;
+
+  // Pad Plane
+  TGeoBBox* pp_PCB       = new TGeoBBox("pp_pcb", bkp_size_x / 2., bkp_size_y / 2., pp_pcb_thickness / 2.);
+  TGeoVolume* vol_pp_PCB = new TGeoVolume("pp_pcb2d", pp_PCB, /*padpcbVolMed*/ cbm::trd::geo::GetMaterial("TRDG10"));
+  vol_pp_PCB->SetLineColor(kGreen);
+  fHeight += pp_pcb_thickness;
+
+  // Perforated BackPanel structure
+  auto vol_bp      = new TGeoVolumeAssembly("bkp_int");
+  auto vol_bp_ASIC = new TGeoVolumeAssembly("");
+  // HC : 3 components (HC, PCB, Cu) with 2 sizes
+  Color_t bp_col[3]      = {kOrange, kGray, kRed + 2};
+  const char* matName[3] = {"TRDaramide", "TRDG10", "TRDcopper"};
+  // build one BP unit
+  double dxHC[2] = {hc_unitx / 2., (hc_unitx - hc_holex) / 4.}, dyHC[2] = {(hc_unity - hc_holey) / 4., hc_holey / 2.},
+         hHCx((hc_unitx + hc_holex) / 4.), hHCy((hc_unity + hc_holey) / 4.), hHC(0.),
+         hHCz[] = {hc_thickness, cu_pcb_thickness, cu_thickness};
+  for (int ibpz(0); ibpz < 3; ibpz++) {
+    hHC += 0.5 * hHCz[ibpz];
+    for (int ibpy(-1), jbp(0); ibpy < 2; ibpy += 2) {
+      auto bpShp   = new TGeoBBox("", dxHC[0], dyHC[0], hHCz[ibpz] / 2.);
+      auto vol_cmp = new TGeoVolume("", bpShp, cbm::trd::geo::GetMaterial(matName[ibpz]));
+      vol_cmp->SetLineColor(bp_col[ibpz]);
+      vol_bp_ASIC->AddNode(vol_cmp, jbp++, new TGeoTranslation("", 0., ibpy * hHCy, hHC));
+    }
+    for (int ibpx(-1), jbp(0); ibpx < 2; ibpx += 2) {
+      auto bpShp   = new TGeoBBox("", dxHC[1], dyHC[1], hHCz[ibpz] / 2.);
+      auto vol_cmp = new TGeoVolume("", bpShp, cbm::trd::geo::GetMaterial(matName[ibpz]));
+      vol_cmp->SetLineColor(bp_col[ibpz]);
+      vol_bp_ASIC->AddNode(vol_cmp, jbp++, new TGeoTranslation("", ibpx * hHCx, 0., hHC));
+    }
+    hHC += 0.5 * hHCz[ibpz];
+  }
+  // build BP plate
+  for (Int_t c(0), ifc(0); c < 9; c++) {
+    for (Int_t r(0); r < 10; r++) {
+      vol_bp->AddNode(vol_bp_ASIC, ifc++, new TGeoTranslation("", (c - 4) * hc_unitx, hc_unity * (0.5 + r), 0.));
+      vol_bp->AddNode(vol_bp_ASIC, ifc++, new TGeoTranslation("", (c - 4) * hc_unitx, -hc_unity * (r + 0.5), 0.));
+    }
+  }
+  fHeight += hHC;
+
+  // framex
+  auto xoutBd =
+    new TGeoBBox("", hc_size_x / 2, (BKP_OutY_thickness - BKP_OutY_correct) / 2, (hHC - BKP_Frame_closure) / 2.);
+  auto xvolBd       = new TGeoVolume("", xoutBd, cbm::trd::geo::GetMaterial("TRDG10"));
+  auto xoutFc       = new TGeoBBox("", hc_size_x / 2, (BKP_Frame_width - BKP_OutY_correct) / 2, BKP_Frame_closure / 2.);
+  auto xvolFc       = new TGeoVolume("", xoutFc, cbm::trd::geo::GetMaterial("TRDG10"));
+  auto vol_bkp_xout = new TGeoVolumeAssembly("bkp_xout");
+  vol_bkp_xout->AddNode(
+    xvolFc, 1, new TGeoTranslation("", 0, (BKP_Frame_width - BKP_OutY_thickness) / 2, (BKP_Frame_closure - hHC) / 2));
+  vol_bkp_xout->AddNode(xvolBd, 1, new TGeoTranslation("", 0., 0., BKP_Frame_closure / 2));
+  vol_bkp_xout->SetLineColor(kViolet + 2);
+
+  // framey
+  auto youtBd =
+    new TGeoBBox("", BKP_OutX_thickness / 2, hc_size_y / 2 + BKP_OutY_thickness, (hHC - BKP_Frame_closure) / 2.);
+  auto yvolBd       = new TGeoVolume("", youtBd, cbm::trd::geo::GetMaterial("TRDG10"));
+  auto youtFc       = new TGeoBBox("", BKP_Frame_width / 2, hc_size_y / 2 + BKP_Frame_width, BKP_Frame_closure / 2.);
+  auto yvolFc       = new TGeoVolume("", youtFc, cbm::trd::geo::GetMaterial("TRDG10"));
+  auto vol_bkp_yout = new TGeoVolumeAssembly("bkp_yout");
+  vol_bkp_yout->AddNode(yvolFc, 1,
+                        new TGeoTranslation("t_bkp_yout_fc", (BKP_Frame_width - BKP_OutX_thickness) / 2, 0.,
+                                            (BKP_Frame_closure - hHC) / 2));
+  vol_bkp_yout->AddNode(yvolBd, 1, new TGeoTranslation("t_bkp_yout_bd", 0., 0., BKP_Frame_closure / 2));
+  vol_bkp_yout->SetLineColor(kViolet + 2);
+
+  // Add up all components
+  fVol = new TGeoVolume(GetName(), new TGeoBBox("", bkp_size_x / 2, bkp_size_y / 2, fHeight / 2),
+                        cbm::trd::geo::GetMaterial("air"));
+  fVol->SetLineColor(kOrange);
+  fVol->SetTransparency(50);
+
+  double x, y;
+  fHeight = -fHeight / 2 + 0.5 * pp_pads_thickness;
+  fVol->AddNode(vol_pp, 1, new TGeoTranslation("", 0., 0., fHeight));
+  fHeight += 0.5 * (pp_pads_thickness + pp_pcb_thickness);
+  fVol->AddNode(vol_pp_PCB, 1, new TGeoTranslation("", 0., 0., fHeight));
+  fHeight += 0.5 * pp_pcb_thickness;
+  fVol->AddNode(vol_bp, 1, new TGeoTranslation("", 0., 0., fHeight));
+  fHeight += 0.5 * hHC;
+
+  x            = 0.5 * (hc_size_x + BKP_OutX_thickness);
+  auto* fy_tra = new TGeoTranslation("", x, 0., fHeight);
+  fVol->AddNode(vol_bkp_yout, 1, fy_tra);
+  auto* fy_rot = new TGeoRotation();
+  fy_rot->RotateZ(180.);
+  auto* fy_mat = new TGeoHMatrix("");
+  (*fy_mat)    = (*fy_rot) * (*fy_tra);
+  fVol->AddNode(vol_bkp_yout, 2, fy_mat);
+  y      = 0.5 * (hc_size_y + BKP_OutY_thickness + BKP_OutY_correct);
+  fy_tra = new TGeoTranslation("", 0., y, fHeight);
+  fVol->AddNode(vol_bkp_xout, 1, fy_tra);
+  fy_mat    = new TGeoHMatrix("");
+  (*fy_mat) = (*fy_rot) * (*fy_tra);
+  fVol->AddNode(vol_bkp_xout, 2, fy_mat);
+  fHeight += 0.5 * hHC;
+  fHeight *= 2;
+  return kSUCCESS;
+}
+
+//________________________________________________________________________________________
+ChamberBuilder::FEB::FEB() : Component("FEB") { ; }
+
+InitStatus ChamberBuilder::FEB::Init()
+{
+  // Create the FASPRO FEBs out of all CU/PCB layers
+  fHeight = FASPRO_zspace;
+
+  TString scu = "", spcb = "";
+  TGeoTranslation* tr(nullptr);
+  double FASPRO_thickness(0.);
+  for (int ily(0); ily < FASPRO_Nly; ily++) {
+    // effective Cu layer thickness  = h [um * 10-4] * coverage [% * 10-2]
+    double lyThickEff = FASPRO_ly_cu[ily][0] * FASPRO_ly_cu[ily][1] * 1.e-6;
+    new TGeoBBox(Form("faspro_ly%02d", ily), FASPRO_length / 2., FASPRO_width / 2., lyThickEff / 2.);
+    FASPRO_thickness += lyThickEff / 2;
+    tr = new TGeoTranslation(Form("t_faspro_ly%02d", ily), 0., 0., FASPRO_thickness);
+    tr->RegisterYourself();
+    scu += Form("%cfaspro_ly%02d:t_faspro_ly%02d", (ily ? '+' : ' '), ily, ily);
+    FASPRO_thickness += lyThickEff / 2;
+    if (ily == FASPRO_Nly - 1) break;  // skip for FR4
+    // the FEB dielectric made of PCB
+    double lyThickPcb = 1.e-4 * FASPRO_ly_pcb[ily] / 2.;
+    new TGeoBBox(Form("faspro_ly%02d_pcb", ily), FASPRO_length / 2., FASPRO_width / 2., lyThickPcb);
+    FASPRO_thickness += lyThickPcb;
+    tr = new TGeoTranslation(Form("t_faspro_ly%02d_pcb", ily), 0., 0., FASPRO_thickness);
+    tr->RegisterYourself();
+    spcb += Form("%cfaspro_ly%02d_pcb:t_faspro_ly%02d_pcb", (ily ? '+' : ' '), ily, ily);
+    FASPRO_thickness += lyThickPcb;
+  }
+  for (int ihole(0); ihole < FASPRO_Nfasp; ihole++) {
+    new TGeoBBox(Form("faspro_hole%d", ihole), FASPRO_hole_x / 2., FASPRO_hole_y / 2., 1.e-4 + FASPRO_thickness / 2.);
+    tr =
+      new TGeoTranslation(Form("t_faspro_hole%d", ihole), HOLE_pos[ihole][0], HOLE_pos[ihole][1], FASPRO_thickness / 2);
+    tr->RegisterYourself();
+    scu += Form("-faspro_hole%d:t_faspro_hole%d", ihole, ihole);
+    spcb += Form("-faspro_hole%d:t_faspro_hole%d", ihole, ihole);
+  }
+  auto faspro_cu     = new TGeoCompositeShape("faspro_cu", scu.Data());
+  auto vol_faspro_cu = new TGeoVolume("faspro_cu", faspro_cu, cbm::trd::geo::GetMaterial("TRDcopper"));
+  vol_faspro_cu->SetLineColor(kRed - 3);  //vol_faspro_cu->SetTransparency(50);
+  auto faspro_pcb     = new TGeoCompositeShape("faspro_pcb", spcb.Data());
+  auto vol_faspro_pcb = new TGeoVolume("faspro_pcb", faspro_pcb,
+                                       cbm::trd::geo::GetMaterial("TRDG10") /*febVolMed*/);  // the FEB made of PCB
+  vol_faspro_pcb->SetLineColor(kGreen + 3);
+  //vol_faspro_pcb->SetTransparency(50);
+  fHeight += FASPRO_thickness;
+
+  // create FASP ASIC
+  auto fasp     = new TGeoBBox("fasp", FASP_x / 2., FASP_y / 2., FASP_z / 2.);
+  auto vol_fasp = new TGeoVolume("fasp", fasp, cbm::trd::geo::GetMaterial("silicon"));
+  vol_fasp->SetLineColor(kBlack);
+  // create ADC ASIC
+  auto adc     = new TGeoBBox("adc", ADC_x / 2., ADC_y / 2., ADC_z / 2.);
+  auto vol_adc = new TGeoVolume("adc", adc, cbm::trd::geo::GetMaterial("silicon"));
+  vol_adc->SetLineColor(kBlack);
+  // create FPGA ASIC
+  auto fpga     = new TGeoBBox("fpga", FPGA_x / 2., FPGA_y / 2., FPGA_z / 2.);
+  auto vol_fpga = new TGeoVolume("fpga", fpga, cbm::trd::geo::GetMaterial("silicon"));
+  vol_fpga->SetLineColor(kBlack);
+  // create DCDC ASIC
+  auto dcdc     = new TGeoBBox("dcdc", DCDC_x / 2., DCDC_y / 2., DCDC_z / 2.);
+  auto vol_dcdc = new TGeoVolume("dcdc", dcdc, cbm::trd::geo::GetMaterial("silicon"));
+  vol_dcdc->SetLineColor(kBlack);
+  // create FC Coonector
+  auto connFc      = new TGeoBBox("connFc", ConnFC_x / 2., ConnFC_y / 2., ConnFC_z / 2.);
+  auto vol_conn_fc = new TGeoVolume("connFc", connFc, cbm::trd::geo::GetMaterial("polypropylene"));
+  vol_conn_fc->SetLineColor(kYellow);
+  // create BRIDGE Coonector
+  auto connBrg      = new TGeoBBox("connBrg", ConnBRG_x / 2., ConnBRG_y / 2., ConnBRG_z / 2.);
+  auto vol_conn_brg = new TGeoVolume("connBrg", connBrg, cbm::trd::geo::GetMaterial("polypropylene"));
+  vol_conn_brg->SetLineColor(kYellow + 2);
+  fHeight += ConnBRG_z;
+
+  // Init volume:
+  // FEB family FASPRO
+  // FEB type v1 (12 FASPs)
+  int fType = 1;
+  fVol      = new TGeoVolumeAssembly(Form("%s1%d", GetName(), fType));
+  fVol->SetLineColor(kGreen);
+  fVol->SetTransparency(50);
+
+  // Add up all components
+  fHeight = -0.5 * fHeight + FASPRO_zspace;
+  fVol->AddNode(vol_faspro_cu, 1, new TGeoTranslation("", 0., 0., fHeight));
+  fVol->AddNode(vol_faspro_pcb, 1, new TGeoTranslation("", 0., 0., fHeight));
+  // add FASPs on the back side of the FEB
+  info_t infoAsic;
+  for (int ifasp(0), jfasp(0); ifasp < faspFeb[fType].nasic; ifasp++) {
+    vol_fasp->SetTitle(Form("%x", 0xff /*gDB->GetASICMask*/));
+    // if ((jfasp = WriteAsicInfo(&infoAsic)) < 0) continue;
+    fVol->AddNode(vol_fasp, jfasp,
+                  new TGeoTranslation("", FASP_pos[ifasp][0], FASP_pos[ifasp][1], fHeight - FASP_z / 2));
+  }
+  fHeight += FASPRO_thickness;
+  // add ADCs, FPGAs and DCDC converters on the tob side of the FEB
+  for (int iadc(0); iadc < FASPRO_Nadc; iadc++)
+    fVol->AddNode(vol_adc, iadc + 1, new TGeoTranslation("", ADC_pos[iadc][0], ADC_pos[iadc][1], fHeight + ADC_z / 2));
+  for (int ifpga(0); ifpga < FASPRO_Nfpga; ifpga++)
+    fVol->AddNode(vol_fpga, ifpga + 1,
+                  new TGeoTranslation("", FPGA_pos[ifpga][0], FPGA_pos[ifpga][1], fHeight + FPGA_z / 2));
+  for (int idcdc(0); idcdc < FASPRO_Ndcdc; idcdc++)
+    fVol->AddNode(vol_dcdc, idcdc + 1,
+                  new TGeoTranslation("", DCDC_pos[idcdc][0], DCDC_pos[idcdc][1], fHeight + DCDC_z / 2));
+  // add connectors to the FEB
+  for (int ifasp(0); ifasp < FASPRO_Nfasp; ifasp++)
+    fVol->AddNode(vol_conn_fc, ifasp + 1,
+                  new TGeoTranslation("", ConnFC_pos[ifasp][0], ConnFC_pos[ifasp][1], fHeight + ConnFC_z / 2));
+  for (int iconn(0); iconn < 2; iconn++)
+    fVol->AddNode(vol_conn_brg, iconn + 1,
+                  new TGeoTranslation("", ConnBRG_pos[iconn][0], ConnBRG_pos[iconn][1], fHeight + ConnBRG_z / 2));
+  fHeight += ConnBRG_z;
+  fHeight *= 2;
+  return kSUCCESS;
+}
+
+//________________________________________________________________________________________
+ChamberBuilder::Radiator::Radiator() : Component("Radiator") { ; }
+
+InitStatus ChamberBuilder::Radiator::Init()
+{
+  TGeoBBox* trd_radiator = new TGeoBBox("trd_radiator", sizeX / 2., sizeY / 2., radiator_thickness / 2.);
+  fVol = new TGeoVolume("Radiator", trd_radiator, cbm::trd::geo::GetMaterial("TRDpefoam20") /*radVolMed*/);
+  fVol->SetLineColor(kRed);
+  //trdmod1_radvol->SetTransparency(50);  // set transparency for the TRD radiator
+
+  fHeight = radiator_thickness;
+  return kSUCCESS;
+}
+/* clang-format off */
+// NamespaceImp(cbm::trd::geo)
+ClassImp(cbm::trd::geo::ChamberBuilder)
+ClassImp(cbm::trd::geo::ChamberBuilder::Component)
+ClassImp(cbm::trd::geo::ChamberBuilder::Radiator)
+ClassImp(cbm::trd::geo::ChamberBuilder::Window)
+ClassImp(cbm::trd::geo::ChamberBuilder::Volume)
+ClassImp(cbm::trd::geo::ChamberBuilder::BackPanel)
+ClassImp(cbm::trd::geo::ChamberBuilder::FEB)
+  /* clang-format on */
diff --git a/core/detectors/trd/CbmTrdGeoFactory.h b/core/detectors/trd/CbmTrdGeoFactory.h
new file mode 100644
index 0000000000..8daa2d0474
--- /dev/null
+++ b/core/detectors/trd/CbmTrdGeoFactory.h
@@ -0,0 +1,352 @@
+/* Copyright (C) 2024 National Institute of Physics and Nuclear Engineering - Horia Hulubei, Bucharest
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Alexandru Bercuci [committer] */
+
+/**
+ * \file CbmTrdGeoFactory.h
+ * \brief Builder class for the TRD chamber geometry.
+ * \author Alexandru Bercuci <abercuci@niham.nipne.ro>
+ * \date 01/10/2023
+ *
+ * This class manages the relative spatial positioning of the following components of the TRD chamber :
+ * - Chamber : initialize and place all components of the TRD chamber
+ *    - Radiator :
+ *    - Window :
+ *    - Volume : 
+ *    - BackPanel
+ *    - FEE
+ */
+
+#ifndef CBMTRDGEOFACTORY_H_
+#define CBMTRDGEOFACTORY_H_
+
+#include "CbmTrdDefs.h"  // for trd namespace
+
+#include <FairTask.h>
+
+#include <TString.h>
+
+#include <array>
+#include <string>
+
+class TGeoMedium;
+class TGeoTranslation;
+class TGeoVolume;
+class TGeoVolumeAssembly;
+using namespace std;
+using namespace cbm::trd;
+namespace cbm::trd::geo
+{
+  enum class eException
+  {
+    invalid_type = 0,  //!
+    invalid_id         //!
+  };
+
+  /** \struct info_t
+   * \brief Information to be storred in the geoManager path.
+   * Based on legacy class CbmTrdGeoHandler.
+   */
+  struct info_t {
+    int address   = -1;  //! global addressing of element
+    int id        = -1;  //! local (wrt installation) id of element
+    int superId   = -1;  //! global (wrt setup) id of element
+    int type      = -1;  //! version of element wrt superType family
+    int superType = -1;  //! global type wrt TRD design
+    int rotation  = -1;  //! rotation angle 0,1,2,3
+  };
+  /** \function ReadModuleInfo
+   * \brief Identify information related to the module encrypted in the geoManager path.
+   * Based on legacy function "void CbmTrdGeoHandler::NavigateTo(const TString& path)"
+   * \param[in] modTxt : module name in gGeoManager
+   * \param[in] info : object to be filled with decrypted info
+   */
+  bool ReadModuleInfo(const char* modTxt, info_t& info);
+
+  /** \function ReadFebInfo
+   * \brief Identify information related to one FEB encrypted in the geoManager path.
+   * \param[in] febTxt : FEB name in gGeoManager
+   * \param[in] info : object to be filled with decrypted info
+   */
+  bool ReadFebInfo(const char* febTxt, info_t& info);
+
+  /** \function WriteModuleInfo
+   * \brief Put up information related to the module and store it in the geoManager path.
+   * Based on legacy version "void Create_TRD_Geometry.C macro"
+   */
+  int WriteModuleInfo(info_t* info);
+
+  /** \function WriteFebInfo
+   * \brief Put up information related to the FEB and store it in the geoManager path.
+   */
+  int WriteFebInfo(info_t* info);
+
+
+  // chamber generic geometrical definitions
+  static double sizeX, sizeY;                                  //! total area
+  static double activeAreaX, activeAreaY;                      //! active area
+  static map<const string, const TGeoMedium*> fMaterial = {};  //! material mapping (name, value)
+  const TGeoMedium* GetMaterial(const char* mname);
+
+
+  /** \brief Generic Chamber builder 
+  **/
+  class ChamberBuilder : public FairTask {
+   public:
+    enum class eGeoPart : int
+    {
+      kRadiator = 0,
+      kWindow,
+      kVolume,
+      kBackPanel,
+      kFEB,
+      kNparts
+    };
+    enum eConfig
+    {
+      kRadiator = 8  //! include radiator in chamber geometry
+        ,
+      kFEB  //! include FEB in chamber geometry
+    };
+    class Component;
+    class Radiator;
+    class Window;
+    class Volume;
+    class BackPanel;
+    class FEB;
+    /** \brief Constructor for the chamber. Adds all elements according to config.       
+     * \param[in] typ TRD chamber type [1, 3, 5, 7].
+    **/
+    ChamberBuilder(int typ = 1);
+
+    TGeoVolume* GetModule() const { return fVol; }
+    bool HasFEB() const { return TESTBIT(fConfig, eConfig::kFEB); }
+    bool HasRadiator() const { return TESTBIT(fConfig, eConfig::kRadiator); }
+    /** \brief Init task **/
+    virtual InitStatus Init();
+    /** \brief Executed task **/
+    virtual void Exec(Option_t*);
+    /** \brief Finish task **/
+    virtual void Finish() { ; }
+
+    void SetFEB(bool feb = true) { feb ? SETBIT(fConfig, eConfig::kFEB) : CLRBIT(fConfig, eConfig::kFEB); }
+    void SetRadiator(bool rad = true)
+    {
+      rad ? SETBIT(fConfig, eConfig::kRadiator) : CLRBIT(fConfig, eConfig::kRadiator);
+    }
+
+   private:
+    ChamberBuilder(const ChamberBuilder&);
+    ChamberBuilder operator=(const ChamberBuilder&);
+
+    short fConfig                                         = 0;   //! bit map of the setter flags
+    short fChmbTyp                                        = 1;   //! chamber type [1, 3, 5, 7]
+    array<Component*, (int) eGeoPart::kNparts> fComponent = {};  //! list of chamber component  builders
+    static const int Nfebs                                = faspFeb[1].nmax;
+    const double feb_pos[Nfebs][2] = {{-18, -21.6}, {0, -21.6},  {18, -21.6},  {-18, -10.8}, {0, -10.8},
+                                      {18, -10.8},  {-18, 0.0},  {0, 0.0},     {18, 0.0},    {-18, +10.8},
+                                      {0, +10.8},   {18, +10.8}, {-18, +21.6}, {0, +21.6},   {18, +21.6}};
+    TGeoVolume* fVol               = nullptr;  //! the geo volume itself
+    ClassDef(ChamberBuilder, 1)                // Manager of the TRD support structure
+  };
+
+
+  /** \brief Generic sub-component 
+  **/
+  class ChamberBuilder::Component : public FairTask {
+   public:
+    friend class ChamberBuilder;
+    /** \brief Constructor of the TRD chamber component.
+      * It links the chamber class
+    **/
+    Component(const char* name) : FairTask(name)
+    {
+      sizeX       = 0;
+      sizeY       = 0;
+      activeAreaX = 0;
+      activeAreaY = 0;
+    }
+    /** Construct the chamber component volume in the reference of the chamber
+      * The function has to be implemented for each particular component of the TRD chamber
+      * \return The dimension of the component on the z axis  
+      */
+    /** \brief Init task **/
+    virtual InitStatus Init() = 0;
+    /** \brief Executed task **/
+    virtual void Exec(Option_t*) { ; }
+    /** \brief Finish task **/
+    virtual void Finish() { ; }
+    virtual double GetCenter() const;
+    virtual double GetHeight() const { return fHeight; }
+
+    static const char* fgName[(int) eGeoPart::kNparts];
+
+   protected:
+    TGeoVolume* fVol = nullptr;  //! the geo volume itself
+
+   private:
+    Component(const Component&);
+    //Component operator=(const Component&);
+
+    double fHeight = 0;                     //! height of the component (local calculation)
+    ClassDef(ChamberBuilder::Component, 1)  // Model for the TRD generic chamber component builder
+  };
+
+  class ChamberBuilder::Radiator : public ChamberBuilder::Component {
+   public:
+    Radiator();
+    /** \brief Init task **/
+    virtual InitStatus Init();
+
+   private:
+    Radiator(const Radiator&);
+    const double radiator_thickness = 30.0;
+    ClassDef(ChamberBuilder::Radiator, 1)  // Model for the TRD radiator
+  };
+
+  class ChamberBuilder::Window : public ChamberBuilder::Component {
+   public:
+    /** \brief Constructor of entrance window for the TRD chamber
+    **/
+    Window();
+    /** \brief Init task **/
+    virtual InitStatus Init();
+
+   private:
+    Window(const Window&);
+
+    const double winIn_C_thickness    = 0.012;  //! 100um C foil + 25um KaptonAl
+    const double winIn_HC_thickness   = 0.9;    //! 9mm HC structure
+    const double WIN_FrameX_thickness = 0.5;    //! entrance window framing 5x9 mm2
+    const double WIN_FrameY_thickness = 0.6;    //! entrance window framing 5x9 mm2
+    const double WIN_OutX_thickness   = 0.35;   //! outside framing at win 3.5x9 mm2
+    const double WIN_OutY_thickness   = 0.30;   //! outside framing at win 3.5x9 mm2
+    ClassDef(ChamberBuilder::Window, 1)         // Model for the TRD2D entrance window
+  };
+
+  /** \brief Inner class describing a :
+  **/
+  class ChamberBuilder::Volume : public ChamberBuilder::Component {
+   public:
+    /** \brief Constructor.
+    **/
+    Volume();
+    /** \brief Init task **/
+    virtual InitStatus Init();
+
+   private:
+    Volume(const Volume&);
+
+    const double gas_extra          = 0.6;                 //! extra volume of gas parallel to wires
+    const double gas_thickness      = 1.2;                 //! active volume thickness
+    const double ridge_height       = 0.29;                //! closure to pad-plane dimension
+    const double ledge_thickness    = gas_thickness / 3.;  //! ledge thickness supporting A/K wires
+    const double cathode_width      = 1.0;                 //! cathode
+    const double anode_width        = 0.65;                //! anode
+    const double dist_width         = 0.40;                //! distance from anode to PP
+    const double WIN_OutX_thickness = 0.35;                //! outside framing
+    const double WIN_OutY_thickness = 0.30;                //! half of outside framing
+    ClassDef(ChamberBuilder::Volume, 1)                    // Model for the TRD active volume
+  };
+
+  /** \brief Inner class describing the back panel of composed of
+   * - pad plane
+   * - honey-comb structure for reinforcement
+   * electric shielding
+  **/
+  class ChamberBuilder::BackPanel : public ChamberBuilder::Component {
+   public:
+    /** \brief Constructor.
+    **/
+    BackPanel();
+    /** \brief Init task **/
+    virtual InitStatus Init();
+
+   private:
+    BackPanel(const BackPanel&);
+    TGeoTranslation* tr = nullptr;
+    TString sexpr       = "";
+
+    const double pp_pads_thickness  = 0.0020;  //! cu coverage of PP PCB
+    const double pp_pcb_thickness   = 0.0230;  //! PP support PCB thickness
+    const double hc_thickness       = 2.30;    //! Honneycomb backpanel support thickness
+    const double hc_unitx           = 6.0;     //! area opearted by one FASP 6 x 2.7 cm2
+    const double hc_unity           = 2.7;     //! area opearted by one FASP 6 x 2.7 cm2
+    const double hc_holex           = 2.4;     //! dimension of flat-cable hole x-dimension (along wires)
+    const double hc_holey           = 0.8;     //! dimension of flat-cable hole x-dimension (along wires)
+    const double cu_pcb_thickness   = 0.0150;  //! Electric shield PCB support thickness
+    const double cu_thickness       = 0.0020;  //! Electric shield Cu covarage thickness
+    const double BKP_Frame_width    = 1.;      //! Global width of the perimetral frame (including indentation)
+    const double BKP_Frame_closure  = 0.25;    //! Perimetral frame indentation
+    const double BKP_OutX_thickness = 0.50;    //! outside framing
+    const double BKP_OutY_thickness = 0.45;    //! outside framing
+    const double BKP_OutY_correct   = 0.15;    //! framing overlap between th BP and frame
+
+    ClassDef(ChamberBuilder::BackPanel, 1)  // Model for the TRD back panel
+  };
+  /** \brief Inner class describing the geometry of the TRD Front End Electronics (FEE):
+  **/
+  class ChamberBuilder::FEB : public ChamberBuilder::Component {
+   public:
+    /** \brief Constructor.
+    **/
+    FEB();
+    /** \brief Init task **/
+    virtual InitStatus Init();
+
+   private:
+    FEB(const FEB&);
+    //ChamberBuilder::FEB operator=(const FEB&);
+    const double FASP_x    = 1.10;    //!
+    const double FASP_y    = 1.10;    //!
+    const double FASP_z    = 0.10;    //!
+    const double FPGA_x    = 2.20;    //!
+    const double FPGA_y    = 2.20;    //!
+    const double FPGA_z    = 0.18;    //!
+    const double ADC_x     = 0.9;     //!
+    const double ADC_y     = 1.5;     //!
+    const double ADC_z     = 0.1;     //!
+    const double DCDC_x    = 1.5012;  //!
+    const double DCDC_y    = 0.8992;  //!
+    const double DCDC_z    = 0.4319;  //!
+    const double ConnFC_x  = 2.37;    //!
+    const double ConnFC_y  = 0.535;   //!
+    const double ConnFC_z  = 0.266;   //!
+    const double ConnBRG_x = 0.5;     //!
+    const double ConnBRG_y = 4.58;    //!
+    const double ConnBRG_z = 0.658;   //!
+
+    static const int FASPRO_Nly                = 18;    //!
+    static const int FASPRO_Nfasp              = 12;    //!
+    static const int FASPRO_Nadc               = 6;     //!
+    static const int FASPRO_Nfpga              = 3;     //!
+    static const int FASPRO_Ndcdc              = 3;     //!
+    const double FASPRO_zspace                 = 1.0;   //! gap size between boards
+    const double FASPRO_length                 = 17.8;  //! length of FASP FEBs in cm
+    const double FASPRO_width                  = 10.6;  //! width of FASP FEBs in cm
+    const double FASPRO_hole_x                 = 2.2;   //!
+    const double FASPRO_hole_y                 = 0.4;   //!
+    const double FASPRO_ly_cu[FASPRO_Nly][2]   = {      // FASPRO(Cu) layer thickness [um] and covarage [%]
+                                                {54, 95}, {34, 10}, {16, 95}, {16, 10}, {16, 95}, {34, 10},
+                                                {16, 95}, {16, 10}, {16, 95}, {16, 95}, {16, 10}, {16, 95},
+                                                {34, 10}, {16, 95}, {16, 10}, {16, 95}, {34, 10}, {54, 95}};
+    const double FASPRO_ly_pcb[FASPRO_Nly - 1] = {// FASPRO(FR4) layer thickness [um]
+                                                  100, 133, 100, 127, 100, 133, 100, 127, 100,
+                                                  127, 100, 133, 100, 127, 100, 133, 100};
+    const double HOLE_pos[FASPRO_Nfasp][2]     = {{-6, -3.55}, {-6, -1.55}, {-6, 1.55}, {-6, 3.55},
+                                              {0, -3.55},  {0, -1.55},  {0, 1.55},  {0, 3.55},
+                                              {+6, -3.55}, {+6, -1.55}, {+6, 1.55}, {+6, 3.55}};
+    const double FASP_pos[FASPRO_Nfasp][2]     = {{-6, -4.5}, {-6, -2.5}, {-6, +2.5}, {-6, +4.5}, {0, -4.5},  {0, -2.5},
+                                              {0, +2.5},  {0, +4.5},  {+6, -4.5}, {+6, -2.5}, {+6, +2.5}, {+6, +4.5}};
+    const double ADC_pos[FASPRO_Nadc][2]       = {{-4.15, -3.35}, {1.85, -3.35}, {7.85, -3.35},
+                                            {-4.15, +3.35}, {1.85, +3.35}, {7.85, +3.35}};
+    const double FPGA_pos[FASPRO_Nfpga][2]     = {{-6, 0}, {0, 0}, {+6, 0}};
+    const double DCDC_pos[FASPRO_Ndcdc][2]     = {{-3, 0.1}, {3, -1.2}, {2.89, 0.1}};
+    const double ConnFC_pos[FASPRO_Nfasp][2]   = {{-6, -4.9}, {-6, -2.9}, {-6, 2.9},  {-6, 4.9},  {0, -4.9}, {0, -2.9},
+                                                {0, 2.9},   {0, 4.9},   {+6, -4.9}, {+6, -2.9}, {+6, 2.9}, {+6, 4.9}};
+    const double ConnBRG_pos[2][2]             = {{-8.4, 0}, {+8.4, 0}};
+
+    ClassDef(ChamberBuilder::FEB, 1)  // Model for the TRD FEB geometry
+  };
+}  // namespace cbm::trd::geo
+#endif  // CBMTRDGEOFACTORY_H_
diff --git a/core/detectors/trd/CbmTrdGeoSetup.cxx b/core/detectors/trd/CbmTrdGeoSetup.cxx
new file mode 100644
index 0000000000..ac43cbc771
--- /dev/null
+++ b/core/detectors/trd/CbmTrdGeoSetup.cxx
@@ -0,0 +1,491 @@
+/* Copyright (C) 2024 National Institute of Physics and Nuclear Engineering - Horia Hulubei, Bucharest
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Alexandru Bercuci [committer] */
+
+#include "CbmTrdGeoSetup.h"
+
+#include "CbmTrdGeoFactory.h"
+
+#include <FairParGenericSet.h>  // for FairParGenericSet
+#include <FairParamList.h>      // for FairParamList
+#include <FairRunAna.h>         // for FairRunAna
+#include <FairRuntimeDb.h>      // for FairRuntimeDb
+#include <Logger.h>             // for LOG
+
+#include <TArrayI.h>      // for TArrayI
+#include <TDatime.h>      // for TDatime::AsString()
+#include <TGeoElement.h>  // for active volume material interogation
+#include <TGeoManager.h>  // for TGeoManager, gGeoManager
+#include <TGeoNode.h>     // for TGeoNode
+#include <TObjArray.h>    // for TObjArray
+#include <TSystem.h>      // for TSystem::GetUserInfo()
+
+using namespace cbm::trd::geo;
+
+
+//__________________________________________________________________
+InitStatus SetupManager::Init()
+{
+  InitStatus stat;
+  TGeoNode* topNode = gGeoManager->GetTopNode();
+  TObjArray* nodes  = topNode->GetNodes();
+  for (Int_t iNode = 0; iNode < nodes->GetEntriesFast(); iNode++) {
+    TGeoNode* trdGeo = static_cast<TGeoNode*>(nodes->At(iNode));
+    if (string(trdGeo->GetName()).find("trd") != 0) continue;  // trd_vXXy top node, e.g. trd_v13a, trd_v14b
+    fGeoTag = trdGeo->GetName();
+
+    // init the setup. Collect meta info
+    string uname = "John Doe", ucontact = "not-defined", udescr = "not-defined";
+    // retrieve user name from the system
+    auto uinfo = gSystem->GetUserInfo(gSystem->GetEffectiveUid());
+    if (!uinfo)
+      LOG(warning) << "Couldn't read user_name.";
+    else
+      uname = uinfo->fRealName;
+    if (fContact.compare("") == 0)
+      LOG(warning) << "No contact info were provided for responsible " << uname;
+    else
+      ucontact = fContact;
+    if (fDescription.compare("") == 0)
+      LOG(error) << "No comments provided for setup. Please add them by SetupManager::SetDescription()";
+    else
+      udescr = fDescription;
+
+    // build setup adding all meta info
+    uname += ";";
+    uname += ucontact;
+    TDatime d;
+    uname += ";";
+    uname += d.AsString();
+    uname += ";";
+    uname += udescr;
+    Setup* setup = new Setup(fGeoTag.data(), uname.data());
+    Setup::Module modSetup;
+    //fHardwareSetup.SelectComponentIdMap(fGeometryTag);
+    TObjArray* layers = trdGeo->GetNodes();
+    for (Int_t iLayer = 0; iLayer < layers->GetEntriesFast(); iLayer++) {
+      TGeoNode* lyGeo = static_cast<TGeoNode*>(layers->At(iLayer));
+      if (string(lyGeo->GetName()).find("layer") != 0) continue;  // only layers
+
+      TObjArray* modules = lyGeo->GetNodes();
+      for (Int_t iModule = 0; iModule < modules->GetEntriesFast(); iModule++) {
+        TGeoNode* modGeo = static_cast<TGeoNode*>(modules->At(iModule));
+        // skip geo elements which are not modules
+        if (string(modGeo->GetName()).find("module") != 0) continue;
+
+        LOG(info) << " Reading module " << modGeo->GetName() << " [" << lyGeo->GetName() << "].";
+        stat = modSetup.init(modGeo);
+        switch (stat) {
+          case kERROR: continue;
+          case kFATAL: LOG(fatal) << GetName() << " Couldn't process geometry file."; break;
+          case kSUCCESS: setup->addParam(new Setup::Module(modSetup)); break;
+        }
+      }     // loop over TRD modules / layers
+    }       // loop over TRD layers
+    break;  // loop over CBM systems
+  }
+  return kSUCCESS;
+}
+
+//__________________________________________________________________
+void SetupManager::SetParContainers()
+{
+  FairRuntimeDb* rtdb = FairRunAna::Instance()->GetRuntimeDb();
+  fSetup              = (Setup*) (rtdb->getContainer("TrdSetup"));
+}
+
+//__________________________________________________________________
+void SetupManager::Finish()
+{
+  FairRuntimeDb* rtdb = FairRunAna::Instance()->GetRuntimeDb();
+  fSetup              = (Setup*) (rtdb->getContainer("TrdSetup"));
+  //fSetup->Print();
+}
+
+//__________________________________________________________________
+Setup::Setup(const char* n, const char* t) : FairParGenericSet(n, t, "default")
+{
+  /** Define complementing info besides the geo description for the TRD system setup.
+   * n = geo tag; e.g. for "trd_v22d_mcbm.geo.root" name = "v22d_mcbm"
+   * t = meta info; list of ";" separated information in the following order
+   *  - "name"  : responsible person's name
+   *  - "email" : responsible person's email
+   *  - "date"  : date of creation
+   */
+  fMetaFields.push_back("name");
+  fMetaFields.push_back("email");
+  fMetaFields.push_back("date");
+  size_t ii(0);
+  if ((ii = Parse()) != fMetaFields.size()) {
+    Help();
+    LOG(warning) << "Number of info fields " << ii << " less than required (" << fMetaFields.size()
+                 << "). Info might be spoiled. Check input.\n";
+  }
+  else {
+    for (auto info : fMeta) {
+      if (strcmp(info.second.data(), "") != 0) continue;
+      Help(info.first.data());
+    }
+  }
+}
+
+//__________________________________________________________________
+const char* Setup::GetInfo(const char* label) const
+{
+  if (fMeta.find(label) == fMeta.end()) {
+    Help(label);
+    return nullptr;
+  }
+  return fMeta.at(label).data();
+}
+
+//__________________________________________________________________
+void Setup::Help(const char* lab) const
+{
+  LOG(info) << "* meta info; list of \";\" separated information in the following order:";
+  LOG(info) << "*  - \"name\"  : responsible person's name";
+  LOG(info) << "*  - \"email\" : responsible person's email";
+  LOG(info) << "*  - \"date\"  : date of creation";
+
+  if (lab) {
+    if (fMeta.find(lab) == fMeta.end())
+      LOG(error) << "Meta info \"" << lab << "\" not defined.\n";
+    else
+      LOG(warning) << "Meta info for\"" << lab << "\" not registered.\n";
+  }
+}
+
+//__________________________________________________________________
+size_t Setup::Parse()
+{
+  size_t idx(0);
+  string s(GetTitle());
+  char* p = strtok(s.data(), ";");
+  while (p != nullptr && idx < fMetaFields.size()) {
+    fMeta[fMetaFields[idx++]] = p;
+    p                         = strtok(nullptr, ";");
+  }
+  return idx;
+}
+
+//_______________________________________________________________________________
+Setup::~Setup() { fModule.clear(); }
+
+//_______________________________________________________________________________
+int Setup::GetModuleId(int i) const
+{
+  if (i < 0 || i >= (int) GetNrOfModules()) return -1;
+  uint16_t id = fModule[i]->GetModuleId();
+  if (id == 0xffff)
+    return -1;
+  else
+    return id;
+}
+
+//_______________________________________________________________________________
+const Setup::Module* Setup::GetModulePar(int detId) const
+{
+  for (auto mod : fModule)
+    if (mod->GetModuleId() == detId) return mod;
+  return nullptr;
+}
+
+//_______________________________________________________________________________
+bool Setup::getParams(FairParamList* l)
+{
+  if (!l) return false;
+  if (!l->fill("Version", &fVersion)) {
+    LOG(error) << GetName() << "::getParams : Couldn't find \"Version\"";
+    return false;
+  }
+  int nmods(0);
+  if (!l->fill("NrOfModules", &nmods)) {
+    LOG(error) << GetName() << "::getParams : Couldn't find \"NrOfModules\"";
+    return false;
+  }
+  TArrayI modId(nmods), typId(nmods), rot(nmods);
+  if (!l->fill("Trd.Id", &modId)) {
+    LOG(error) << GetName() << "::getParams : Couldn't find \"Trd.Id\"";
+    return false;
+  }
+  if (!l->fill("Trd.Type", &typId)) {
+    LOG(error) << GetName() << "::getParams : Couldn't find \"Trd.Type\"";
+    return false;
+  }
+  if (!l->fill("Trd.Rot", &rot)) {
+    LOG(error) << GetName() << "::getParams : Couldn't find \"Trd.Rot\"";
+    return false;
+  }
+  Text_t textIn[100];
+  if (!l->fill("Trd.Gas", textIn, 100)) {
+    LOG(error) << GetName() << "::getParams : Couldn't find \"Trd.Gas\"";
+    return false;
+  }
+  if (textIn[0] == 'A' && textIn[1] == 'r')
+    fGas = eGas::kAr;
+  else
+    fGas = eGas::kXe;
+
+  for (int imod(0); imod < nmods; imod++) {
+    fModule.push_back(new Module(Form("Trd%s.%d", (modId[imod] < 0 ? "2D" : "1D"), abs(modId[imod])), GetTitle()));
+    auto mod   = fModule.back();
+    mod->fType = typId[imod];
+    mod->fRot  = rot[imod];
+    mod->getParams(l);
+  }
+  return true;
+}
+
+
+//_______________________________________________________________________________
+void Setup::putParams(FairParamList* l)
+{
+  if (!l) return;
+  l->add("Version", fVersion);
+  int ii(0), nmods = (int) GetNrOfModules();
+  l->add("NrOfModules", nmods);
+  TArrayI modId(nmods), typId(nmods), rot(nmods);
+  for (auto mod : fModule) {
+    modId[ii] = mod->GetModuleId() * (mod->GetFamily() == ePadPlane::k1d ? 1 : -1);
+    typId[ii] = mod->GetType();
+    rot[ii]   = mod->GetRotation();
+    ii++;
+  }
+  l->add("Trd.Id", modId);
+  l->add("Trd.Type", typId);
+  l->add("Trd.Rot", rot);
+  if (fGas == eGas::kAr)
+    l->add("Trd.Gas", "ArCO2");
+  else
+    l->add("Trd.Gas", "XeCO2");
+  for (auto mod : fModule)
+    mod->putParams(l);
+}
+
+//_______________________________________________________________________________
+void Setup::addParam(Module* mod) { fModule.push_back(mod); }
+
+//_______________________________________________________________________________
+Setup::Module::Module(const char* n, const char* t) : TNamed(n, t)
+{
+  //   string name = n;
+  //   if (name.size() > 6) {
+  //     if (name.substr(3, 2).compare("1D") == 0) fFamily = ePadPlane::k1d;
+  //     else
+  //       fFamily = ePadPlane::k2d;
+  //     fId = stoi(name.substr(6, 10));
+  //   }
+}
+
+//_______________________________________________________________________________
+Setup::Module::Module(const Module& m0) : TNamed((const TNamed&) m0)
+{
+  fId      = m0.fId;
+  fFee     = m0.fFee;
+  fFamily  = m0.fFamily;
+  fWindow  = m0.fWindow;
+  fGas     = m0.fGas;
+  fType    = m0.fType;
+  fFeeType = m0.fFeeType;
+  fRot     = m0.fRot;
+  fDaq     = m0.fDaq;
+  fFEE     = m0.fFEE;
+}
+
+//_______________________________________________________________________________
+InitStatus Setup::Module::init(TGeoNode* n)
+{
+  bool hasRadiator(false);
+  info_t info;
+  if (!ReadModuleInfo(n->GetName(), info)) return kERROR;
+
+  TObjArray* components = n->GetNodes();
+  for (Int_t icomp = 0; icomp < components->GetEntriesFast(); icomp++) {
+    TGeoNode* comp = static_cast<TGeoNode*>(components->At(icomp));
+    string cname(comp->GetName());
+
+    if (cname.find(ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kRadiator]) == 0) {
+      LOG(debug4) << GetName() << " Initialize " << comp->GetName() << " with "
+                  << ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kRadiator];
+      hasRadiator = true;  // to be used when defining entrance window params
+    }
+    else if (cname.find(ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kWindow]) == 0) {
+      LOG(debug4) << GetName() << " Initialize " << comp->GetName() << " with "
+                  << ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kWindow];
+      if (!hasRadiator)
+        fWindow = eWindow::kNotSet;
+      else {  // determine if the module have a thin (1D) or thick (2D) entrance window
+        int selectFeature(0);
+        TIter ipcs(comp->GetNodes());
+        while (auto pcs = (TGeoNode*) ipcs()) {
+          if (string(pcs->GetName()).find("winIn_C") == 0)
+            selectFeature++;
+          else if (string(pcs->GetName()).find("winIn_HC") == 0)
+            selectFeature++;
+        }
+        if (selectFeature == 2)
+          fWindow = eWindow::kThick;
+        else
+          fWindow = eWindow::kThin;
+
+        LOG(info) << GetName() << " Initialize TR absorption in " << (fWindow == eWindow::kThick ? "thick" : "thin")
+                  << " entrance window.";
+      }
+    }
+    else if (cname.find(ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kVolume]) == 0) {
+      LOG(debug4) << GetName() << " Initialize " << comp->GetName() << " with "
+                  << ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kVolume];
+      // determine the active gas
+      auto gas = (TGeoNode*) comp->GetNodes()->FindObject("gas_0");
+      if (!gas)
+        LOG(error) << GetName() << " Couldn't find \"gas_0\" in " << comp->GetName();
+      else {
+        auto activeGas = gas->GetMedium()->GetMaterial();
+        for (int imat(0); imat < activeGas->GetNelements(); imat++) {
+          auto elem = activeGas->GetElement(imat);
+          switch (elem->Z()) {
+            case 6:
+            case 8: break;  // do nothing for C and O
+            case 18:        // found Ar
+              fGas = eGas::kAr;
+              break;
+            case 54:  // found Xe
+              fGas = eGas::kXe;
+              break;
+            default:
+              elem->Print();
+              LOG(error) << GetName() << " Couldn't found element in active gas from " << comp->GetName();
+              break;
+          }
+        }
+      }
+      if (fGas == eGas::kNotSet) {
+        LOG(warning) << GetName() << " Couldn't identify active gas type. Use legacy mode.";
+        return kERROR;
+      }
+      LOG(info) << GetName() << " Initialize active gas to " << (fGas == eGas::kXe ? "XeCO2." : "ArCO2.");
+    }
+    else if (cname.find(ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kBackPanel]) == 0) {
+      LOG(debug4) << GetName() << " Initialize " << comp->GetName() << " with "
+                  << ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kBackPanel];
+      // find the type of the pad-plane and consequently the TRD family
+      TIter ibkp(comp->GetNodes());
+      while (auto bkp = (TGeoNode*) ibkp()) {
+        if (string(bkp->GetName()).find("pp_pcb2d") == 0) {
+          fFamily = ePadPlane::k2d;  // 2d
+          SetName(Form("Trd2D.%d", info.address));
+          break;
+        }
+        else if (string(bkp->GetName()).find("pp_pcb1d") == 0) {
+          fFamily = ePadPlane::k1d;  // 1d
+          SetName(Form("Trd1D.%d", info.address));
+          break;
+        }
+      }
+      if (fFamily == ePadPlane::kNotSet) {
+        LOG(error) << GetName() << " Couldn't identify TRD module family for " << n->GetName() << " " << n->GetTitle();
+        return kFATAL;
+      }
+      LOG(info) << GetName() << " Initialize TRD family to " << (fFamily == ePadPlane::k2d ? "2D." : "1D;");
+    }
+    else if (cname.find(ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kFEB]) == 0) {
+      LOG(info) << GetName() << " Initialize " << comp->GetName() << " with "
+                << ChamberBuilder::Component::fgName[(int) ChamberBuilder::eGeoPart::kFEB];
+      // find the FEE family, number of ASICs / module and eventually mapping
+      if (!ReadFebInfo(comp->GetName(), info)) return kERROR;
+    }
+    else {
+      LOG(info) << GetName() << "Geometry of module " << n->GetName() << " uses legacy setup.";
+      return kERROR;
+    }
+    //           if (!TString(part->GetName()).BeginsWith("gas_")) continue;  // only active gas volume
+    //
+    //           // Put together the full path to the interesting volume, which
+    //           // is needed to navigate with the geomanager to this volume.
+    //           // Extract the geometry information (size, global position)
+    //           // from this volume.
+    //           TString path = TString("/") + topNode->GetName() + "/" + station->GetName() + "/" + layer->GetName() + "/"
+    //                          + module->GetName() + "/" + part->GetName();
+    //
+    //           CreateModuleParameters(path);
+  }
+  return kSUCCESS;
+}
+
+//_______________________________________________________________________________
+void Setup::Module::putParams(FairParamList* l)
+{
+  int ii(0);
+  TArrayI daqId(fDaq.size());
+  for (auto ic : fDaq)
+    daqId[ii++] = ic;
+  l->add(Form("%s.DaqInfo", GetName()), daqId);
+
+  ii        = 0;
+  auto pads = fFEE[0]->GetPads();
+  TArrayI asicSetup(fFEE.size() * (pads.size() + 2));
+  for (auto asic : fFEE) {
+    asicSetup[ii++] = asic->GetId();  // asic id in the module
+    asicSetup[ii++] = asic->GetMask();
+    pads            = asic->GetPads();
+    for (auto pad : pads)
+      asicSetup[ii++] = pad;
+  }
+  l->add(Form("%s.%sInfo", GetName(), (fFee == eAsic::kSpadic ? "Spadic" : "Fasp")), asicSetup);
+}
+
+//_______________________________________________________________________________
+bool Setup::Module::getParams(FairParamList* l)
+{
+  READOUT pMod = (fFamily == ePadPlane::k1d ? mod1D[fType] : mod2D[fType]);
+  FEB pFeb     = faspFeb[fFeeType];
+  int ndaq     = pMod.ndaq;
+  int nasic    = pMod.nasic;
+  int nch      = pFeb.nchannels;
+  TArrayI daqId(ndaq);
+  if (!l->fill(Form("%s.DaqInfo", GetName()), &daqId)) {
+    LOG(error) << GetName() << "::getParams : Couldn't find \"DaqInfo\"";
+    return false;
+  }
+  fDaq.assign(daqId.GetArray(), daqId.GetArray() + ndaq);
+
+  TArrayI asicInfo(nasic);
+  if (!l->fill(Form("%s.SpadicInfo", GetName()), &asicInfo)) fFee = eAsic::kSpadic;
+  if (!l->fill(Form("%s.FaspInfo", GetName()), &asicInfo))
+    fFee = eAsic::kFasp;
+  else {
+    LOG(error) << GetName() << "::getParams : Couldn't find \"AsicInfo\"";
+    return false;
+  }
+  for (int i(0), k(0); i < nasic; i++) {
+    fFEE.push_back(new Asic(Form("%s%d", (fFee == eAsic::kSpadic ? "Spadic" : "Fasp"), i), GetName()));
+    auto asic     = fFEE.back();
+    asic->fUnique = asicInfo[k++];
+    asic->fMask   = asicInfo[k++];
+    asic->fPad.assign(&asicInfo[k], &asicInfo[k + nch]);
+    k += nch;
+  }
+
+  return true;
+}
+
+//_______________________________________________________________________________
+Setup::Asic::Asic(const char* n, const char* t) : TNamed(n, t)
+{
+  string name = n;
+  // fFamily = eAsic::kFasp;
+  int nskip(4);
+  if (name.find("Spadic") == 0) {
+    // fFamily = eAsic::kSpadic;
+    nskip = 6;
+  }
+  fId = stoi(name.substr(nskip, 10));
+}
+
+/* clang-format off */
+// NamespaceImp(cbm::trd::geo)
+ClassImp(cbm::trd::geo::SetupManager)
+ClassImp(cbm::trd::geo::Setup)
+ClassImp(cbm::trd::geo::Setup::Module)
+ClassImp(cbm::trd::geo::Setup::Asic)
+  /* clang-format on */
diff --git a/core/detectors/trd/CbmTrdGeoSetup.h b/core/detectors/trd/CbmTrdGeoSetup.h
new file mode 100644
index 0000000000..9d82748718
--- /dev/null
+++ b/core/detectors/trd/CbmTrdGeoSetup.h
@@ -0,0 +1,204 @@
+/* Copyright (C) 2024 National Institute of Physics and Nuclear Engineering - Horia Hulubei, Bucharest
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Alexandru Bercuci [committer] */
+
+/**
+ * \file CbmTrdGeoSetup.h
+ * \brief Describing class of the TRD setup geometry, FEE, gas.
+ * \author Alexandru Bercuci <abercuci@niham.nipne.ro>
+ * \date 20/10/2023
+ *
+ * This class describe the setup of the TRD detectors including :
+ * - version : local versioning of the setup (within the TRD group)
+ * - main-type of TRD version : 1/2 D version
+ * - sub-type of TRD version : 1, 3, 5, etc
+ * - rotation : no. of 90 deg 
+ * - gas : gas type
+ * 
+ * Detector-wise description
+ * - DAQ : Data AQuisition for each module (CROB/CRI config)
+ * - FEE : Front-End Electronics description for each modue (ASIC config)
+ */
+
+#ifndef CBMTRDGEOSETUP_H_
+#define CBMTRDGEOSETUP_H_
+
+#include "CbmTrdDefs.h"  // for trd namespace
+
+#include <FairParGenericSet.h>  // for FairParGenericSet
+#include <FairTask.h>           // for FairTask
+
+#include <TNamed.h>  // for the base class
+
+#include <map>
+#include <string>
+#include <vector>
+
+using namespace std;
+using namespace cbm::trd;
+class FairParamList;
+class TGeoNode;
+namespace cbm::trd::geo
+{
+  /** \class Setup
+   * \brief Setup meta info for the TRD system to supplement the geometry
+   */
+  class Setup : public FairParGenericSet {
+   public:
+    friend class SetupManager;
+    class Asic;
+    class Module;
+
+    /** \brief Setup descriptor for the TRD setup. The identification should be :       
+     * \param[in] n identification of geometry setup to which it is linked.
+     * \param[in] t responsible name, email and date of creation.
+    **/
+    Setup(const char* n, const char* t);
+    virtual ~Setup();
+    /** \brief Retrieve meta info for the setup according to label. \sa Setup().       
+     * \param[in] label description of the meta info to be retrieved. In case of un-registered label return nullptr;
+    **/
+    virtual const char* GetInfo(const char* label) const;
+    /** \brief Get module par by index
+     * \param[in] i index of the module in the list */
+    virtual int GetModuleId(int i) const;
+    /** \brief Get module par by detector id
+     * \param[in] detId detector id in the setup */
+    virtual const Module* GetModulePar(int detId) const;
+    /** \brief Retrieve no of modules in the setup*/
+    virtual size_t GetNrOfModules() const { return fModule.size(); }
+    /** \brief Retrieve full list of modules in the setup*/
+    vector<Module*> GetModules() { return fModule; }
+    virtual void addParam(Module* mod);
+    /** \brief Write out the setup from object to FairParamList*/
+    virtual void putParams(FairParamList*);
+    /** \brief Read in the setup from FairParamList*/
+    virtual bool getParams(FairParamList*);
+
+   protected:
+    int fVersion               = 1;              ///<
+    eGas fGas                  = eGas::kNotSet;  ///<
+    vector<Module*> fModule    = {};             ///< list of modules defined in the setup
+    vector<string> fMetaFields = {};             ///< ordered list of meta info types
+    map<string, string> fMeta  = {};             ///< meta info attached to this setup
+
+   private:
+    Setup(const Setup&);
+    /** \brief Help message for user */
+    void Help(const char* lab = nullptr) const;
+    /** \brief Parse setup description for meta info */
+    size_t Parse();
+
+    ClassDef(cbm::trd::geo::Setup, 1)  // Setup description of the TRD system, accompanying the geometry
+  };                                   // class cbm::trd::geo::Setup
+
+
+  /**
+   * \class Setup::Module
+   * \brief Meta info for one TRD module
+   */
+  class Setup::Module : public TNamed {
+   public:
+    friend class Setup;
+    friend class SetupManager;
+    Module(const char* n = "", const char* t = "");
+
+    int GetModuleId() const { return (fId == 0xffff ? -1 : 1); }
+    int GetType() const { return fType; }
+    int GetRotation() const { return fRot; }
+    ePadPlane GetFamily() const { return fFamily; }
+    eAsic GetFeeType() const { return fFee; }
+    eWindow GetWindowType() const { return fWindow; }
+    vector<int> GetDaq() const { return fDaq; }
+    vector<Asic*> GetFEE() const { return fFEE; }
+
+   protected:
+    /** \brief Read info relevant for the module from the geometry*/
+    virtual InitStatus init(TGeoNode*);
+    /** \brief Write out the setup from object to FairParamList*/
+    virtual void putParams(FairParamList*);
+    /** \brief Read in the setup from FairParamList*/
+    virtual bool getParams(FairParamList*);
+
+    uint16_t fId       = 0xffff;              ///< TRD chamber id in the setup
+    ePadPlane fFamily  = ePadPlane::kNotSet;  ///< Chamber family (1D / 2D)
+    eAsic fFee         = eAsic::kNotSet;      ///< ASIC family (SPADIC/FASP)
+    eWindow fWindow    = eWindow::kNotSet;    ///< Entrance window type
+    eGas fGas          = eGas::kNotSet;       ///< gas type
+    int fType          = 1;                   ///< TRD chamber sub-type (e.g. 1, 3, 5, 7 for TRD1D)
+    int fFeeType       = 1;                   ///< FEB type for each FEE version
+    int fRot           = 0;                   ///< rotation of chamber in steps of 90 deg
+    vector<int> fDaq   = {};                  ///<
+    vector<Asic*> fFEE = {};                  ///<
+   private:
+    Module(const Module&);
+
+    ClassDef(cbm::trd::geo::Setup::Module, 1)  // Setup description of a TRD module
+  };                                           // class cbm::trd::geo::Setup::Module
+
+
+  /**
+   * \class Setup::Asic
+   * \brief Meta info for one TRD ASIC
+   */
+  class Setup::Asic : public TNamed {
+   public:
+    friend class Setup;
+    friend class SetupManager;
+    Asic(const char* n, const char* t);
+    int GetMask() const { return fMask; }
+    int GetId() const { return (fId == 0xff ? -1 : fId); }
+    int GetUniqueId() const { return (fUnique == 0xffff ? -1 : fUnique); }
+    vector<int> GetPads() const { return fPad; }
+
+   private:
+    Asic(const Asic&);
+
+    uint8_t fId      = 0xff;    ///< ASIC id in the chamber
+    uint16_t fUnique = 0xffff;  ///< ASIC id in the production
+    uint16_t fMask   = 0xffff;  ///<
+    vector<int> fPad = {};      ///<
+
+    ClassDef(cbm::trd::geo::Setup::Asic, 1)  // Setup description of an ASIC
+  };                                         // class cbm::trd::geo::Setup::Asic
+
+
+  /**
+   * \class SetupManager
+   * \brief Generate setup meta info for the TRD system
+   */
+  class SetupManager : public FairTask {
+   public:
+    /** \brief Default constructor.*/
+    SetupManager() : FairTask("TrdSetupManager") { ; }
+    /** \brief Destructor.*/
+    virtual ~SetupManager() { ; }
+    /** \brief Inherited from FairTask.*/
+    virtual InitStatus Init();
+    /** \brief Inherited from FairTask.*/
+    virtual void SetParContainers();
+    /** \brief Inherited from FairTask.*/
+    virtual void Exec(Option_t*) { ; }
+    /** \brief Inherited from FairTask.*/
+    virtual void Finish();
+
+    void SetContact(const char* contact) { fContact = contact; }
+    void SetDescription(const char* text) { fDescription = text; }
+
+   private:
+    SetupManager(const SetupManager&);
+    SetupManager& operator=(const SetupManager&);
+    /** \brief .*/
+    void CreateModuleParameters(const TString& path);
+    /** \brief .*/
+    bool CreateParFilesFromGeometry(TString outDir = "");
+
+    string fGeoTag      = "";       ///< the setup name
+    string fContact     = "";       ///< contact info (usual email) of the responsible
+    string fDescription = "";       ///< further description of the current setup
+    Setup* fSetup       = nullptr;  ///< the setup object
+
+    ClassDef(cbm::trd::geo::SetupManager, 1)  // Manages the creation of meta info for the TRD system setup
+  };                                          // class cbm::trd::geo::SetupManager
+}  // namespace cbm::trd::geo
+#endif  // CBMTRDGEOSETUP_H_
diff --git a/core/detectors/trd/CbmTrdModuleAbstract.cxx b/core/detectors/trd/CbmTrdModuleAbstract.cxx
index 9ba7513d73..7fcfca29e9 100644
--- a/core/detectors/trd/CbmTrdModuleAbstract.cxx
+++ b/core/detectors/trd/CbmTrdModuleAbstract.cxx
@@ -1,4 +1,4 @@
-/* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Florian Uhlig [committer], Alexandru Bercuci */
 
@@ -9,33 +9,15 @@
 #include <Logger.h>
 
 //_______________________________________________________________________________
-CbmTrdModuleAbstract::CbmTrdModuleAbstract()
-  : TNamed()
-  , fModConfig(0)
-  , fModAddress(0)
-  , fLayerId(-1)
-  , fRotation(0)
-  , fDigiPar(nullptr)
-  , fChmbPar(nullptr)
-  , fAsicPar(nullptr)
-  , fGainPar(nullptr)
-  , fGeoPar(nullptr)
-{
-}
+CbmTrdModuleAbstract::CbmTrdModuleAbstract() : TNamed() {}
 
 //_______________________________________________________________________________
 CbmTrdModuleAbstract::CbmTrdModuleAbstract(Int_t mod, Int_t ly, Int_t rot)
   : TNamed("CbmTrdModule", "Abstract TRD module implementation")
-  , fModConfig(0)
-  , fModAddress(mod)
-  , fLayerId(ly)
-  , fRotation(rot)
-  , fDigiPar(nullptr)
-  , fChmbPar(nullptr)
-  , fAsicPar(nullptr)
-  , fGainPar(nullptr)
-  , fGeoPar(nullptr)
 {
+  fModAddress = mod;
+  fLayerId    = ly;
+  fRotation   = rot;
 }
 
 //_______________________________________________________________________________
diff --git a/core/detectors/trd/CbmTrdModuleAbstract.h b/core/detectors/trd/CbmTrdModuleAbstract.h
index 75bc0ad3bf..388f439e35 100644
--- a/core/detectors/trd/CbmTrdModuleAbstract.h
+++ b/core/detectors/trd/CbmTrdModuleAbstract.h
@@ -1,10 +1,11 @@
-/* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Florian Uhlig [committer], Alexandru Bercuci */
 
 #ifndef CBMTRDMODULEABSTRACT_H
 #define CBMTRDMODULEABSTRACT_H
 
+#include "CbmTrdDefs.h"        // for cbm::trd namespace
 #include "CbmTrdParModAsic.h"  // for CbmTrdParSetAsic
 #include "CbmTrdParModDigi.h"  // for CbmTrdParModDigi
 #include "CbmTrdParModGeo.h"   // for CbmTrdParModGeo
@@ -16,17 +17,22 @@
 class CbmTrdParModGain;
 class CbmTrdParModGas;
 
+using namespace cbm::trd;
 /**
-  * \brief Abstract class for TRD module
+  * \brief Abstract class for the TRD module
+  * It provides access to the basic properties of the chamber as follows :
+  * - The chamber geometry (CbmTrdParModGeo)
+  * - The pad-plane geometry (CbmTrdParModDigi)  
+  * - The ASICs allocation and properties (CbmTrdParModAsic)
+  * - The gas properties (CbmTrdParModGas)  
+  * 
+  * It define basic configuration properties
+  * - type in the TRD wall
+  * - type of pad-plane (1D or 2D)
+  * - type of FEE ASIC (SPADIC or FASP)
   **/
 class CbmTrdModuleAbstract : public TNamed {
 public:
-  enum eCbmTrdModuleDef
-  {
-    kTrd2d = 0  ///< toggle pad-plane type of the chamber
-      ,
-    kFasp = 1  ///< toggle FEE type for the module
-  };
   /** \brief Default constructor.*/
   CbmTrdModuleAbstract();
   /** \brief Constructor with placement */
@@ -64,14 +70,6 @@ public:
    */
   virtual inline Int_t GetPadRowCol(Int_t address, Int_t& c) const;
   virtual const Char_t* GetPath() const { return fGeoPar ? fGeoPar->GetTitle() : ""; }
-  /** \brief Inquire the FEE read-out type of the module
-   * \return false for SPADIC and true for FASP
-   */
-  bool HasFaspFEE() const { return TESTBIT(fModConfig, eCbmTrdModuleDef::kFasp); }
-  /** \brief Inquire the pad-plane type of the chamber
-   * \return false for TRD-1D and true for TRD-2D
-   */
-  bool Has2dPadPlane() const { return TESTBIT(fModConfig, eCbmTrdModuleDef::kTrd2d); }
 
   /** \brief Inquire the ASIC par set
    * \return true for actively masked channel
@@ -85,45 +83,18 @@ public:
   virtual void SetDigiPar(const CbmTrdParModDigi* p) { fDigiPar = p; }
   virtual void SetGainPar(const CbmTrdParModGain* p) { fGainPar = p; }
   virtual void SetGeoPar(const CbmTrdParModGeo* p) { fGeoPar = p; }
-
-  /** \brief Define the read-out FEE type of the module
-   * \param[in] set true for FASP and false [default] for SPADIC
-   */
-  void SetFEE(bool set = true)
-  {
-    set ? SETBIT(fModConfig, eCbmTrdModuleDef::kFasp) : CLRBIT(fModConfig, eCbmTrdModuleDef::kFasp);
-  }
-  /** \brief Define the pad-plane type of the chamber
-   * \param[in] set true for TRD-2D and false [default] for TRD-1D
-   */
-  void SetPadPlane(bool set = true)
-  {
-    set ? SETBIT(fModConfig, eCbmTrdModuleDef::kTrd2d) : CLRBIT(fModConfig, eCbmTrdModuleDef::kTrd2d);
-  }
-
 protected:
-  /** 8 bits bit map for module configuration
-   * [0] - chamber's pad-plane type; 0 rectangular pads, 1 triangular pads, \see SetRO
-   * [1] - chamber's FEE type; 0 SPADIC, 1 FASP, \see SetFEE
-   * [2] -  
-   * [3] -  
-   * [4] -  
-   * [5] -  
-   * [6] -  
-   * [7] -  
-   */
-  uint8_t fModConfig;
   // geometrical definitions imported from CbmTrdGeoHandler
-  UShort_t fModAddress;  ///< unique identifier for current module
-  Char_t fLayerId;       ///< layer identifier
-  UChar_t fRotation;     ///< rotation angle for current module
-
-  // calibration objects
-  const CbmTrdParModDigi* fDigiPar;  ///< read-out description of module
-  const CbmTrdParModGas* fChmbPar;   ///< detection description (HV, drift) of module
-  CbmTrdParModAsic* fAsicPar;        ///< the set of ASIC operating on the module (owned)
-  const CbmTrdParModGain* fGainPar;  ///< Analog to digital conversion for module
-  const CbmTrdParModGeo* fGeoPar;    ///< link to gGeometry for module
+ UShort_t fModAddress = 0;   ///< unique identifier for current module
+ Char_t fLayerId      = -1;  ///< layer identifier
+ UChar_t fRotation    = 0;   ///< rotation angle for current module
+
+ // calibration objects
+ const CbmTrdParModDigi* fDigiPar = nullptr;  ///< read-out description of module
+ const CbmTrdParModGas* fChmbPar  = nullptr;  ///< detection description (HV, drift) of module
+ CbmTrdParModAsic* fAsicPar       = nullptr;  ///< the set of ASIC operating on the module (owned)
+ const CbmTrdParModGain* fGainPar = nullptr;  ///< Analog to digital conversion for module
+ const CbmTrdParModGeo* fGeoPar   = nullptr;  ///< link to gGeometry for module
 
 private:
   CbmTrdModuleAbstract(const CbmTrdModuleAbstract& ref);
diff --git a/core/detectors/trd/CbmTrdParMod.cxx b/core/detectors/trd/CbmTrdParMod.cxx
index 8e7d3074e0..847af27fc0 100644
--- a/core/detectors/trd/CbmTrdParMod.cxx
+++ b/core/detectors/trd/CbmTrdParMod.cxx
@@ -1,13 +1,13 @@
-/* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
-   Authors: Florian Uhlig [committer] */
+   Authors: Florian Uhlig [committer], Alexandru Bercuci*/
 
 #include "CbmTrdParMod.h"
 
 #include <Logger.h>  // for LOG
 
 //___________________________________________________________________
-CbmTrdParMod::CbmTrdParMod(const char* name, const char* title) : TNamed(name, title), fModuleId(0) {}
+CbmTrdParMod::CbmTrdParMod(const char* name, const char* title) : TNamed(name, title) {}
 
 //___________________________________________________________________
 CbmTrdParMod::~CbmTrdParMod() { LOG(debug) << GetName() << "::delete[" << GetTitle() << "]"; }
diff --git a/core/detectors/trd/CbmTrdParMod.h b/core/detectors/trd/CbmTrdParMod.h
index d8e7050e86..cfe9d96188 100644
--- a/core/detectors/trd/CbmTrdParMod.h
+++ b/core/detectors/trd/CbmTrdParMod.h
@@ -1,12 +1,11 @@
-/* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
-   Authors: Florian Uhlig [committer] */
+   Authors: Florian Uhlig [committer], Alexandru Bercuci */
 
 #ifndef CBMTRDPARMOD_H
 #define CBMTRDPARMOD_H
 
 #include <Rtypes.h>      // for THashConsistencyHolder, ClassDef
-#include <RtypesCore.h>  // for Int_t
 #include <TNamed.h>      // for TNamed
 
 /** \brief Definition of generic parameters for one TRD module **/
@@ -15,15 +14,21 @@ public:
   CbmTrdParMod(const char* name = "CbmTrdParMod", const char* title = "TRD generic module definition");
   virtual ~CbmTrdParMod();
 
-  virtual Int_t GetModuleId() const { return fModuleId; }
+  virtual uint16_t GetConfig() const { return fConfig; }
+  virtual int GetModuleId() const { return fModuleId; }
+  virtual uint8_t GetVersion() const { return fVersion; }
 
-  virtual void SetModuleId(Int_t m) { fModuleId = m; }
+  virtual void SetConfigId(uint16_t c) { fConfig = c; }
+  virtual void SetModuleId(int m) { fModuleId = m; }
+  virtual void SetVersion(uint8_t v) { fVersion = v; }
 
-protected:
-  Int_t fModuleId;  ///< module id
-private:
+ protected:
+  uint8_t fVersion = 0;  ///< version of the parameter
+  uint16_t fConfig = 0;  ///< configuration setup of the module
+  int fModuleId    = 0;  ///< module id
+ private:
   ClassDef(CbmTrdParMod,
-           1)  // Definition of generic parameters for one TRD module
+           2)  // Definition of generic parameters for one TRD module
 };
 
 #endif
diff --git a/core/detectors/trd/CbmTrdParModDigi.cxx b/core/detectors/trd/CbmTrdParModDigi.cxx
index 9795e2b1ca..2ff82816de 100644
--- a/core/detectors/trd/CbmTrdParModDigi.cxx
+++ b/core/detectors/trd/CbmTrdParModDigi.cxx
@@ -1,6 +1,6 @@
-/* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
-   Authors: Florian Uhlig [committer] */
+   Authors: Florian Uhlig [committer], Alexandru Bercuci */
 
 #include "CbmTrdParModDigi.h"
 
@@ -19,6 +19,8 @@
 #include <stdio.h>   // for printf
 #include <string.h>  // for strcmp
 
+using namespace cbm::trd;
+
 //___________________________________________________________________
 CbmTrdParModDigi::CbmTrdParModDigi()
   : CbmTrdParMod("CbmTrdParModDigi", "TRD read-out definition")
@@ -219,6 +221,13 @@ void CbmTrdParModDigi::ProjectPositionToNextAnodeWire(Double_t* local_point) con
   }
 }
 
+//___________________________________________________________________________
+int CbmTrdParModDigi::GetPadPlaneType() const
+{
+  if (fVersion == 0) return -1;  // legacy parameters
+  return int(HasPadPlane2D(fConfig));
+}
+
 //___________________________________________________________________________
 Int_t CbmTrdParModDigi::GetSector(const Double_t* local_point) const
 {
diff --git a/core/detectors/trd/CbmTrdParModDigi.h b/core/detectors/trd/CbmTrdParModDigi.h
index fdc8930515..b06329681b 100644
--- a/core/detectors/trd/CbmTrdParModDigi.h
+++ b/core/detectors/trd/CbmTrdParModDigi.h
@@ -1,10 +1,11 @@
-/* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
-   Authors: Florian Uhlig [committer], Pascal Raisig */
+   Authors: Florian Uhlig [committer], Pascal Raisig, Alexandru Bercuci*/
 
 #ifndef CBMTRDPARMODDIGI_H
 #define CBMTRDPARMODDIGI_H
 
+#include "CbmTrdDefs.h"    // for cbm::trd namespace
 #include "CbmTrdParMod.h"  // for CbmTrdParMod
 
 #include <Rtypes.h>      // for THashConsistencyHolder, ClassDef
@@ -85,6 +86,16 @@ public:
   Double_t GetX() const { return fX; }
   Double_t GetY() const { return fY; }
   Double_t GetZ() const { return fZ; }
+
+  /** \brief Access the basic type of pad plane topology. For convenience also specific accessors are added for each specific pad-plane type.
+   * \return -1 : legacy version. No info on the pad-plane
+   *          0 : 1D type
+   *          1 : 2D type
+   */
+  int GetPadPlaneType() const;
+  bool IsPadPlane1D() const { return (GetPadPlaneType() >= 0) && !bool(GetPadPlaneType()); }
+  bool IsPadPlane2D() const { return (GetPadPlaneType() >= 0) && bool(GetPadPlaneType()); }
+
   void Print(Option_t* opt = "") const;
 
   void ProjectPositionToNextAnodeWire(Double_t* local_point) const;
diff --git a/core/detectors/trd/CbmTrdParSpadic.cxx b/core/detectors/trd/CbmTrdParSpadic.cxx
index c59e6e44c3..451179690e 100644
--- a/core/detectors/trd/CbmTrdParSpadic.cxx
+++ b/core/detectors/trd/CbmTrdParSpadic.cxx
@@ -1,10 +1,10 @@
-/* Copyright (C) 2018-2020 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Florian Uhlig [committer], Pascal Raisig */
 
 #include "CbmTrdParSpadic.h"
 
-#include "CbmTrdDefs.h"  // for eCbmTrdModuleTypes, eCbmTrdModuleType...
+#include "CbmTrdDefs.h"  // for eModuleTypes1D, eCbmTrdModuleType...
 
 #include <FairParamList.h>  // for FairParamList
 #include <Logger.h>         // for Logger, LOG
@@ -133,14 +133,15 @@ std::uint8_t CbmTrdParSpadic::GetElinkId(size_t componentId, Int_t channelId)
 }
 
 // ---- GetNasicsOnModule ----------------------------------------------------
+using namespace cbm::trd;
 Int_t CbmTrdParSpadic::GetNasicsOnModule(Int_t moduleType)
 {
   switch (moduleType) {
-    case (Int_t) eCbmTrdModuleTypes::kHighChDensitySmallR: return 80; break;
-    case (Int_t) eCbmTrdModuleTypes::kLowChDensitySmallR: return 20; break;
-    case (Int_t) eCbmTrdModuleTypes::kHighChDensityLargeR: return 108; break;
-    case (Int_t) eCbmTrdModuleTypes::kLowChDensityLargeR: return 36; break;
-    case (Int_t) eCbmTrdModuleTypes::kMcbmModule:
+    case (Int_t) eModuleTypes1D::kHighChDensitySmallR: return 80; break;
+    case (Int_t) eModuleTypes1D::kLowChDensitySmallR: return 20; break;
+    case (Int_t) eModuleTypes1D::kHighChDensityLargeR: return 108; break;
+    case (Int_t) eModuleTypes1D::kLowChDensityLargeR: return 36; break;
+    case (Int_t) eModuleTypes1D::kMcbmModule:
       return 24;  // 24 is the maximum on a kMcbmModule it can also be less
       break;
     default: return 1; break;
@@ -152,11 +153,11 @@ Int_t CbmTrdParSpadic::GetNasicsPerCrob(Int_t moduleType)
 {
   Int_t nAsicsPerCrob = GetNasicsOnModule(moduleType);
   switch (moduleType) {
-    case (Int_t) eCbmTrdModuleTypes::kHighChDensitySmallR: nAsicsPerCrob /= 4; break;
-    case (Int_t) eCbmTrdModuleTypes::kLowChDensitySmallR: nAsicsPerCrob /= 1; break;
-    case (Int_t) eCbmTrdModuleTypes::kHighChDensityLargeR: nAsicsPerCrob /= 6; break;
-    case (Int_t) eCbmTrdModuleTypes::kLowChDensityLargeR: nAsicsPerCrob /= 2; break;
-    case (Int_t) eCbmTrdModuleTypes::kMcbmModule:
+    case (Int_t) eModuleTypes1D::kHighChDensitySmallR: nAsicsPerCrob /= 4; break;
+    case (Int_t) eModuleTypes1D::kLowChDensitySmallR: nAsicsPerCrob /= 1; break;
+    case (Int_t) eModuleTypes1D::kHighChDensityLargeR: nAsicsPerCrob /= 6; break;
+    case (Int_t) eModuleTypes1D::kLowChDensityLargeR: nAsicsPerCrob /= 2; break;
+    case (Int_t) eModuleTypes1D::kMcbmModule:
       nAsicsPerCrob /= 1;  // 24 is the maximum on a kMcbmModule it can also be less
       break;
     default: nAsicsPerCrob /= -1; break;
diff --git a/reco/detectors/trd/CbmTrdHitProducer.cxx b/reco/detectors/trd/CbmTrdHitProducer.cxx
index 16e55d6e30..c900451432 100644
--- a/reco/detectors/trd/CbmTrdHitProducer.cxx
+++ b/reco/detectors/trd/CbmTrdHitProducer.cxx
@@ -1,6 +1,6 @@
-/* Copyright (C) 2018-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2018-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
-   Authors: Pascal Raisig, Florian Uhlig [committer] */
+   Authors: Pascal Raisig, Florian Uhlig [committer], Alexandru Bercuci */
 
 #include "CbmTrdHitProducer.h"
 
@@ -93,13 +93,27 @@ CbmTrdModuleRec* CbmTrdHitProducer::AddModule(Int_t address, const CbmTrdParModG
   if (moduleAddress != address) {
     LOG(error) << "CbmTrdHitProducer::AddModule: Module ID " << address << " does not match geometry definition "
                << moduleAddress << ". Module init failed!";
-    return NULL;
+    return nullptr;
+  }
+  // try to load read-out parameters for module
+  const CbmTrdParModDigi* pDigi(NULL);
+  if (!fDigiPar || !(pDigi = (const CbmTrdParModDigi*) fDigiPar->GetModulePar(address))) {
+    LOG(error) << GetName() << "::AddModule : No Read-Out params for module " << address << " @ " << pg->GetTitle()
+               << ". Module init failed!";
+    return nullptr;
   }
-  LOG(info) << GetName() << "::AddModule(" << pg->GetName() << " " << (moduleType < 9 ? '1' : '2') << "D] mod["
-            << moduleAddress << "] ly[" << lyId << "] det[" << moduleAddress << "]";
+
+  // find the type of TRD detector was hit. Temporary until a new scheme of setup parameters will be but in place. TODO
+  bool trd2d(false);
+  if (pDigi->GetPadPlaneType() >= 0)
+    trd2d = pDigi->IsPadPlane2D();
+  else
+    trd2d = (moduleType >= 9);  // legacy support for old pad-plane addresing
+  LOG(info) << GetName() << "::AddModule(" << pg->GetName() << " " << (trd2d ? '2' : '1') << "D] mod[" << moduleAddress
+            << "] ly[" << lyId << "] det[" << moduleAddress << "]";
 
   CbmTrdModuleRec* module(nullptr);
-  if (moduleType >= 9) {
+  if (trd2d) {
     module = fModules[address] = new CbmTrdModuleRec2D(address);
     ((CbmTrdModuleRec2D*) module)->SetUseHelpers(CbmTrdClusterFinder::UseRecoHelpers());
     ((CbmTrdModuleRec2D*) module)->SetHitTimeOffset(fHitTimeOffset);
@@ -110,15 +124,7 @@ CbmTrdModuleRec* CbmTrdHitProducer::AddModule(Int_t address, const CbmTrdParModG
 
   // Load geometry parameters for the module
   module->SetGeoPar(pg);
-
-
-  // try to load read-out parameters for module
-  const CbmTrdParModDigi* pDigi(NULL);
-  if (!fDigiPar || !(pDigi = (const CbmTrdParModDigi*) fDigiPar->GetModulePar(address))) {
-    LOG(warn) << GetName() << "::AddModule : No Read-Out params for modAddress " << address << ". Using default.";
-  }
-  else
-    module->SetDigiPar(pDigi);
+  module->SetDigiPar(pDigi);
 
   // try to load ASIC parameters for module
   CbmTrdParModAsic* pAsic(NULL);
@@ -138,7 +144,7 @@ CbmTrdModuleRec* CbmTrdHitProducer::AddModule(Int_t address, const CbmTrdParModG
     module->SetChmbPar(pChmb);
 
   // try to load Gain parameters for module
-  if (moduleType >= 9) {
+  if (trd2d) {
     const CbmTrdParModGain* pGain(NULL);
     if (!fGainPar || !(pGain = (const CbmTrdParModGain*) fGainPar->GetModulePar(address))) {
       //LOG(warn) << GetName() << "::AddModule : No Gain params for modAddress "<< address <<". Using default.";
diff --git a/sim/detectors/trd/CbmTrdDigitizer.cxx b/sim/detectors/trd/CbmTrdDigitizer.cxx
index e3469521d8..15f0a8e0f3 100644
--- a/sim/detectors/trd/CbmTrdDigitizer.cxx
+++ b/sim/detectors/trd/CbmTrdDigitizer.cxx
@@ -1,4 +1,4 @@
-/* Copyright (C) 2009-2021 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
+/* Copyright (C) 2009-2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt
    SPDX-License-Identifier: GPL-3.0-only
    Authors: Florian Uhlig [committer], Alexandru Bercuci, Etienne Bechtel */
 
@@ -312,13 +312,26 @@ CbmTrdModuleSim* CbmTrdDigitizer::AddModule(Int_t detId)
   if (moduleAddress != detId) {
     LOG(error) << "CbmTrdDigitizer::AddModule: MC module ID " << detId << " does not match geometry definition "
                << moduleAddress << ". Module init failed!";
-    return NULL;
+    return nullptr;
   }
-  LOG(debug) << GetName() << "::AddModule[" << (moduleType < 9 ? '1' : '2') << "D] address[" << moduleAddress << "] ly["
-             << lyId << "]";
+  // try to load read-out parameters for module
+  const CbmTrdParModDigi* pDigi(NULL);
+  if (!fDigiPar || !(pDigi = (const CbmTrdParModDigi*) fDigiPar->GetModulePar(detId))) {
+    LOG(error) << GetName() << "::AddModule : No Read-Out params for module " << detId << " @ " << path
+               << ". Module init failed!";
+    return nullptr;
+  }
+
+  // find the type of TRD detector was hit. Temporary until a new scheme of setup parameters will be but in place. TODO
+  bool trd2d(false);
+  if (pDigi->GetPadPlaneType() >= 0)
+    trd2d = pDigi->IsPadPlane2D();
+  else
+    trd2d = (moduleType >= 9);  // legacy support for old pad-plane addresing
+  LOG(debug) << GetName() << "::AddModule(" << path << " " << (trd2d ? '2' : '1') << "D] mod[" << moduleAddress;
   CbmTrdModuleSim* module(NULL);
-  if (moduleType >= 9) {
-    // temporary fix for TRD-2Dh @ mCBM 2021
+  if (trd2d) {
+    // temporary fix for TRD-2Dh @ mCBM 2021 (legacy)
     if (moduleType == 10)
       SetUseFASP(kFALSE);
     else
@@ -361,6 +374,7 @@ CbmTrdModuleSim* CbmTrdDigitizer::AddModule(Int_t detId)
     module->SetMessageConverter(fConverter);
     module->SetQA(fQA);
   }
+  module->SetDigiPar(pDigi);
 
   // try to load Geometry parameters for module
   const CbmTrdParModGeo* pGeo(NULL);
@@ -371,17 +385,8 @@ CbmTrdModuleSim* CbmTrdDigitizer::AddModule(Int_t detId)
   else
     module->SetGeoPar(pGeo);
 
-  // try to load read-out parameters for module
-  const CbmTrdParModDigi* pDigi(NULL);
-  if (!fDigiPar || !(pDigi = (const CbmTrdParModDigi*) fDigiPar->GetModulePar(detId))) {
-    LOG(info) << GetName() << "::AddModule : No Read-Out params for module " << detId << " @ " << path
-              << ". Using default.";
-  }
-  else
-    module->SetDigiPar(pDigi);
-
-  // TODO check if this works also for ModuleR (moduleType < 9) modules
-  if (moduleType >= 9) {
+  // TODO check if this works also for TRD1D modules
+  if (trd2d) {
     // try to load ASIC parameters for module
     CbmTrdParModAsic* pAsic(NULL);
     if (!fAsicPar || !(pAsic = (CbmTrdParModAsic*) fAsicPar->GetModulePar(detId))) {
-- 
GitLab