From 5e700d5dc5bbcd903804710793d61d8d710e327f Mon Sep 17 00:00:00 2001
From: Lukas Chlad <chlad@ujf.cas.cz>
Date: Thu, 13 Jul 2023 12:19:21 +0000
Subject: [PATCH] Integration of FSD into CORE

Defining data structures of Forward Spectator Detector in CbmRoot.
In core/data/fsd/ the addressing scheme is defined together with Point, Digi and Hit classes.
In core/detectors/fsd/ a structure to encapsulate a detector geometry properties is defined and intialized from the corresponding .geo.root file.
At the same place, currently, an empty factory for parameter containers is present. At several other places, FSD was added in a similar fashion as PSD was used.

Increase the version numbers for the Boost and Root streamers in CbmDigiData The increase of the Root streamer version was forgotten when adding the Trd2d with commit #190d49ee. To be consistent again both version numbers are synchronised and put to 5.
---
 algo/data/CMakeLists.txt                      |   5 +
 core/CMakeLists.txt                           |   1 +
 core/base/CbmDigiManager.cxx                  |   2 +
 core/base/CbmMatchRecoToMC.cxx                |  41 ++++-
 core/base/CbmMatchRecoToMC.h                  |   6 +
 core/config/CbmConfigBase.h                   |  10 +-
 core/data/CMakeLists.txt                      |  10 +-
 core/data/CbmDataLinkDef.h                    |   8 +
 core/data/CbmDefs.cxx                         |   3 +-
 core/data/CbmDefs.h                           |   6 +-
 core/data/CbmHit.h                            |   3 +-
 core/data/CbmMCTrack.cxx                      |  11 +-
 core/data/CbmMCTrack.h                        |   3 +-
 core/data/CbmModuleList.cxx                   |   3 +-
 core/data/CbmTsEventHeader.cxx                |   1 +
 core/data/CbmTsEventHeader.h                  |   8 +
 core/data/base/CbmDigiData.h                  |   8 +-
 core/data/fsd/CbmFsdAddress.cxx               | 134 ++++++++++++++
 core/data/fsd/CbmFsdAddress.h                 | 151 +++++++++++++++
 core/data/fsd/CbmFsdDigi.cxx                  |  40 ++++
 core/data/fsd/CbmFsdDigi.h                    | 174 ++++++++++++++++++
 core/data/fsd/CbmFsdDigiData.h                |  52 ++++++
 core/data/fsd/CbmFsdHit.cxx                   |  43 +++++
 core/data/fsd/CbmFsdHit.h                     |  61 ++++++
 core/data/fsd/CbmFsdPoint.cxx                 |  46 +++++
 core/data/fsd/CbmFsdPoint.h                   |  68 +++++++
 core/detectors/fsd/CMakeLists.txt             |  27 +++
 core/detectors/fsd/CbmFsdBaseLinkDef.h        |  16 ++
 core/detectors/fsd/CbmFsdContFact.cxx         |  54 ++++++
 core/detectors/fsd/CbmFsdContFact.h           |  38 ++++
 core/detectors/fsd/CbmFsdDetectorData.h       |  23 +++
 .../fsd/CbmFsdDetectorMapManager.cxx          | 111 +++++++++++
 core/detectors/fsd/CbmFsdDetectorMapManager.h |  64 +++++++
 33 files changed, 1215 insertions(+), 16 deletions(-)
 create mode 100644 core/data/fsd/CbmFsdAddress.cxx
 create mode 100644 core/data/fsd/CbmFsdAddress.h
 create mode 100644 core/data/fsd/CbmFsdDigi.cxx
 create mode 100644 core/data/fsd/CbmFsdDigi.h
 create mode 100644 core/data/fsd/CbmFsdDigiData.h
 create mode 100644 core/data/fsd/CbmFsdHit.cxx
 create mode 100644 core/data/fsd/CbmFsdHit.h
 create mode 100644 core/data/fsd/CbmFsdPoint.cxx
 create mode 100644 core/data/fsd/CbmFsdPoint.h
 create mode 100644 core/detectors/fsd/CMakeLists.txt
 create mode 100644 core/detectors/fsd/CbmFsdBaseLinkDef.h
 create mode 100644 core/detectors/fsd/CbmFsdContFact.cxx
 create mode 100644 core/detectors/fsd/CbmFsdContFact.h
 create mode 100644 core/detectors/fsd/CbmFsdDetectorData.h
 create mode 100644 core/detectors/fsd/CbmFsdDetectorMapManager.cxx
 create mode 100644 core/detectors/fsd/CbmFsdDetectorMapManager.h

diff --git a/algo/data/CMakeLists.txt b/algo/data/CMakeLists.txt
index e684dc5462..eea39c14db 100644
--- a/algo/data/CMakeLists.txt
+++ b/algo/data/CMakeLists.txt
@@ -27,6 +27,10 @@ set(SRCS
   ${CMAKE_SOURCE_DIR}/core/data/psd/CbmPsdDigi.cxx
   ${CMAKE_SOURCE_DIR}/core/data/psd/CbmPsdAddress.cxx
 
+  ${CMAKE_SOURCE_DIR}/core/data/fsd/CbmFsdDigi.cxx
+  ${CMAKE_SOURCE_DIR}/core/data/fsd/CbmFsdAddress.cxx
+
+
   ${CMAKE_SOURCE_DIR}/core/data/raw/CriGet4Mess001.cxx
   ${CMAKE_SOURCE_DIR}/core/data/raw/StsXyterMessage.cxx
 )
@@ -43,6 +47,7 @@ target_include_directories(OnlineData
   PUBLIC ${CMAKE_SOURCE_DIR}/core/data/trd
   PUBLIC ${CMAKE_SOURCE_DIR}/core/data/tof
   PUBLIC ${CMAKE_SOURCE_DIR}/core/data/psd
+  PUBLIC ${CMAKE_SOURCE_DIR}/core/data/fsd
   PUBLIC ${CMAKE_SOURCE_DIR}/core/data/global
   PUBLIC ${CMAKE_SOURCE_DIR}/core/data/raw
 )
diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt
index f83c7f0019..7fa667426b 100644
--- a/core/CMakeLists.txt
+++ b/core/CMakeLists.txt
@@ -14,6 +14,7 @@ add_subdirectory(detectors/mvd)
 add_subdirectory(detectors/tof)
 add_subdirectory(detectors/sts)
 add_subdirectory(detectors/psd)
+add_subdirectory(detectors/fsd)
 
 If(ROOT_opengl_FOUND)
   Message(STATUS "OpenGL support found. Build the eventdisplay.")
diff --git a/core/base/CbmDigiManager.cxx b/core/base/CbmDigiManager.cxx
index 75fe067181..d47ba11247 100644
--- a/core/base/CbmDigiManager.cxx
+++ b/core/base/CbmDigiManager.cxx
@@ -11,6 +11,7 @@
 #include "CbmBmonDigi.h"          // for CbmBmonDigi
 #include "CbmDefs.h"              // for kMuch
 #include "CbmDigiBranch.h"        // for CbmDigiBranch
+#include "CbmFsdDigi.h"           // for CbmFsdDigi
 #include "CbmMuchBeamTimeDigi.h"  // for CbmMuchBeamTimeDigi
 #include "CbmMuchDigi.h"          // for CbmMuchDigi
 #include "CbmMvdDigi.h"           // for CbmMvdDigi
@@ -91,6 +92,7 @@ InitStatus CbmDigiManager::Init()
   SetBranch<CbmTrdDigi>();
   SetBranch<CbmTofDigi>();
   SetBranch<CbmPsdDigi>();
+  SetBranch<CbmFsdDigi>();
   SetBranch<CbmBmonDigi>();
   LOG(info) << "Present branches:";
   for (auto const& branch : fBranches) {
diff --git a/core/base/CbmMatchRecoToMC.cxx b/core/base/CbmMatchRecoToMC.cxx
index 3e11ab73f4..a47936a528 100644
--- a/core/base/CbmMatchRecoToMC.cxx
+++ b/core/base/CbmMatchRecoToMC.cxx
@@ -111,6 +111,11 @@ CbmMatchRecoToMC::~CbmMatchRecoToMC()
     fTofHitMatches->Delete();
     delete fTofHitMatches;
   }
+
+  if (fFsdHitMatches != nullptr) {
+    fFsdHitMatches->Delete();
+    delete fFsdHitMatches;
+  }
 }
 
 InitStatus CbmMatchRecoToMC::Init()
@@ -121,7 +126,7 @@ InitStatus CbmMatchRecoToMC::Init()
   if (fbSuppressReMatching) {
     std::stringstream msg;
     msg << "\033[1;31mCbmMatchRecoToMC (\"" << fName << "\"): the cluster and hit matching routines for MVD, STS, ";
-    msg << "MuCh, TRD, TOF will be suppressed by a request from CbmMatchRecoToMC::SuppressHitMatching():\033[0m\n";
+    msg << "MuCh, TRD, TOF, FSD will be suppressed by a request from CbmMatchRecoToMC::SuppressHitMatching():\033[0m\n";
     LOG(warn) << msg.str();
   }
 
@@ -140,6 +145,7 @@ void CbmMatchRecoToMC::Exec(Option_t* /*opt*/)
     if (fMuchClusterMatches != nullptr) fMuchClusterMatches->Delete();
     if (fMuchPixelHitMatches != nullptr) fMuchPixelHitMatches->Delete();
     if (fTofHitMatches != nullptr) fTofHitMatches->Delete();
+    if (fFsdHitMatches != nullptr) fFsdHitMatches->Delete();
   }
   if (fTrdClusterMatches != nullptr) fTrdClusterMatches->Delete();
   if (fStsTrackMatches != nullptr) fStsTrackMatches->Delete();
@@ -201,6 +207,14 @@ void CbmMatchRecoToMC::Exec(Option_t* /*opt*/)
 
   // TOF: (Digi->MC)+(Hit->Digi)=>(Hit->MC)
   if (!fbSuppressReMatching) { MatchHitsTof(fTofHitDigiMatches, fTofHits, fTofHitMatches); }
+
+  // -----   FSD   -----
+  if (!fbSuppressReMatching) {
+    // FSD: digi->hit
+    if (fFsdHits && fFsdHitMatches) { MatchHitsFsd(fFsdHits, fFsdHitMatches); }
+  }
+
+
   //static Int_t eventNo = 0;
   LOG(info) << "CbmMatchRecoToMC::Exec eventNo=" << fEventNumber++;
 }
@@ -419,6 +433,19 @@ void CbmMatchRecoToMC::ReadAndCreateDataBranches()
     else
       LOG(info) << "Found calibrated tof digi to point match vector in one of the input files";
   }
+
+  // FSD
+  fFsdPoints = mcManager->InitBranch("FsdPoint");
+
+  fFsdHits = static_cast<TClonesArray*>(ioman->GetObject("FsdHit"));
+  if (nullptr != fFsdHits) {
+    fFsdHitMatches = static_cast<TClonesArray*>(ioman->GetObject("FsdHitMatch"));
+    if (nullptr == fFsdHitMatches) {
+      fbSuppressReMatching = false;  // Ensure, that matching is done, if matches are absent
+      fFsdHitMatches       = new TClonesArray("CbmMatch", 100);
+      ioman->Register("FsdHitMatch", "FSD", fFsdHitMatches, IsOutputBranchPersistent("FsdHitMatch"));
+    }
+  }
 }
 
 
@@ -506,6 +533,18 @@ void CbmMatchRecoToMC::MatchHitsMvd(const TClonesArray* hits, TClonesArray* hitM
   }
 }
 
+void CbmMatchRecoToMC::MatchHitsFsd(const TClonesArray* hits, TClonesArray* hitMatches)
+{
+  if (!(hits && hitMatches)) return;
+  Int_t nofHits = hits->GetEntriesFast();
+  for (Int_t iHit = 0; iHit < nofHits; iHit++) {
+    CbmPixelHit* hit          = static_cast<CbmPixelHit*>(hits->At(iHit));
+    CbmMatch* hitMatch        = new ((*hitMatches)[iHit]) CbmMatch();
+    const CbmMatch* digiMatch = fDigiManager->GetMatch(ECbmModuleId::kFsd, hit->GetRefId());
+    hitMatch->AddLinks(*digiMatch);
+  }
+}
+
 void CbmMatchRecoToMC::MatchHitsTof(const TClonesArray* HitDigiMatches, const TClonesArray* hits,
                                     TClonesArray* hitMatches)
 {
diff --git a/core/base/CbmMatchRecoToMC.h b/core/base/CbmMatchRecoToMC.h
index b686757696..e76b6abafe 100644
--- a/core/base/CbmMatchRecoToMC.h
+++ b/core/base/CbmMatchRecoToMC.h
@@ -101,6 +101,8 @@ private:
 
   void MatchHitsMvd(const TClonesArray* hits, TClonesArray* hitMatches);
 
+  void MatchHitsFsd(const TClonesArray* hits, TClonesArray* hitMatches);
+
   void MatchHitsTof(const TClonesArray* HitDigiMatches, const TClonesArray* hits, TClonesArray* hitMatches);
 
   void MatchHitsToPoints(CbmMCDataArray* points, const TClonesArray* hits, TClonesArray* hitMatches);
@@ -195,6 +197,10 @@ private:
   TClonesArray* fTofHitDigiMatches           = nullptr;  //! Match Hit -> Digi [out]
   TClonesArray* fTofHitMatches               = nullptr;  //! Match Hit -> MC point [out]
 
+  // FSD
+  CbmMCDataArray* fFsdPoints   = nullptr;  //! MC points [in]
+  TClonesArray* fFsdHits       = nullptr;  //! Hits [in]
+  TClonesArray* fFsdHitMatches = nullptr;  //! Hit matches [out]
 
   CbmMatchRecoToMC(const CbmMatchRecoToMC&);
   CbmMatchRecoToMC& operator=(const CbmMatchRecoToMC&);
diff --git a/core/config/CbmConfigBase.h b/core/config/CbmConfigBase.h
index 8fb0706b55..7d09363b9e 100644
--- a/core/config/CbmConfigBase.h
+++ b/core/config/CbmConfigBase.h
@@ -117,11 +117,11 @@ public:
   static ECbmModuleId stringToECbmModuleId(std::string s)
   {
     std::map<std::string, ECbmModuleId> stringToModuleId = {
-      {"cave", ECbmModuleId::kCave},     {"magnet", ECbmModuleId::kMagnet},    {"pipe", ECbmModuleId::kPipe},
-      {"target", ECbmModuleId::kTarget}, {"mvd", ECbmModuleId::kMvd},          {"sts", ECbmModuleId::kSts},
-      {"rich", ECbmModuleId::kRich},     {"much", ECbmModuleId::kMuch},        {"trd", ECbmModuleId::kTrd},
-      {"tof", ECbmModuleId::kTof},       {"psd", ECbmModuleId::kPsd},          {"hodo", ECbmModuleId::kHodo},
-      {"shield", ECbmModuleId::kShield}, {"platform", ECbmModuleId::kPlatform}};
+      {"cave", ECbmModuleId::kCave},     {"magnet", ECbmModuleId::kMagnet}, {"pipe", ECbmModuleId::kPipe},
+      {"target", ECbmModuleId::kTarget}, {"mvd", ECbmModuleId::kMvd},       {"sts", ECbmModuleId::kSts},
+      {"rich", ECbmModuleId::kRich},     {"much", ECbmModuleId::kMuch},     {"trd", ECbmModuleId::kTrd},
+      {"tof", ECbmModuleId::kTof},       {"psd", ECbmModuleId::kPsd},       {"fsd", ECbmModuleId::kFsd},
+      {"hodo", ECbmModuleId::kHodo},     {"shield", ECbmModuleId::kShield}, {"platform", ECbmModuleId::kPlatform}};
     if (stringToModuleId.find(s) == stringToModuleId.end()) {
       LOG(error) << "CbmConfig: detector subsystem not recognized: " << s;
       std::cout << "list of available detector subsystems:\n";
diff --git a/core/data/CMakeLists.txt b/core/data/CMakeLists.txt
index 4d1ee4e36b..568015be6d 100644
--- a/core/data/CMakeLists.txt
+++ b/core/data/CMakeLists.txt
@@ -14,6 +14,7 @@ set(INCLUDE_DIRECTORIES
   ${CMAKE_CURRENT_SOURCE_DIR}/tof
   ${CMAKE_CURRENT_SOURCE_DIR}/rich
   ${CMAKE_CURRENT_SOURCE_DIR}/psd
+  ${CMAKE_CURRENT_SOURCE_DIR}/fsd
   ${CMAKE_CURRENT_SOURCE_DIR}/global
   )
 
@@ -100,6 +101,11 @@ set(SRCS
   psd/CbmPsdPoint.cxx
   psd/CbmPsdAddress.cxx
   psd/CbmPsdMCbmHit.cxx
+  
+  fsd/CbmFsdDigi.cxx
+  fsd/CbmFsdHit.cxx
+  fsd/CbmFsdPoint.cxx
+  fsd/CbmFsdAddress.cxx
 
   global/CbmGlobalTrack.cxx
   global/CbmVertex.cxx
@@ -128,7 +134,7 @@ SET_SOURCE_FILES_PROPERTIES(tof/etof/star_rhicf.c PROPERTIES COMPILE_FLAGS -Wno-
 
 list(APPEND HEADERS base/CbmDigiData.h global/CbmDigiEvent.h global/CbmDigiTimeslice.h
 bmon/CbmBmonDigiData.h sts/CbmStsDigiData.h much/CbmMuchDigiData.h rich/CbmRichDigiData.h trd/CbmTrdDigiData.h
-tof/CbmTofDigiData.h psd/CbmPsdDigiData.h)
+tof/CbmTofDigiData.h psd/CbmPsdDigiData.h fsd/CbmFsdDigiData.h)
 
 set(LIBRARY_NAME CbmData)
 set(LINKDEF ${LIBRARY_NAME}LinkDef.h)
@@ -157,6 +163,7 @@ Install(FILES
         bmon/CbmBmonDigiData.h
         much/CbmMuchDigiData.h
         psd/CbmPsdDigiData.h
+        fsd/CbmFsdDigiData.h
         rich/CbmRichDigiData.h rich/CbmRichRingLight.h
         sts/CbmStsDigiData.h
         trd/CbmTrdDigiData.h
@@ -166,4 +173,3 @@ Install(FILES
         DESTINATION include
        )
 
-
diff --git a/core/data/CbmDataLinkDef.h b/core/data/CbmDataLinkDef.h
index 67b82b4b7c..4c0a08a60d 100644
--- a/core/data/CbmDataLinkDef.h
+++ b/core/data/CbmDataLinkDef.h
@@ -99,6 +99,12 @@
 #pragma link C++ class CbmPsdAddress;
 #pragma link C++ class CbmPsdMCbmHit;
 
+#pragma link C++ class CbmFsdDigi + ;
+#pragma link C++ class CbmFsdDigiData + ;
+#pragma link C++ class CbmFsdHit + ;
+#pragma link C++ class CbmFsdPoint + ;
+#pragma link C++ class CbmFsdAddress + ;
+
 // --- data/global
 #pragma link C++ class CbmGlobalTrack + ;
 #pragma link C++ class CbmVertex + ;
@@ -134,6 +140,7 @@
 #pragma link C++ class vector < CbmBmonDigi> + ;
 #pragma link C++ class vector < CbmPsdDigi> + ;
 #pragma link C++ class vector < CbmPsdDsp> + ;
+#pragma link C++ class vector < CbmFsdDigi> + ;
 #pragma link C++ class vector < CbmMatch> + ;
 #pragma link C++ class CbmDigiVector < CbmMvdDigi> + ;
 #pragma link C++ class CbmDigiVector < CbmStsDigi> + ;
@@ -144,6 +151,7 @@
 #pragma link C++ class CbmDigiVector < CbmTofDigi> + ;
 #pragma link C++ class CbmDigiVector < CbmPsdDigi> + ;
 #pragma link C++ class CbmDigiVector < CbmPsdDsp> + ;
+#pragma link C++ class CbmDigiVector < CbmFsdDigi> + ;
 #pragma link C++ class vector < CbmEventStore> + ;
 
 #pragma link C++ class std::vector < CbmEvent> + ;
diff --git a/core/data/CbmDefs.cxx b/core/data/CbmDefs.cxx
index d5e6ec3e53..6e37c66c85 100644
--- a/core/data/CbmDefs.cxx
+++ b/core/data/CbmDefs.cxx
@@ -41,7 +41,7 @@ std::ostream& operator<<(std::ostream& strm, const ECbmModuleId& modId)
 }
 
 // conversion functions between ECbmModuleId and std::string
-static const std::array<std::pair<ECbmModuleId, std::string>, 22> ModIdStrMap = {
+static const std::array<std::pair<ECbmModuleId, std::string>, 23> ModIdStrMap = {
   {{ECbmModuleId::kRef, "Ref"},
    {ECbmModuleId::kMvd, "Mvd"},
    {ECbmModuleId::kSts, "Sts"},
@@ -55,6 +55,7 @@ static const std::array<std::pair<ECbmModuleId, std::string>, 22> ModIdStrMap =
    {ECbmModuleId::kDummyDet, "DummyDet"},
    {ECbmModuleId::kT0, "T0"},
    {ECbmModuleId::kTrd2d, "Trd2d"},
+   {ECbmModuleId::kFsd, "Fsd"},
    {ECbmModuleId::kNofSystems, "NofSystems"},
    {ECbmModuleId::kMagnet, "Magnet"},
    {ECbmModuleId::kTarget, "Target"},
diff --git a/core/data/CbmDefs.h b/core/data/CbmDefs.h
index 64ddc7fcbf..e77d04ccaf 100644
--- a/core/data/CbmDefs.h
+++ b/core/data/CbmDefs.h
@@ -50,7 +50,8 @@ enum class ECbmModuleId
   kDummyDet   = 10,  ///< Dummy for tutorials or tests
   kT0         = 11,  ///< ToF start Detector (FIXME)
   kTrd2d      = 12,  ///< TRD-FASP Detector  (FIXME)
-  kNofSystems = 13,  ///< For loops over active systems
+  kFsd        = 13,  ///< Forward spectator detector
+  kNofSystems = 14,  ///< For loops over active systems
   kMagnet     = 17,  ///< Magnet
   kTarget     = 18,  ///< Target
   kPipe       = 19,  ///< Beam pipe
@@ -126,6 +127,9 @@ enum class ECbmDataType
   kT0Digi,
   kT0CalDigi,
   kT0Hit,              // T0
+  kFsdPoint = ToIntegralType(ECbmModuleId::kFsd) * 100,
+  kFsdDigi,
+  kFsdHit,             // Fsd
   kGlobalTrack = 2000  // Global
 };
 
diff --git a/core/data/CbmHit.h b/core/data/CbmHit.h
index da47e229b3..7fc5ca610c 100644
--- a/core/data/CbmHit.h
+++ b/core/data/CbmHit.h
@@ -29,7 +29,8 @@ enum HitType
   kMUCHSTRAWHIT,
   kTRDHIT,
   kTOFHIT,
-  kECALHIT
+  kECALHIT,
+  kFSDHIT
 };
 
 #include <Rtypes.h>  // for THashConsistencyHolder, ClassDef
diff --git a/core/data/CbmMCTrack.cxx b/core/data/CbmMCTrack.cxx
index 40066d4cca..06cfeeb674 100644
--- a/core/data/CbmMCTrack.cxx
+++ b/core/data/CbmMCTrack.cxx
@@ -213,6 +213,8 @@ int32_t CbmMCTrack::GetNPoints(ECbmModuleId detId) const
     return ((fNPoints & (1 << 24)) >> 24);
   else if (detId == ECbmModuleId::kPsd)
     return ((fNPoints & (1 << 25)) >> 25);
+  else if (detId == ECbmModuleId::kFsd)
+    return ((fNPoints & (1 << 26)) >> 26);
   else {
     LOG(error) << "GetNPoints: Unknown detector ID " << detId;
     return 0;
@@ -288,6 +290,13 @@ void CbmMCTrack::SetNPoints(ECbmModuleId iDet, int32_t nPoints)
     fNPoints = (fNPoints & (~(1 << 25))) | (nPoints << 25);
   }
 
+  else if (iDet == ECbmModuleId::kFsd) {
+    if (nPoints < 0) nPoints = 0;
+    else if (nPoints > 1)
+      nPoints = 1;
+    fNPoints = (fNPoints & (~(1 << 26))) | (nPoints << 26);
+  }
+
   else
     LOG(error) << "Unknown detector ID " << iDet;
 }
@@ -304,7 +313,7 @@ std::string CbmMCTrack::ToString() const
      << GetNPoints(ECbmModuleId::kSts) << ", RICH " << GetNPoints(ECbmModuleId::kRich) << ", MUCH "
      << GetNPoints(ECbmModuleId::kMuch) << ", TRD " << GetNPoints(ECbmModuleId::kTrd) << ", TOF "
      << GetNPoints(ECbmModuleId::kTof) << ", ECAL " << GetNPoints(ECbmModuleId::kEcal) << ", PSD "
-     << GetNPoints(ECbmModuleId::kPsd) << std::endl;
+     << GetNPoints(ECbmModuleId::kPsd) << ", FSD " << GetNPoints(ECbmModuleId::kFsd) << std::endl;
   return ss.str();
 }
 // -------------------------------------------------------------------------
diff --git a/core/data/CbmMCTrack.h b/core/data/CbmMCTrack.h
index d7c7ca95a0..5ac230f11e 100644
--- a/core/data/CbmMCTrack.h
+++ b/core/data/CbmMCTrack.h
@@ -145,9 +145,10 @@ private:
    **  TOF:         Bit 20 - 23 (4 bits, max. value 15)
    **  ECAL:        Bit 24      (1 bit,  max. value  1)
    **  ZDC:         Bit 25      (1 bit,  max. value  1)
+   **  FSD:         Bit 26      (1 bit,  max. value  1)
    **  The respective point numbers can be accessed and modified 
    **  with the inline functions. 
-   **  Bits 26-31 are spare for potential additional detectors.
+   **  Bits 27-31 are spare for potential additional detectors.
    **/
   int32_t fNPoints;
 
diff --git a/core/data/CbmModuleList.cxx b/core/data/CbmModuleList.cxx
index 7f0cbf82af..de8ff14260 100644
--- a/core/data/CbmModuleList.cxx
+++ b/core/data/CbmModuleList.cxx
@@ -29,10 +29,11 @@ map<ECbmModuleId, TString> CbmModuleList::DefineModules()
   data[ECbmModuleId::kTrd]      = "trd";
   data[ECbmModuleId::kTof]      = "tof";
   data[ECbmModuleId::kEcal]     = "ecal";
-  data[ECbmModuleId::kPsd]      = "psd";
+  data[ECbmModuleId::kFsd]      = "fsd";
   data[ECbmModuleId::kHodo]     = "hodo";
   data[ECbmModuleId::kDummyDet] = "dummy";
   data[ECbmModuleId::kT0]       = "t0";
+  data[ECbmModuleId::kPsd]      = "psd";
   data[ECbmModuleId::kMagnet]   = "magnet";
   data[ECbmModuleId::kTarget]   = "target";
   data[ECbmModuleId::kPipe]     = "pipe";
diff --git a/core/data/CbmTsEventHeader.cxx b/core/data/CbmTsEventHeader.cxx
index 524f238456..75439e6103 100644
--- a/core/data/CbmTsEventHeader.cxx
+++ b/core/data/CbmTsEventHeader.cxx
@@ -15,6 +15,7 @@ void CbmTsEventHeader::Reset()
   // Reset the digi counters
   fNDigisMuch  = 0;
   fNDigisPsd   = 0;
+  fNDigisFsd   = 0;
   fNDigisRich  = 0;
   fNDigisSts   = 0;
   fNDigisTof   = 0;
diff --git a/core/data/CbmTsEventHeader.h b/core/data/CbmTsEventHeader.h
index d77d7343d5..6cbb3c8e82 100644
--- a/core/data/CbmTsEventHeader.h
+++ b/core/data/CbmTsEventHeader.h
@@ -24,6 +24,8 @@ public:
   /** @brief Add a number of digis from this Ts */
   void AddNDigisPsd(uint64_t value) { fNDigisPsd += value; }
   /** @brief Add a number of digis from this Ts */
+  void AddNDigisFsd(uint64_t value) { fNDigisFsd += value; }
+  /** @brief Add a number of digis from this Ts */
   void AddNDigisRich(uint64_t value) { fNDigisRich += value; }
   /** @brief Add a number of digis from this Ts */
   void AddNDigisSts(uint64_t value) { fNDigisSts += value; }
@@ -41,6 +43,8 @@ public:
   /** @brief Get the number of digis in this Ts */
   uint64_t GetNDigisPsd() const { return fNDigisPsd; }
   /** @brief Get the number of digis in this Ts */
+  uint64_t GetNDigisFsd() const { return fNDigisFsd; }
+  /** @brief Get the number of digis in this Ts */
   uint64_t GetNDigisRich() const { return fNDigisRich; }
   /** @brief Get the number of digis in this Ts */
   uint64_t GetNDigisSts() const { return fNDigisSts; }
@@ -66,6 +70,8 @@ public:
   /** @brief Set the number of digis in this Ts */
   void SetNDigisPsd(uint64_t value) { fNDigisPsd = value; }
   /** @brief Set the number of digis in this Ts */
+  void SetNDigisFsd(uint64_t value) { fNDigisFsd = value; }
+  /** @brief Set the number of digis in this Ts */
   void SetNDigisRich(uint64_t value) { fNDigisRich = value; }
   /** @brief Set the number of digis in this Ts */
   void SetNDigisSts(uint64_t value) { fNDigisSts = value; }
@@ -97,6 +103,8 @@ protected:
   uint64_t fNDigisMuch = 0;
   /** @brief nDigis in "this" timeslice measured by the PSD */
   uint64_t fNDigisPsd = 0;
+  /** @brief nDigis in "this" timeslice measured by the FSD */
+  uint64_t fNDigisFsd = 0;
   /** @brief nDigis in "this" timeslice measured by the RICH */
   uint64_t fNDigisRich = 0;
   /** @brief nDigis in "this" timeslice measured by the STS */
diff --git a/core/data/base/CbmDigiData.h b/core/data/base/CbmDigiData.h
index d44185d8de..36282ed401 100644
--- a/core/data/base/CbmDigiData.h
+++ b/core/data/base/CbmDigiData.h
@@ -7,6 +7,7 @@
 #define CBMDIGIDATA_H 1
 
 #include "CbmBmonDigiData.h"
+#include "CbmFsdDigiData.h"
 #include "CbmMuchDigiData.h"
 #include "CbmPsdDigiData.h"
 #include "CbmRichDigiData.h"
@@ -39,6 +40,7 @@ public:
   CbmTrdDigiData fTrd2d;  ///< TRD2D data
   CbmTofDigiData fTof;    ///< TOF data
   CbmPsdDigiData fPsd;    ///< PSD data
+  CbmFsdDigiData fFsd;    ///< FSD data
 
   friend class boost::serialization::access;
   /** @brief BOOST serializer**/
@@ -53,12 +55,13 @@ public:
     ar& fTrd2d;
     ar& fTof;
     ar& fPsd;
+    ar& fFsd;
     ar& fRich;
   }
 
   // --- ROOT serializer
 #ifndef NO_ROOT
-  ClassDefNV(CbmDigiData, 3);
+  ClassDefNV(CbmDigiData, 5);
 #endif
 
   /** @brief Clear content **/
@@ -71,9 +74,10 @@ public:
     fTrd2d.Clear();
     fTof.Clear();
     fPsd.Clear();
+    fFsd.Clear();
     fRich.Clear();
   }
 };
 
-BOOST_CLASS_VERSION(CbmDigiData, 4)
+BOOST_CLASS_VERSION(CbmDigiData, 5)
 #endif /* CBMDIGIDATA_H */
diff --git a/core/data/fsd/CbmFsdAddress.cxx b/core/data/fsd/CbmFsdAddress.cxx
new file mode 100644
index 0000000000..2e00ae4c02
--- /dev/null
+++ b/core/data/fsd/CbmFsdAddress.cxx
@@ -0,0 +1,134 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese, Andrey Lebedev, Lukas Chlad [committer] */
+
+/** @file CbmFsdAddress.cxx
+ ** @author Lukas Chlad <l.chlad@gsi.de>
+ ** @date 16.06.2023
+ **
+ ** Inspired by CbmStsAddress and only accomodate physical properties of expected FSD detector
+ **
+ **/
+
+#include "CbmFsdAddress.h"
+
+#include "CbmDefs.h"  // for kFsd
+
+#include <cassert>  // for assert
+#include <sstream>  // for operator<<, basic_ostream, stringstream
+
+#include "AlgoFairloggerCompat.h"  // for Logger, LOG
+
+// -----   Construct address from element Ids   ------------------------------
+int32_t CbmFsdAddress::GetAddress(uint32_t Unit, uint32_t Module, uint32_t PhotoDet, uint32_t Version)
+{
+  using namespace Detail;
+
+  assert(Version <= kCurrentVersion);
+
+  // Catch overrun of allowed ranges
+  if (Unit > static_cast<uint32_t>(kMask[Version][static_cast<int32_t>(CbmFsdAddress::Level::Unit)])) {
+    LOG(error) << "Unit Id " << Unit << " exceeds maximum "
+               << kMask[Version][static_cast<int32_t>(CbmFsdAddress::Level::Unit)];
+    return 0;
+  }
+  if (Module > static_cast<uint32_t>(kMask[Version][static_cast<int32_t>(CbmFsdAddress::Level::Module)])) {
+    LOG(error) << "Module Id " << Module << " exceeds maximum "
+               << kMask[Version][static_cast<int32_t>(CbmFsdAddress::Level::Module)];
+    return 0;
+  }
+  if (PhotoDet > static_cast<uint32_t>(kMask[Version][static_cast<int32_t>(CbmFsdAddress::Level::PhotoDet)])) {
+    LOG(error) << "PhotoDetector Id " << PhotoDet << " exceeds maximum "
+               << kMask[Version][static_cast<int32_t>(CbmFsdAddress::Level::PhotoDet)];
+    return 0;
+  }
+
+  return ToIntegralType(ECbmModuleId::kFsd) << kShift[Version][static_cast<uint32_t>(CbmFsdAddress::Level::System)]
+         | Unit << kShift[Version][static_cast<int32_t>(CbmFsdAddress::Level::Unit)]
+         | Module << kShift[Version][static_cast<int32_t>(CbmFsdAddress::Level::Module)]
+         | PhotoDet << kShift[Version][static_cast<int32_t>(CbmFsdAddress::Level::PhotoDet)] | Version << kVersionShift;
+}
+// ---------------------------------------------------------------------------
+
+
+// -----   Construct address from address of descendant element   ------------
+int32_t CbmFsdAddress::GetMotherAddress(int32_t address, int32_t level)
+{
+  using namespace Detail;
+  if (!(level >= static_cast<int32_t>(CbmFsdAddress::Level::System)
+        && level < static_cast<int32_t>(CbmFsdAddress::Level::NumLevels))) {
+    throw std::out_of_range("CbmFsdAddress: Illegal element level" + level);
+    return 0;
+  }
+  if (level == static_cast<uint32_t>(CbmFsdAddress::Level::NumLevels) - 1) return address;
+  uint32_t version  = GetVersion(address);
+  int32_t motherAdd = (address & ((1 << kShift[version][level + 1]) - 1));
+  motherAdd         = motherAdd | (version << kVersionShift);
+  return motherAdd;
+}
+// ---------------------------------------------------------------------------
+
+
+// -----   Get the index of an element   -------------------------------------
+uint32_t CbmFsdAddress::GetElementId(int32_t address, int32_t level)
+{
+  using namespace Detail;
+  if (!(level >= static_cast<int32_t>(CbmFsdAddress::Level::System)
+        && level < static_cast<int32_t>(CbmFsdAddress::Level::NumLevels))) {
+    throw std::out_of_range("CbmFsdAddress: Illegal element level" + level);
+    return 0;
+  }
+  uint32_t version = GetVersion(address);
+  return (address & (kMask[version][level] << kShift[version][level])) >> kShift[version][level];
+}
+// ---------------------------------------------------------------------------
+
+
+// -----   Get System ID   ---------------------------------------------------
+uint32_t CbmFsdAddress::GetSystemId(int32_t address)
+{
+  return GetElementId(address, static_cast<uint32_t>(CbmFsdAddress::Level::System));
+}
+// ---------------------------------------------------------------------------
+
+
+// -----   Get the version number from the address   -------------------------
+uint32_t CbmFsdAddress::GetVersion(int32_t address)
+{
+  return uint32_t((address & (kVersionMask << kVersionShift)) >> kVersionShift);
+}
+// ---------------------------------------------------------------------------
+
+
+// -----  Construct address by changing the index of an element   ------------
+int32_t CbmFsdAddress::SetElementId(int32_t address, int32_t level, uint32_t newId)
+{
+  using namespace Detail;
+  if (!(level >= static_cast<int32_t>(CbmFsdAddress::Level::System)
+        && level < static_cast<int32_t>(CbmFsdAddress::Level::NumLevels))) {
+    throw std::out_of_range("CbmFsdAddress: Illegal element level" + level);
+    return 0;
+  }
+  uint32_t version = GetVersion(address);
+  uint32_t maxId   = (1 << kBits[version][level]) - 1;
+  if (newId > maxId) {
+    LOG(fatal) << "Id " << newId << " for FSD level " << level << " exceeds maximum " << maxId;
+    return 0;
+  }
+  return (address & (~(kMask[version][level] << kShift[version][level]))) | (newId << kShift[version][level]);
+}
+// -------------------------------------------------------------------------
+
+// -----   String output   -------------------------------------------------
+std::string CbmFsdAddress::ToString(int32_t address)
+{
+  std::stringstream ss;
+
+  ss << "FsdAddress: address " << address << " (version " << GetVersion(address) << ")"
+     << ": system " << GetElementId(address, static_cast<int32_t>(CbmFsdAddress::Level::System)) << ", unit "
+     << GetElementId(address, static_cast<int32_t>(CbmFsdAddress::Level::Unit)) << ", module "
+     << GetElementId(address, static_cast<int32_t>(CbmFsdAddress::Level::Module)) << ", photo detector "
+     << GetElementId(address, static_cast<int32_t>(CbmFsdAddress::Level::PhotoDet));
+  return ss.str();
+}
+// -------------------------------------------------------------------------
diff --git a/core/data/fsd/CbmFsdAddress.h b/core/data/fsd/CbmFsdAddress.h
new file mode 100644
index 0000000000..ffae9d59d1
--- /dev/null
+++ b/core/data/fsd/CbmFsdAddress.h
@@ -0,0 +1,151 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese, Andrey Lebedev, Lukas Chlad [committer] */
+
+/** @file CbmFsdAddress.h
+ ** @author Lukas Chlad <l.chlad@gsi.de>
+ ** @date 16.06.2023
+ **
+ ** Inspired by CbmStsAddress and only accomodate physical properties of expected FSD detector
+ **
+ **/
+
+#ifndef CBMFSDADDRESS_H
+#define CBMFSDADDRESS_H 1
+
+#include "CbmDefs.h"  // for ECbmModuleId
+
+#include <cassert>  // for assert
+#include <cstdint>  // for uint32_t
+#include <sstream>  // for string
+
+/** Namespace CbmFsdAddress
+ ** @brief Functions to encode or decode the address field of FSD data.
+ ** @author Lukas Chlad <l.chlad@gsi.de>
+ **
+ ** Inspired by the structure used by STS.
+ ** The current definition (version 0) of the address bit field for the FSD is:
+ **
+ ** Level           Bits  Max. Elements  Bit Position
+ ** System (kFSD)     4         16          0 -  3
+ ** Unit              4         16          4 -  7
+ ** Module           15      32768          8 - 22
+ ** PhotoDetector     2          4         23 - 24
+ ** Unused            3                    25 - 27
+ ** Version           4         16         28 - 31
+ **/
+namespace CbmFsdAddress
+{
+  /** Enumerator for the hierarchy levels of the FSD setup **/
+  enum class Level
+  {
+    System,
+    Unit,
+    Module,
+    PhotoDet,
+    NumLevels
+  };
+
+  inline constexpr uint32_t kCurrentVersion = 0;
+
+  // --- These values are not to be changed if backward compatibility
+  // --- shall be maintained.
+  inline constexpr int32_t kVersionSize  = 4;   // Bits for version number
+  inline constexpr int32_t kVersionShift = 28;  // First bit for version number
+  inline constexpr int32_t kVersionMask  = (1 << kVersionSize) - 1;
+
+  namespace Detail
+  {
+    // clang-format off
+    // -----    Definition of address bit field   ------------------------------
+    inline constexpr uint16_t kBits[kCurrentVersion + 1][static_cast<uint32_t>(CbmFsdAddress::Level::NumLevels)] = {
+
+      // Version 0
+      {
+        4,  // system
+        4,  // unit 
+       15,  // module
+        2   // photodet
+      }
+
+    };
+    // -------------------------------------------------------------------------
+
+    // -----    Bit shifts -----------------------------------------------------
+    inline constexpr int32_t kShift[kCurrentVersion + 1][static_cast<uint32_t>(CbmFsdAddress::Level::NumLevels)] = {
+      {0, kShift[0][0] + kBits[0][0], kShift[0][1] + kBits[0][1], kShift[0][2] + kBits[0][2]}
+    };
+    // -------------------------------------------------------------------------
+
+    // -----    Bit masks  -----------------------------------------------------
+    inline constexpr int32_t kMask[kCurrentVersion + 1][static_cast<uint32_t>(CbmFsdAddress::Level::NumLevels)] = {
+      {(1 << kBits[0][0]) - 1, (1 << kBits[0][1]) - 1, (1 << kBits[0][2]) - 1, (1 << kBits[0][3]) - 1}
+    };
+    // -------------------------------------------------------------------------
+    // clang-format on
+  }  // Namespace Detail
+
+
+  /** @brief Construct address
+   ** @param unit         Unit index
+   ** @param module       Module index in unit
+   ** @param photodet     PhotoDetector index in module
+   ** @return Unique element address
+   **/
+  int32_t GetAddress(uint32_t Unit = 0, uint32_t Module = 0, uint32_t PhotoDet = 0, uint32_t Version = kCurrentVersion);
+
+
+  /** @brief Construct the address of an element from the address of a
+   ** descendant element.
+   ** @param address Address of descendant element
+   ** @param level   Desired hierarchy level
+   ** @return Address of element at desired hierarchy level
+   **
+   ** This strips of the address information of all hierarchy levels
+   ** below the desired one.
+   **/
+  int32_t GetMotherAddress(int32_t address, int32_t level);
+
+
+  /** @brief Get the index of an element
+   ** @param address Unique element address
+   ** @param level Hierarchy level
+   ** @return Element index
+   **/
+  uint32_t GetElementId(int32_t address, int32_t level);
+
+
+  /** @brief Get system Id (should be integer value of ECbmModuleId::kFsd)
+   ** @param address Unique element address
+   **/
+  uint32_t GetSystemId(int32_t address);
+
+
+  /** @brief Extract version number
+   ** @param address Unique element address
+   ** @value Version number
+   **
+   ** The version is encoded in the last 4 bits (28 to 31).
+   ** The maximal number of versions is 16.
+   **/
+  uint32_t GetVersion(int32_t address);
+
+
+  /** @brief Set the index of an element, leaving the other element levels
+   ** untouched
+   ** @param address Unique element address
+   ** @param level   Hierarchy level
+   ** @param newId   New element index
+   ** @return New address
+   **/
+  int32_t SetElementId(int32_t address, int32_t level, uint32_t newId);
+
+  /** @brief String output
+   ** @param address Unique element address
+   **/
+  std::string ToString(int32_t address);
+
+}  // Namespace CbmFsdAddress
+
+
+#endif  // CBMFSDADDRESS_H
diff --git a/core/data/fsd/CbmFsdDigi.cxx b/core/data/fsd/CbmFsdDigi.cxx
new file mode 100644
index 0000000000..d090b41b37
--- /dev/null
+++ b/core/data/fsd/CbmFsdDigi.cxx
@@ -0,0 +1,40 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese, Florian Uhlig, Lukas Chlad [committer] */
+
+/** @file CbmFsdDigi.cxx
+ ** @author Lukas Chlad <l.chlad@gsi.de>
+ ** @date 15.06.2023
+ **
+ ** Code for Data class for FSD digital information
+ **/
+
+#include "CbmFsdDigi.h"
+
+#include <iomanip>  // for hex, setw, setfill, fixed, setprecission
+#include <sstream>  // for operator<<, basic_ostream, char_trait
+#include <string>   // for basic_string
+
+// --- Set address from module and section number
+// --- version in CbmFsdAddress is taken the latest
+void CbmFsdDigi::SetAddress(uint32_t unitId, uint32_t moduleId, uint32_t photodetId)
+{
+  fAddress = CbmFsdAddress::GetAddress(unitId, moduleId, photodetId);
+}
+
+
+// --- Info to string
+std::string CbmFsdDigi::ToString() const
+{
+  // Example output
+  // CbmFsdDigi: address = 0x00001018 Charge = 0.011590 Time = 1006.438294
+
+  std::stringstream ss;
+  ss << "CbmFsdDigi: address = 0x" << std::uppercase << std::hex << std::setw(8) << std::setfill('0') << fAddress
+     << " Charge = " << std::fixed << std::setprecision(6) << fEdep << " Time = " << fTime;
+  return ss.str();
+}
+
+#ifndef NO_ROOT
+ClassImp(CbmFsdDigi)
+#endif
diff --git a/core/data/fsd/CbmFsdDigi.h b/core/data/fsd/CbmFsdDigi.h
new file mode 100644
index 0000000000..42fc8bb5db
--- /dev/null
+++ b/core/data/fsd/CbmFsdDigi.h
@@ -0,0 +1,174 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese, Pierre-Alain Loizeau, Lukas Chlad [committer] */
+
+/** \file CbmFsdDigi.h
+ ** \author Lukas Chlad <l.chlad@gsi.de>
+ ** \date 15.06.2023
+ **/
+
+/** \class CbmFsdDigi
+ ** \brief Data class for FSD digital information
+ ** \version 1
+ **
+ ** Unique Address:        32 bits following CbmFsdAddress
+ ** Time:                  64 bits double
+ ** Energy deposition:     64 bits double
+ **/
+
+#ifndef CBMFSDDIGI_H
+#define CBMFSDDIGI_H 1
+
+#include "CbmDefs.h"        // for ECbmModuleId::kFsd
+#include "CbmFsdAddress.h"  // for CbmFsdAddress
+
+#ifndef NO_ROOT
+#include <Rtypes.h>  // for ClassDefNV
+#endif
+
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/base_object.hpp>
+
+#include <cstdint>
+#include <string>  // for string
+
+
+class CbmFsdDigi {
+
+public:
+  /**@brief Default constructor.
+       **/
+  CbmFsdDigi() {}
+
+
+  /** @brief Constructor with assignment
+       ** @param address Unique channel address
+       ** @param time    Time [ns]
+       ** @param edep    Energy deposition
+       **/
+  CbmFsdDigi(uint32_t address, double time, double edep) : fAddress(address), fTime(time), fEdep(edep) {}
+
+
+  /** @brief Constructor with detailed assignment.
+       ** @param unitId        Unit Identifier
+       ** @param moduleId      Module Identifier
+       ** @param photodetId    PhotoDetector Identifier
+       ** @param time          Time [ns]
+       ** @param edep          Energy deposition
+       **/
+  CbmFsdDigi(uint32_t unitId, uint32_t moduleId, uint32_t photodetId, double time, double edep)
+    : fAddress(CbmFsdAddress::GetAddress(unitId, moduleId, photodetId))
+    , fTime(time)
+    , fEdep(edep)
+  {
+  }
+
+
+  /** Destructor **/
+  ~CbmFsdDigi() {}
+
+
+  /** @brief Class name (static)
+       ** @return CbmFsdDigi
+       **/
+  static const char* GetClassName() { return "CbmFsdDigi"; }
+
+
+  /** @brief Address
+       ** @return Unique channel address (see CbmFsdAddress)
+       **/
+  uint32_t GetAddress() const { return fAddress; };
+
+
+  /** @brief Get the desired name of the branch for this obj in the cbm output tree  (static)
+   ** @return "FsdDigi"
+   **/
+  static const char* GetBranchName() { return "FsdDigi"; }
+
+
+  /** @brief Time
+       ** @return Time [ns]
+       **/
+  double GetTime() const { return fTime; };
+
+
+  /** @brief Charge
+       ** @return Charge (energy deposition)
+       **
+       ** Alias for GetEdep(), for compatibility with template methods
+       */
+  double GetCharge() const { return fEdep; };
+
+
+  /** @brief Energy deposit
+       ** @return Energy deposit
+       **/
+  double GetEdep() const { return fEdep; };
+
+
+  /** @brief Module Identifier
+       ** @return Module number
+       **/
+  double GetModuleID() const
+  {
+    return CbmFsdAddress::GetElementId(GetAddress(), static_cast<int32_t>(CbmFsdAddress::Level::Module));
+  }
+
+
+  /** @brief Unit Identifier
+       ** @return Unit number
+       **/
+  double GetUnitID() const
+  {
+    return CbmFsdAddress::GetElementId(GetAddress(), static_cast<int32_t>(CbmFsdAddress::Level::Unit));
+  }
+
+
+  /** @brief PhotoDet Identifier
+       ** @return PhotoDet number
+       **/
+  double GetPhotoDetID() const
+  {
+    return CbmFsdAddress::GetElementId(GetAddress(), static_cast<int32_t>(CbmFsdAddress::Level::PhotoDet));
+  }
+
+  /** @brief System identifier
+       ** @return System ID (ECbmModuleId)
+       **/
+  static ECbmModuleId GetSystem() { return ECbmModuleId::kFsd; }
+
+
+  /** Modifiers **/
+  void SetAddress(uint32_t address) { fAddress = address; };
+  void SetAddress(uint32_t unitId, uint32_t moduleId, uint32_t photodetId);
+  void SetTime(double time) { fTime = time; }
+  void SetEdep(double edep) { fEdep = edep; }
+
+
+  /** @brief String output
+       ** @return Info
+       **/
+  std::string ToString() const;
+
+
+private:
+  uint32_t fAddress = 0;    /// Unique channel address
+  double fTime      = -1.;  /// Time of measurement [ns]
+  double fEdep      = 0.;   /// Energy deposition from FPGA [MeV]
+
+  /// BOOST serialization interface
+  friend class boost::serialization::access;
+  template<class Archive>
+  void serialize(Archive& ar, const unsigned int /*version*/)
+  {
+    ar& fAddress;
+    ar& fTime;
+    ar& fEdep;
+  }
+
+#ifndef NO_ROOT
+  ClassDefNV(CbmFsdDigi, 1);
+#endif
+};
+
+#endif  // CBMFSDDIGI_H
diff --git a/core/data/fsd/CbmFsdDigiData.h b/core/data/fsd/CbmFsdDigiData.h
new file mode 100644
index 0000000000..0c34eb8c44
--- /dev/null
+++ b/core/data/fsd/CbmFsdDigiData.h
@@ -0,0 +1,52 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese, Lukas Chlad [committer] */
+
+#ifndef CBMFSDDIGIDATA_H
+#define CBMFSDDIGIDATA_H 1
+
+
+#include "CbmFsdDigi.h"
+
+#ifndef NO_ROOT
+#include <Rtypes.h>  // for ClassDef
+#endif
+
+#include <boost/serialization/access.hpp>
+#include <boost/serialization/base_object.hpp>
+
+#include <vector>
+
+/** @class CbmFsdDigiData
+ ** @brief Container class for CbmFsdDigi objects
+ ** @author Volker Friese <v.friese@gsi.de>
+ ** @since 7.12.2022
+ ** @version 1.0
+ **
+ ** Container class for transporting CbmFsdDigi objects.
+ ** The current implementation is the simplest one: a std::vector.
+ **/
+class CbmFsdDigiData {
+
+public:
+  std::vector<CbmFsdDigi> fDigis = {};  ///< Data vector
+
+  friend class boost::serialization::access;
+
+  /** @brief BOOST serializer**/
+  template<class Archive>
+  void serialize(Archive& ar, const unsigned int /*version*/)
+  {
+    ar& fDigis;
+  }
+
+  /** @brief Clear content **/
+  void Clear() { fDigis.clear(); }
+
+  // --- ROOT serializer
+#ifndef NO_ROOT
+  ClassDefNV(CbmFsdDigiData, 1);
+#endif
+};
+
+#endif
diff --git a/core/data/fsd/CbmFsdHit.cxx b/core/data/fsd/CbmFsdHit.cxx
new file mode 100644
index 0000000000..1f6082ec61
--- /dev/null
+++ b/core/data/fsd/CbmFsdHit.cxx
@@ -0,0 +1,43 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese, Florian Uhlig, Lukas Chlad [committer] */
+
+/** CbmFsdHit.cxx
+ **@author Lukas Chlad <l.chlad@gsi.de>
+ **@since 15.06.2023
+ **
+ **/
+#include "CbmFsdHit.h"
+
+#include "CbmHit.h"  // for kFSDHIT
+
+#include <Logger.h>  // for Logger, LOG
+
+// -----   Default constructor   -------------------------------------------
+CbmFsdHit::CbmFsdHit() : CbmPixelHit(), fModuleID(-1), fEdep(-1)
+{
+  SetType(kFSDHIT);
+  SetTime(0.);
+}
+CbmFsdHit::CbmFsdHit(int32_t module, double edep) : CbmPixelHit(), fModuleID(module), fEdep(edep)
+{
+  SetType(kFSDHIT);
+  SetTime(0.);
+}
+
+
+// -----   Destructor   ----------------------------------------------------
+CbmFsdHit::~CbmFsdHit() {}
+// -------------------------------------------------------------------------
+
+void CbmFsdHit::Print(Option_t*) const { LOG(info) << ToString(); }
+
+std::string CbmFsdHit::ToString() const
+{
+  std::stringstream ss;
+  ss << "module : " << fModuleID << "position: [" << GetX() << "," << GetY() << "," << GetZ() << "] "
+     << " ELoss " << fEdep;
+  return ss.str();
+}
+
+ClassImp(CbmFsdHit)
diff --git a/core/data/fsd/CbmFsdHit.h b/core/data/fsd/CbmFsdHit.h
new file mode 100644
index 0000000000..8989a540c9
--- /dev/null
+++ b/core/data/fsd/CbmFsdHit.h
@@ -0,0 +1,61 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese, Lukas Chlad [committer] */
+
+/** CbmFsdHit.h
+ **@author Lukas Chlad <l.chlad@gsi.de>
+ **@since 15.06.2023
+ **@version 1
+ **
+ ** Data class for FSD reconstruction
+ ** Energy deposition per module
+ **
+ **/
+
+
+#ifndef CBMFSDHIT_H
+#define CBMFSDHIT_H 1
+
+#include "CbmPixelHit.h"  // for CbmPixelHit
+
+#include <Rtypes.h>  // for ClassDef
+
+#include <cstdint>
+
+class CbmFsdHit : public CbmPixelHit {
+
+public:
+  /**   Default constructor   **/
+  CbmFsdHit();
+
+  CbmFsdHit(int32_t module, double edep);
+
+
+  /**   Destructor   **/
+  virtual ~CbmFsdHit();
+
+
+  /**   Setters - Getters   **/
+
+  double GetEdep() const { return fEdep; }
+  void SetEdep(double edep) { fEdep = edep; }
+
+  int32_t GetModuleID() const { return fModuleID; }
+  void SetModuleID(int32_t mod) { fModuleID = mod; }
+
+  void Print(Option_t* = "") const;
+
+  std::string ToString() const;
+
+private:
+  /**   Data members  **/
+
+  int32_t fModuleID;
+  double fEdep;
+
+
+  ClassDef(CbmFsdHit, 1);
+};
+
+
+#endif
diff --git a/core/data/fsd/CbmFsdPoint.cxx b/core/data/fsd/CbmFsdPoint.cxx
new file mode 100644
index 0000000000..b200a6de42
--- /dev/null
+++ b/core/data/fsd/CbmFsdPoint.cxx
@@ -0,0 +1,46 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese, Florian Uhlig, Lukas Chlad [committer] */
+
+#include "CbmFsdPoint.h"
+
+#include <FairMCPoint.h>  // for FairMCPoint
+#include <Logger.h>       // for Logger, LOG
+
+#include <sstream>  // for stringstream
+
+// -----   Default constructor   -------------------------------------------
+CbmFsdPoint::CbmFsdPoint() : FairMCPoint(), fModuleID(0) {}
+// -------------------------------------------------------------------------
+
+
+// -----   Standard constructor   ------------------------------------------
+CbmFsdPoint::CbmFsdPoint(int32_t trackID, int32_t detID, TVector3 pos, TVector3 mom, double tof, double length,
+                         double eLoss)
+  : FairMCPoint(trackID, detID, pos, mom, tof, length, eLoss)
+  , fModuleID(0)
+{
+}
+// -------------------------------------------------------------------------
+
+
+// -----   Destructor   ----------------------------------------------------
+CbmFsdPoint::~CbmFsdPoint() {}
+// -------------------------------------------------------------------------
+
+
+// -----   Public method Print   -------------------------------------------
+void CbmFsdPoint::Print(const Option_t* /*opt*/) const { LOG(info) << ToString(); }
+
+std::string CbmFsdPoint::ToString() const
+{
+  std::stringstream ss;
+  ss << "Fsd point for track " << fTrackID << " in detector " << fDetectorID << "\n"
+     << "      Position (" << fX << ", " << fY << ", " << fZ << ") cm\n"
+     << "      Momentum (" << fPx << ", " << fPy << ", " << fPz << ") GeV\n"
+     << "      Time " << fTime << " ns,  Length " << fLength << " cm,  Energy loss " << fELoss * 1.0e06 << " keV";
+  return ss.str();
+}
+// -------------------------------------------------------------------------
+
+ClassImp(CbmFsdPoint)
diff --git a/core/data/fsd/CbmFsdPoint.h b/core/data/fsd/CbmFsdPoint.h
new file mode 100644
index 0000000000..329c2bb9c1
--- /dev/null
+++ b/core/data/fsd/CbmFsdPoint.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Volker Friese, Florian Uhlig, Lukas Chlad [committer] */
+
+/** @class CbmFsdPoint
+ ** @author L. Chlad
+ **
+ ** @brief Interception of MC track with the plane representing the FSD.
+ **/
+
+
+#ifndef CBMFSDPOINT_H
+#define CBMFSDPOINT_H 1
+
+#include <FairMCPoint.h>  // for FairMCPoint
+
+#include <Rtypes.h>    // for ClassDef
+#include <TVector3.h>  // for TVector3
+
+#include <cstdint>
+#include <string>  // for string
+
+class CbmFsdPoint : public FairMCPoint {
+
+public:
+  /** Default constructor **/
+  CbmFsdPoint();
+
+
+  /** Constructor with arguments
+   *@param trackID  Index of MCTrack
+   *@param detID    Detector ID
+   *@param pos      Ccoordinates at entrance to active volume [cm]
+   *@param mom      Momentum of track at entrance [GeV]
+   *@param tof      Time since event start [ns]
+   *@param length   Track length since creation [cm]
+   *@param eLoss    Energy deposit [GeV]
+   **/
+  CbmFsdPoint(int32_t trackID, int32_t detID, TVector3 pos, TVector3 mom, double tof, double length, double eLoss);
+
+
+  /** Copy constructor **/
+  //  CbmFsdPoint(const CbmFsdPoint& point) { *this = point; };
+
+
+  /** Destructor **/
+  virtual ~CbmFsdPoint();
+
+
+  /** Output to screen **/
+  virtual void Print(const Option_t* opt) const;
+
+  /** Modifiers **/
+  void SetModuleID(int32_t mod) { fModuleID = mod; }
+  /** Accessors **/
+  int32_t GetModuleID() const { return fModuleID; }
+
+  std::string ToString() const;
+
+private:
+  int32_t fModuleID;  //number of module
+
+
+  ClassDef(CbmFsdPoint, 1)
+};
+
+
+#endif
diff --git a/core/detectors/fsd/CMakeLists.txt b/core/detectors/fsd/CMakeLists.txt
new file mode 100644
index 0000000000..e3582ed7bc
--- /dev/null
+++ b/core/detectors/fsd/CMakeLists.txt
@@ -0,0 +1,27 @@
+set(INCLUDE_DIRECTORIES
+  ${CMAKE_CURRENT_SOURCE_DIR}
+  )
+
+set(SRCS
+  CbmFsdContFact.cxx
+  CbmFsdDetectorMapManager.cxx
+  )
+
+set(LIBRARY_NAME CbmFsdBase)
+set(LINKDEF ${LIBRARY_NAME}LinkDef.h)
+set(PUBLIC_DEPENDENCIES 
+  FairRoot::ParBase
+  )
+
+set(PRIVATE_DEPENDENCIES 
+  FairLogger::FairLogger 
+  ROOT::Core 
+  )
+
+generate_cbm_library()
+
+# Install file which has no corresponding source file
+install(FILES
+        CbmFsdDetectorData.h
+        DESTINATION include
+       )
diff --git a/core/detectors/fsd/CbmFsdBaseLinkDef.h b/core/detectors/fsd/CbmFsdBaseLinkDef.h
new file mode 100644
index 0000000000..26be7730a4
--- /dev/null
+++ b/core/detectors/fsd/CbmFsdBaseLinkDef.h
@@ -0,0 +1,16 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Pierre-Alain Loizeau, Florian Uhlig, Lukas Chlad [committer] */
+
+// $Id: TofLinkDef.h,v 1.3 2006/03/07 11:51:55 friese Exp $
+
+#ifdef __CINT__
+
+#pragma link off all globals;
+#pragma link off all classes;
+#pragma link off all functions;
+
+#pragma link C++ class CbmFsdContFact + ;
+#pragma link C++ class CbmFsdDetectorMapManager + ;
+
+#endif
diff --git a/core/detectors/fsd/CbmFsdContFact.cxx b/core/detectors/fsd/CbmFsdContFact.cxx
new file mode 100644
index 0000000000..550b8ebcf2
--- /dev/null
+++ b/core/detectors/fsd/CbmFsdContFact.cxx
@@ -0,0 +1,54 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Florian Uhlig, Lukas Chlad [committer] */
+
+/** CbmFsdContFact.h
+ *
+ * @author  F. Uhlig <f.uhlig@gsi.de>
+ * @version 1
+ * @since   25.01.21
+ *
+ *  Factory for the parameter containers of the FSD detector
+ *
+ */
+#include "CbmFsdContFact.h"
+
+#include <FairContFact.h>   // for FairContainer
+#include <FairRuntimeDb.h>  // for FairRuntimeDb
+#include <Logger.h>         // for LOG
+
+#include <TList.h>    // for TList
+#include <TString.h>  // for TString
+
+#include <string.h>  // for strcmp
+
+ClassImp(CbmFsdContFact)
+
+  static CbmFsdContFact gCbmFsdContFact;
+
+CbmFsdContFact::CbmFsdContFact()
+{
+  // Constructor (called when the library is loaded)
+  fName  = "CbmFsdContFact";
+  fTitle = "Factory for parameter containers in libFsdBase";
+  setAllContainers();
+  FairRuntimeDb::instance()->addContFactory(this);
+}
+
+void CbmFsdContFact::setAllContainers()
+{
+  /** Creates the Container objects with all accepted contexts and adds them to
+   *  the list of containers for the FsdBase library.*/
+}
+
+FairParSet* CbmFsdContFact::createContainer(FairContainer* c)
+{
+  /** Calls the constructor of the corresponding parameter container.
+   * For an actual context, which is not an empty string and not the default context
+   * of this container, the name is concatinated with the context. */
+  const char* name = c->GetName();
+  LOG(info) << " -I container name " << name;
+  FairParSet* p = 0;
+
+  return p;
+}
diff --git a/core/detectors/fsd/CbmFsdContFact.h b/core/detectors/fsd/CbmFsdContFact.h
new file mode 100644
index 0000000000..dbc5f34503
--- /dev/null
+++ b/core/detectors/fsd/CbmFsdContFact.h
@@ -0,0 +1,38 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Florian Uhlig, Lukas Chlad [committer] */
+
+/** CbmFsdContFact.h
+ *
+ * @author  F. Uhlig <f.uhlig@gsi.de>
+ * @version 1
+ * @since   25.01.21
+ *
+ *  Factory for the parameter containers of the FSD detector
+ *
+ */
+
+#ifndef CBMFSDCONTFACT_H
+#define CBMFSDCONTFACT_H
+
+#include <FairContFact.h>  // for FairContFact
+
+#include <Rtypes.h>  // for THashConsistencyHolder, ClassDef
+
+class FairParIo;
+class FairParSet;
+class FairContainer;
+
+class CbmFsdContFact : public FairContFact {
+public:
+  CbmFsdContFact();
+  ~CbmFsdContFact() {}
+  FairParSet* createContainer(FairContainer*);
+
+private:
+  void setAllContainers();
+
+  ClassDef(CbmFsdContFact, 0)  // Factory for all Fsd parameter containers
+};
+
+#endif /* !CBMFSDCONTFACT_H */
diff --git a/core/detectors/fsd/CbmFsdDetectorData.h b/core/detectors/fsd/CbmFsdDetectorData.h
new file mode 100644
index 0000000000..5bab1cfbae
--- /dev/null
+++ b/core/detectors/fsd/CbmFsdDetectorData.h
@@ -0,0 +1,23 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Lukas Chlad [committer] */
+
+#ifndef CBMFSDDETECTORDATA_H
+#define CBMFSDDETECTORDATA_H
+
+#include <RtypesCore.h>  // for Double_t, Int_t
+
+struct CbmFsdModuleData {
+  // module index
+  Int_t fId;
+  // module center position
+  Double_t fX;
+  Double_t fY;
+  Double_t fZ;
+  // module half-lengths
+  Double_t dX;
+  Double_t dY;
+  Double_t dZ;
+};
+
+#endif /* CBMFSDDETECTORDATA_H */
diff --git a/core/detectors/fsd/CbmFsdDetectorMapManager.cxx b/core/detectors/fsd/CbmFsdDetectorMapManager.cxx
new file mode 100644
index 0000000000..bfbed6a7e1
--- /dev/null
+++ b/core/detectors/fsd/CbmFsdDetectorMapManager.cxx
@@ -0,0 +1,111 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Lukas Chlad [committer] */
+
+#include "CbmFsdDetectorMapManager.h"
+
+#include "CbmFsdDetectorData.h"  // for CbmFsdModuleData
+
+#include <Logger.h>  // for LOG, Logger
+
+#include <TGeoBBox.h>     // for TGeoBBox
+#include <TGeoManager.h>  // for TGeoManager, gGeoManager
+#include <TGeoMatrix.h>   // for TGeoMatrix
+#include <TGeoNode.h>     // for TGeoIterator, TGeoNode
+#include <TGeoVolume.h>   // for TGeoVolume
+#include <TRandom.h>      // for TRandom, gRandom
+
+#include <string>   // for operator<, stoul
+#include <utility>  // for pair
+
+#include <stddef.h>  // for size_t
+
+using namespace std;
+
+CbmFsdDetectorMapManager::CbmFsdDetectorMapManager() : fModulePathToIdMap(), fModuleIdToDataMap(), fModuleIds()
+{
+  Init();
+}
+
+CbmFsdDetectorMapManager::~CbmFsdDetectorMapManager() {}
+
+void CbmFsdDetectorMapManager::Init()
+{
+
+  fModulePathToIdMap.clear();
+  fModuleIdToDataMap.clear();
+  fModuleIds.clear();
+
+  Int_t currentModuleId = 0;
+
+  TGeoIterator geoIterator(gGeoManager->GetTopNode()->GetVolume());
+
+  TGeoNode* curNode;
+  TString branchStr("fsd_");  // stored in path of nodes, fsd_geoTag_0
+  TString moduleStr("fsdmodule");
+  TString scintStr("scintillator");
+  geoIterator.Reset();  // safety to reset to "cave" befor the loop starts
+  while ((curNode = geoIterator())) {
+    TString nodePath;
+    geoIterator.GetPath(nodePath);
+    if (!nodePath.Contains(branchStr)) {
+      geoIterator.Skip();  // skip current branch when it is not FSD => should speed up
+      continue;            // don't do anything for this branch
+    }
+
+    TString nodeName(curNode->GetName());
+    // FSD detector -> all modules names contain "fsdmodule"
+    if (TString(curNode->GetVolume()->GetName()).Contains(moduleStr)) {
+
+      const TGeoMatrix* curMatrix = geoIterator.GetCurrentMatrix();
+      const Double_t* curNodeTr   = curMatrix->GetTranslation();
+      string path                 = string(nodePath.Data());
+
+      TGeoVolume* curScintillator = nullptr;
+      for (int idn = 0; idn < curNode->GetNdaughters(); idn++) {
+        TGeoNode* daughterNode = curNode->GetDaughter(idn);
+        if (TString(daughterNode->GetVolume()->GetName()).Contains(scintStr)) {
+          curScintillator = daughterNode->GetVolume();
+          break;
+        }
+      }
+      const TGeoBBox* shape = (const TGeoBBox*) (curScintillator->GetShape());
+
+      fModulePathToIdMap.insert(pair<string, Int_t>(path, currentModuleId));
+      CbmFsdModuleData* moduleData = new CbmFsdModuleData();
+      moduleData->fX               = curNodeTr[0];
+      moduleData->fY               = curNodeTr[1];
+      moduleData->fZ               = curNodeTr[2];
+      moduleData->dX               = shape->GetDX();
+      moduleData->dY               = shape->GetDY();
+      moduleData->dZ               = shape->GetDZ();
+      moduleData->fId              = currentModuleId;
+      fModuleIdToDataMap.insert(pair<Int_t, CbmFsdModuleData*>(moduleData->fId, moduleData));
+      fModuleIds.push_back(currentModuleId);
+      currentModuleId++;
+    }
+  }
+
+  LOG(info) << "CbmFsdDetectorMapManager is initialized";
+  LOG(info) << "fModulePathToIdMap.size() = " << fModulePathToIdMap.size();
+  LOG(info) << "fModuleIdToDataMap.size() = " << fModuleIdToDataMap.size();
+}
+
+Int_t CbmFsdDetectorMapManager::GetModuleIdByPath(const string& path)
+{
+  std::map<string, Int_t>::iterator it;
+  it = fModulePathToIdMap.find(path);
+  if (it == fModulePathToIdMap.end()) return -1;
+  return it->second;
+}
+
+
+CbmFsdModuleData* CbmFsdDetectorMapManager::GetModuleDataById(Int_t modId)
+{
+  std::map<Int_t, CbmFsdModuleData*>::iterator it;
+  it = fModuleIdToDataMap.find(modId);
+  if (it == fModuleIdToDataMap.end()) return nullptr;
+  return it->second;
+}
+
+vector<Int_t> CbmFsdDetectorMapManager::GetModuleIds() { return fModuleIds; }
diff --git a/core/detectors/fsd/CbmFsdDetectorMapManager.h b/core/detectors/fsd/CbmFsdDetectorMapManager.h
new file mode 100644
index 0000000000..5afe83850a
--- /dev/null
+++ b/core/detectors/fsd/CbmFsdDetectorMapManager.h
@@ -0,0 +1,64 @@
+/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen
+   SPDX-License-Identifier: GPL-3.0-only
+   Authors: Lukas Chlad [committer] */
+
+#ifndef CBMFSDDETECTORMAPMANAGER_H
+#define CBMFSDDETECTORMAPMANAGER_H
+
+#include <RtypesCore.h>  // for Int_t, Double_t
+
+#include <iostream>  // for string
+#include <map>       // for map
+#include <vector>    // for vector
+
+struct CbmFsdModuleData;
+
+class CbmFsdDetectorMapManager {
+
+private:
+  /** Default constructor **/
+  CbmFsdDetectorMapManager();
+
+  /** Default destructor **/
+  ~CbmFsdDetectorMapManager();
+
+public:
+  CbmFsdDetectorMapManager(const CbmFsdDetectorMapManager&) = delete;
+  CbmFsdDetectorMapManager& operator=(const CbmFsdDetectorMapManager&) = delete;
+
+  /**
+	 * Return Instance of CbmFsdDetectorMapManager.
+	 */
+  static CbmFsdDetectorMapManager& GetInstance()
+  {
+    static CbmFsdDetectorMapManager fInstance;
+    return fInstance;
+  }
+
+  /*
+	 * \brief Return digi moduleId by path to node.
+	 */
+  Int_t GetModuleIdByPath(const std::string& path);
+
+  /*
+	 * \brief Return CbmFsdModuleData by digi moduleId.
+	 */
+  CbmFsdModuleData* GetModuleDataById(Int_t id);
+
+  /*
+     * \brief Return ids of all modules
+     */
+  std::vector<Int_t> GetModuleIds();
+
+private:
+  std::map<std::string, Int_t> fModulePathToIdMap;
+  std::map<Int_t, CbmFsdModuleData*> fModuleIdToDataMap;
+  std::vector<Int_t> fModuleIds;  // vector of all  module ids
+
+  /*
+	 * \brief Initialize maps.
+	 */
+  void Init();
+};
+
+#endif /* CBMFSDDETECTORMAPMANAGER_H */
-- 
GitLab