From 4b459cc0f3b6962ad868313d15454019f840b8b0 Mon Sep 17 00:00:00 2001 From: Lukas Chlad <l.chlad@gsi.de> Date: Wed, 9 Aug 2023 11:43:48 +0000 Subject: [PATCH] FSD integration into SIM --- core/data/CbmDataLinkDef.h | 3 +- core/data/fsd/CbmFsdHit.cxx | 11 +- core/data/fsd/CbmFsdHit.h | 12 +- core/data/fsd/CbmFsdPoint.cxx | 3 +- core/data/fsd/CbmFsdPoint.h | 15 +- core/detectors/fsd/CMakeLists.txt | 23 +- core/detectors/fsd/CbmFsdBaseLinkDef.h | 3 +- core/detectors/fsd/CbmFsdContFact.cxx | 15 +- .../fsd/CbmFsdDetectorMapManager.cxx | 111 ------- core/detectors/fsd/CbmFsdDetectorMapManager.h | 64 ---- ...sdDetectorData.h => CbmFsdDetectorSpecs.h} | 23 +- core/detectors/fsd/CbmFsdDigiPar.cxx | 79 +++++ core/detectors/fsd/CbmFsdDigiPar.h | 47 +++ core/detectors/fsd/CbmFsdGeoHandler.cxx | 173 +++++++++++ core/detectors/fsd/CbmFsdGeoHandler.h | 88 ++++++ sim/detectors/CMakeLists.txt | 1 + sim/detectors/fsd/CMakeLists.txt | 30 ++ sim/detectors/fsd/CbmFsdDigitize.cxx | 286 ++++++++++++++++++ sim/detectors/fsd/CbmFsdDigitize.h | 99 ++++++ sim/detectors/fsd/CbmFsdMC.cxx | 135 +++++++++ sim/detectors/fsd/CbmFsdMC.h | 165 ++++++++++ sim/detectors/fsd/CbmFsdSimLinkDef.h | 15 + sim/response/CMakeLists.txt | 1 + sim/response/base/CbmDigitization.cxx | 12 + sim/transport/base/CbmMCEventFilter.cxx | 3 + sim/transport/base/CbmStack.cxx | 2 +- sim/transport/geosetup/CMakeLists.txt | 1 + .../geosetup/CbmGeoSetupDbProvider.cxx | 4 +- .../geosetup/CbmGeoSetupProvider.cxx | 10 +- .../geosetup/CbmGeoSetupRepoProvider.cxx | 1 + sim/transport/steer/CbmTransportConfig.cxx | 1 + 31 files changed, 1212 insertions(+), 224 deletions(-) delete mode 100644 core/detectors/fsd/CbmFsdDetectorMapManager.cxx delete mode 100644 core/detectors/fsd/CbmFsdDetectorMapManager.h rename core/detectors/fsd/{CbmFsdDetectorData.h => CbmFsdDetectorSpecs.h} (50%) create mode 100644 core/detectors/fsd/CbmFsdDigiPar.cxx create mode 100644 core/detectors/fsd/CbmFsdDigiPar.h create mode 100644 core/detectors/fsd/CbmFsdGeoHandler.cxx create mode 100644 core/detectors/fsd/CbmFsdGeoHandler.h create mode 100644 sim/detectors/fsd/CMakeLists.txt create mode 100644 sim/detectors/fsd/CbmFsdDigitize.cxx create mode 100644 sim/detectors/fsd/CbmFsdDigitize.h create mode 100644 sim/detectors/fsd/CbmFsdMC.cxx create mode 100644 sim/detectors/fsd/CbmFsdMC.h create mode 100644 sim/detectors/fsd/CbmFsdSimLinkDef.h diff --git a/core/data/CbmDataLinkDef.h b/core/data/CbmDataLinkDef.h index 4c0a08a60d..68d3650dc5 100644 --- a/core/data/CbmDataLinkDef.h +++ b/core/data/CbmDataLinkDef.h @@ -103,7 +103,8 @@ #pragma link C++ class CbmFsdDigiData + ; #pragma link C++ class CbmFsdHit + ; #pragma link C++ class CbmFsdPoint + ; -#pragma link C++ class CbmFsdAddress + ; +#pragma link C++ namespace CbmFsdAddress; +#pragma link C++ enum CbmFsdAddress::Level; // --- data/global #pragma link C++ class CbmGlobalTrack + ; diff --git a/core/data/fsd/CbmFsdHit.cxx b/core/data/fsd/CbmFsdHit.cxx index 1f6082ec61..dc814a2de6 100644 --- a/core/data/fsd/CbmFsdHit.cxx +++ b/core/data/fsd/CbmFsdHit.cxx @@ -14,12 +14,16 @@ #include <Logger.h> // for Logger, LOG // ----- Default constructor ------------------------------------------- -CbmFsdHit::CbmFsdHit() : CbmPixelHit(), fModuleID(-1), fEdep(-1) +CbmFsdHit::CbmFsdHit() : CbmPixelHit(), fUnitId(-1), fModuleId(-1), fEdep(-1) { SetType(kFSDHIT); SetTime(0.); } -CbmFsdHit::CbmFsdHit(int32_t module, double edep) : CbmPixelHit(), fModuleID(module), fEdep(edep) +CbmFsdHit::CbmFsdHit(int32_t unit, int32_t module, double edep) + : CbmPixelHit() + , fUnitId(unit) + , fModuleId(module) + , fEdep(edep) { SetType(kFSDHIT); SetTime(0.); @@ -35,7 +39,8 @@ void CbmFsdHit::Print(Option_t*) const { LOG(info) << ToString(); } std::string CbmFsdHit::ToString() const { std::stringstream ss; - ss << "module : " << fModuleID << "position: [" << GetX() << "," << GetY() << "," << GetZ() << "] " + ss << "unit : " << fUnitId << "module : " << fModuleId << "position: [" << GetX() << "," << GetY() << "," << GetZ() + << "] " << " ELoss " << fEdep; return ss.str(); } diff --git a/core/data/fsd/CbmFsdHit.h b/core/data/fsd/CbmFsdHit.h index 8989a540c9..d833bfa800 100644 --- a/core/data/fsd/CbmFsdHit.h +++ b/core/data/fsd/CbmFsdHit.h @@ -28,7 +28,7 @@ public: /** Default constructor **/ CbmFsdHit(); - CbmFsdHit(int32_t module, double edep); + CbmFsdHit(int32_t unit, int32_t module, double edep); /** Destructor **/ @@ -40,8 +40,11 @@ public: double GetEdep() const { return fEdep; } void SetEdep(double edep) { fEdep = edep; } - int32_t GetModuleID() const { return fModuleID; } - void SetModuleID(int32_t mod) { fModuleID = mod; } + int32_t GetModuleId() const { return fModuleId; } + void SetModuleId(int32_t mod) { fModuleId = mod; } + + int32_t GetUnitId() const { return fUnitId; } + void SetUnitId(int32_t unit) { fUnitId = unit; } void Print(Option_t* = "") const; @@ -50,7 +53,8 @@ public: private: /** Data members **/ - int32_t fModuleID; + int32_t fModuleId; + int32_t fUnitId; double fEdep; diff --git a/core/data/fsd/CbmFsdPoint.cxx b/core/data/fsd/CbmFsdPoint.cxx index b200a6de42..baddb48790 100644 --- a/core/data/fsd/CbmFsdPoint.cxx +++ b/core/data/fsd/CbmFsdPoint.cxx @@ -10,7 +10,7 @@ #include <sstream> // for stringstream // ----- Default constructor ------------------------------------------- -CbmFsdPoint::CbmFsdPoint() : FairMCPoint(), fModuleID(0) {} +CbmFsdPoint::CbmFsdPoint() : FairMCPoint() {} // ------------------------------------------------------------------------- @@ -18,7 +18,6 @@ CbmFsdPoint::CbmFsdPoint() : FairMCPoint(), fModuleID(0) {} 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) { } // ------------------------------------------------------------------------- diff --git a/core/data/fsd/CbmFsdPoint.h b/core/data/fsd/CbmFsdPoint.h index 329c2bb9c1..764ab7442d 100644 --- a/core/data/fsd/CbmFsdPoint.h +++ b/core/data/fsd/CbmFsdPoint.h @@ -30,7 +30,7 @@ public: /** Constructor with arguments *@param trackID Index of MCTrack *@param detID Detector ID - *@param pos Ccoordinates at entrance to active volume [cm] + *@param pos Coordinates 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] @@ -39,10 +39,6 @@ public: 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(); @@ -50,17 +46,8 @@ public: /** 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) }; diff --git a/core/detectors/fsd/CMakeLists.txt b/core/detectors/fsd/CMakeLists.txt index e3582ed7bc..3781292489 100644 --- a/core/detectors/fsd/CMakeLists.txt +++ b/core/detectors/fsd/CMakeLists.txt @@ -4,24 +4,27 @@ set(INCLUDE_DIRECTORIES set(SRCS CbmFsdContFact.cxx - CbmFsdDetectorMapManager.cxx + CbmFsdGeoHandler.cxx + CbmFsdDigiPar.cxx ) set(LIBRARY_NAME CbmFsdBase) set(LINKDEF ${LIBRARY_NAME}LinkDef.h) set(PUBLIC_DEPENDENCIES + ROOT::Core FairRoot::ParBase ) -set(PRIVATE_DEPENDENCIES - FairLogger::FairLogger - ROOT::Core +set(PRIVATE_DEPENDENCIES + CbmData + FairLogger::FairLogger + ROOT::Geom + ${VMCLIB} ) -generate_cbm_library() - # Install file which has no corresponding source file -install(FILES - CbmFsdDetectorData.h - DESTINATION include - ) +set(HEADERS + CbmFsdDetectorSpecs.h + ) + +generate_cbm_library() diff --git a/core/detectors/fsd/CbmFsdBaseLinkDef.h b/core/detectors/fsd/CbmFsdBaseLinkDef.h index 26be7730a4..9bb21eb15a 100644 --- a/core/detectors/fsd/CbmFsdBaseLinkDef.h +++ b/core/detectors/fsd/CbmFsdBaseLinkDef.h @@ -11,6 +11,7 @@ #pragma link off all functions; #pragma link C++ class CbmFsdContFact + ; -#pragma link C++ class CbmFsdDetectorMapManager + ; +#pragma link C++ class CbmFsdGeoHandler + ; +#pragma link C++ class CbmFsdDigiPar + ; #endif diff --git a/core/detectors/fsd/CbmFsdContFact.cxx b/core/detectors/fsd/CbmFsdContFact.cxx index 550b8ebcf2..e685b4a818 100644 --- a/core/detectors/fsd/CbmFsdContFact.cxx +++ b/core/detectors/fsd/CbmFsdContFact.cxx @@ -13,6 +13,8 @@ */ #include "CbmFsdContFact.h" +#include "CbmFsdDigiPar.h" + #include <FairContFact.h> // for FairContainer #include <FairRuntimeDb.h> // for FairRuntimeDb #include <Logger.h> // for LOG @@ -39,6 +41,13 @@ void CbmFsdContFact::setAllContainers() { /** Creates the Container objects with all accepted contexts and adds them to * the list of containers for the FsdBase library.*/ + + FairContainer* p1 = + new FairContainer("CbmFsdDigiPar", "Digitization parameters for the FSD detector", + "Needed parameters to adjust FsdDigitizer according to the geometry and read-out propetries"); + p1->addContext("Needed parameters to adjust FsdDigitizer according to the geometry and read-out propetries"); + + containers->Add(p1); } FairParSet* CbmFsdContFact::createContainer(FairContainer* c) @@ -48,7 +57,11 @@ FairParSet* CbmFsdContFact::createContainer(FairContainer* c) * of this container, the name is concatinated with the context. */ const char* name = c->GetName(); LOG(info) << " -I container name " << name; - FairParSet* p = 0; + FairParSet* p = nullptr; + + if (strcmp(name, "CbmFsdDigiPar") == 0) { + p = new CbmFsdDigiPar(c->getConcatName().Data(), c->GetTitle(), c->getContext()); + } return p; } diff --git a/core/detectors/fsd/CbmFsdDetectorMapManager.cxx b/core/detectors/fsd/CbmFsdDetectorMapManager.cxx deleted file mode 100644 index bfbed6a7e1..0000000000 --- a/core/detectors/fsd/CbmFsdDetectorMapManager.cxx +++ /dev/null @@ -1,111 +0,0 @@ -/* 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 deleted file mode 100644 index 5afe83850a..0000000000 --- a/core/detectors/fsd/CbmFsdDetectorMapManager.h +++ /dev/null @@ -1,64 +0,0 @@ -/* 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 */ diff --git a/core/detectors/fsd/CbmFsdDetectorData.h b/core/detectors/fsd/CbmFsdDetectorSpecs.h similarity index 50% rename from core/detectors/fsd/CbmFsdDetectorData.h rename to core/detectors/fsd/CbmFsdDetectorSpecs.h index 5bab1cfbae..bb7c83f618 100644 --- a/core/detectors/fsd/CbmFsdDetectorData.h +++ b/core/detectors/fsd/CbmFsdDetectorSpecs.h @@ -2,14 +2,16 @@ SPDX-License-Identifier: GPL-3.0-only Authors: Lukas Chlad [committer] */ -#ifndef CBMFSDDETECTORDATA_H -#define CBMFSDDETECTORDATA_H +#ifndef CBMFSDDETECTORSPECS_H +#define CBMFSDDETECTORSPECS_H #include <RtypesCore.h> // for Double_t, Int_t +#include <TString.h> // for TString -struct CbmFsdModuleData { - // module index - Int_t fId; +struct CbmFsdModuleSpecs { + // location indices + Int_t fUnitId; + Int_t fModuleId; // module center position Double_t fX; Double_t fY; @@ -20,4 +22,13 @@ struct CbmFsdModuleData { Double_t dZ; }; -#endif /* CBMFSDDETECTORDATA_H */ +struct CbmFsdUnitSpecs { + // name of unit + TString fUnitName; + // unit id + Int_t fUnitId; + // number of modules in unit + Int_t fNumModules; +}; + +#endif /* CBMFSDDETECTORSPECS_H */ diff --git a/core/detectors/fsd/CbmFsdDigiPar.cxx b/core/detectors/fsd/CbmFsdDigiPar.cxx new file mode 100644 index 0000000000..72ba522681 --- /dev/null +++ b/core/detectors/fsd/CbmFsdDigiPar.cxx @@ -0,0 +1,79 @@ +/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen + SPDX-License-Identifier: GPL-3.0-only + Authors: Florian Uhlig, Lukas Chlad [committer] */ + +#include "CbmFsdDigiPar.h" + +#include <FairParGenericSet.h> // for FairParGenericSet +#include <FairParamList.h> // for FairParamList +#include <Logger.h> // for LOG, Logger + +ClassImp(CbmFsdDigiPar) + + CbmFsdDigiPar::CbmFsdDigiPar(const char* name, const char* title, const char* context) + : FairParGenericSet(name, title, context) + , fNumPhotoDets(-1) + , fTimeResolution(-1.) + , fEnergyResolution(-1.) +{ + detName = "Fsd"; +} + +CbmFsdDigiPar::~CbmFsdDigiPar(void) { clear(); } + +void CbmFsdDigiPar::clear(void) +{ + status = kFALSE; + resetInputVersions(); +} + +void CbmFsdDigiPar::putParams(FairParamList* l) +{ + if (!l) { return; } + + l->add("NumPhotoDets", fNumPhotoDets); + l->add("NumUnits", fNumUnits); + l->add("TimeResolution", fTimeResolution); + l->add("EnergyResolution", fEnergyResolution); + l->add("DeadTime", fDeadTime); +} + +Bool_t CbmFsdDigiPar::getParams(FairParamList* l) +{ + if (!l) { return kFALSE; } + + LOG(debug2) << "Get the FSD digitization parameters."; + + if (!l->fill("NumPhotoDets", &fNumPhotoDets)) return kFALSE; + if (!l->fill("NumUnits", &fNumUnits)) return kFALSE; + + fTimeResolution.Set(fNumUnits); + fEnergyResolution.Set(fNumUnits); + fDeadTime.Set(fNumUnits); + if (!l->fill("TimeResolution", &fTimeResolution)) return kFALSE; + if (!l->fill("EnergyResolution", &fEnergyResolution)) return kFALSE; + if (!l->fill("DeadTime", &fDeadTime)) return kFALSE; + + return kTRUE; +} + +Double_t CbmFsdDigiPar::GetTimeResolution(Int_t iUnitId) const +{ + if (iUnitId < fNumUnits) return fTimeResolution[iUnitId]; + else + return -1.; +} + +Double_t CbmFsdDigiPar::GetEnergyResolution(Int_t iUnitId) const +{ + if (iUnitId < fNumUnits) return fEnergyResolution[iUnitId]; + else + return -1.; +} + +Double_t CbmFsdDigiPar::GetDeadTime(Int_t iUnitId) const +{ + if (iUnitId < fNumUnits) return fDeadTime[iUnitId]; + else + return -1.; +} diff --git a/core/detectors/fsd/CbmFsdDigiPar.h b/core/detectors/fsd/CbmFsdDigiPar.h new file mode 100644 index 0000000000..b0502615c8 --- /dev/null +++ b/core/detectors/fsd/CbmFsdDigiPar.h @@ -0,0 +1,47 @@ +/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen + SPDX-License-Identifier: GPL-3.0-only + Authors: Florian Uhlig, Lukas Chlad [committer] */ + +#ifndef CBMFSDDIGIPAR_H +#define CBMFSDDIGIPAR_H + +#include <FairParGenericSet.h> // for FairParGenericSet + +#include <Rtypes.h> // for THashConsistencyHolder, ClassDef +#include <RtypesCore.h> // for Int_t, Double_t +#include <TArrayD.h> // for TArrayD + +class FairParamList; + +class CbmFsdDigiPar : public FairParGenericSet { +public: + CbmFsdDigiPar( + const char* name = "CbmFsdDigiPar", const char* title = "Digitization parameters for the FSD detector", + const char* context = "Needed parameters to adjust FsdDigitizer according to the geometry and read-out propetries"); + + CbmFsdDigiPar(const CbmFsdDigiPar&) = delete; + CbmFsdDigiPar& operator=(const CbmFsdDigiPar&) = delete; + + ~CbmFsdDigiPar(void); + + void clear(void); + void putParams(FairParamList*); + Bool_t getParams(FairParamList*); + + Int_t GetNumPhotoDets() const { return fNumPhotoDets; } + Int_t GetNumUnits() const { return fNumUnits; } + Double_t GetTimeResolution(Int_t iUnitId) const; + Double_t GetEnergyResolution(Int_t iUnitId) const; + Double_t GetDeadTime(Int_t iUnitId) const; + +private: + Int_t fNumPhotoDets; // number of photo detectors per module + Int_t fNumUnits; // number of units within given FSD geo version + TArrayD fTimeResolution; // value to smear the timing via gaussian + TArrayD fEnergyResolution; // value to smear the energy measurement via gaussian + TArrayD fDeadTime; // value to separate digis in time-based + + ClassDef(CbmFsdDigiPar, 1) +}; + +#endif diff --git a/core/detectors/fsd/CbmFsdGeoHandler.cxx b/core/detectors/fsd/CbmFsdGeoHandler.cxx new file mode 100644 index 0000000000..465e5ff215 --- /dev/null +++ b/core/detectors/fsd/CbmFsdGeoHandler.cxx @@ -0,0 +1,173 @@ +/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen + SPDX-License-Identifier: GPL-3.0-only + Authors: Lukas Chlad [committer] */ + +#include "CbmFsdGeoHandler.h" + +#include "CbmFsdAddress.h" // for CbmFsdAddress +#include "CbmFsdDetectorSpecs.h" // for CbmFsdModuleSpecs + +#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 <TVirtualMC.h> // for TVirtualMC, gMC + +#include <string> // for operator<, stoul +#include <utility> // for pair + +#include <stddef.h> // for size_t + +using namespace std; + +// constructor with initialization of maps +CbmFsdGeoHandler::CbmFsdGeoHandler() { InitMaps(); } + +void CbmFsdGeoHandler::InitMaps() +{ + fUnitIdToSpecsMap.clear(); + fModuleIdToSpecsMap.clear(); + + Int_t currentModuleId = -1; + Int_t currentUnitId = -1; + + TGeoIterator geoIterator(gGeoManager->GetTopNode()->GetVolume()); + + TGeoNode* curNode; + geoIterator.Reset(); // safety to reset to "cave" befor the loop starts + while ((curNode = geoIterator())) { + TString nodePath; + geoIterator.GetPath(nodePath); + if (!nodePath.Contains(fBranchStr)) { + 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()); + if (nodeName.Contains(fUnitStr)) { + currentUnitId = curNode->GetNumber(); + + CbmFsdUnitSpecs* unitSpecs = new CbmFsdUnitSpecs(); + unitSpecs->fUnitId = currentUnitId; + unitSpecs->fUnitName = static_cast<TString>(curNode->GetVolume()->GetName()); + unitSpecs->fNumModules = curNode->GetNdaughters(); + fUnitIdToSpecsMap.insert(pair<Int_t, CbmFsdUnitSpecs*>(currentUnitId, unitSpecs)); + } + if (nodeName.Contains(fModuleStr)) { + currentModuleId = curNode->GetNumber(); + const TGeoMatrix* curMatrix = geoIterator.GetCurrentMatrix(); + const Double_t* curNodeTr = curMatrix->GetTranslation(); + + TGeoVolume* curScintillator = nullptr; + for (int idn = 0; idn < curNode->GetNdaughters(); idn++) { + TGeoNode* daughterNode = curNode->GetDaughter(idn); + if (TString(daughterNode->GetName()).Contains(fActiveMatStr)) { + curScintillator = daughterNode->GetVolume(); + break; + } + } + const TGeoBBox* shape = (const TGeoBBox*) (curScintillator->GetShape()); + + CbmFsdModuleSpecs* moduleSpecs = new CbmFsdModuleSpecs(); + moduleSpecs->fX = curNodeTr[0]; + moduleSpecs->fY = curNodeTr[1]; + moduleSpecs->fZ = curNodeTr[2]; + moduleSpecs->dX = shape->GetDX(); + moduleSpecs->dY = shape->GetDY(); + moduleSpecs->dZ = shape->GetDZ(); + moduleSpecs->fModuleId = currentModuleId; + moduleSpecs->fUnitId = currentUnitId; + fModuleIdToSpecsMap.insert(pair<Int_t, CbmFsdModuleSpecs*>(currentModuleId, moduleSpecs)); + } + } + + LOG(info) << "CbmFsdGeoHandler has initialized maps"; + LOG(info) << "fUnitIdToSpecsMap.size() = " << fUnitIdToSpecsMap.size(); + LOG(info) << "fModuleIdToSpecsMap.size() = " << fModuleIdToSpecsMap.size(); +} + +CbmFsdModuleSpecs* CbmFsdGeoHandler::GetModuleSpecsById(Int_t modId) +{ + std::map<Int_t, CbmFsdModuleSpecs*>::iterator it; + it = fModuleIdToSpecsMap.find(modId); + if (it == fModuleIdToSpecsMap.end()) return nullptr; + return it->second; +} + +CbmFsdUnitSpecs* CbmFsdGeoHandler::GetUnitSpecsById(Int_t unitId) +{ + std::map<Int_t, CbmFsdUnitSpecs*>::iterator it; + it = fUnitIdToSpecsMap.find(unitId); + if (it == fUnitIdToSpecsMap.end()) return nullptr; + return it->second; +} + +int32_t CbmFsdGeoHandler::GetAddress(TString geoPath) const +{ + Int_t moduleID = GetCopyNumberByKey(geoPath, fModuleStr); + Int_t unitID = GetCopyNumberByKey(geoPath, fUnitStr); + + return CbmFsdAddress::GetAddress(unitID, moduleID); +} + +int32_t CbmFsdGeoHandler::GetCurrentAddress(TVirtualMC* vmc) const +{ + Int_t moduleID = -1; + Int_t unitID = -1; + + Int_t upstreamOffset = 0; + while (((TString) vmc->CurrentVolOffName(upstreamOffset)).Length() > 0) { + if (((TString) vmc->CurrentVolOffName(upstreamOffset)).Contains(fUnitStr)) + vmc->CurrentVolOffID(upstreamOffset, unitID); + if (((TString) vmc->CurrentVolOffName(upstreamOffset)).Contains(fModuleStr)) + vmc->CurrentVolOffID(upstreamOffset, moduleID); + upstreamOffset++; + } + + return CbmFsdAddress::GetAddress(unitID, moduleID); +} + +int32_t CbmFsdGeoHandler::GetCurrentAddress(TGeoManager* geoMan) const +{ + Int_t moduleID = -1; + Int_t unitID = -1; + + Int_t upstreamOffset = 0; + while (upstreamOffset <= geoMan->GetLevel()) { + TGeoNode* node = geoMan->GetMother(upstreamOffset); + if (((TString) node->GetVolume()->GetName()).Contains(fUnitStr)) unitID = node->GetNumber(); + if (((TString) node->GetVolume()->GetName()).Contains(fModuleStr)) moduleID = node->GetNumber(); + upstreamOffset++; + } + + return CbmFsdAddress::GetAddress(unitID, moduleID); +} + +Int_t CbmFsdGeoHandler::GetCopyNumberByKey(TString geoPath, TString key) const +{ + Int_t copyNum = -1; + + // sanity checks + if (!geoPath.Contains(fBranchStr)) { LOG(warning) << __func__ << ": In geoPath " << fBranchStr << " was not found!"; } + else if (!geoPath.Contains(key)) { + LOG(warning) << __func__ << ": In geoPath " << key << " was not found!"; + } + else { + Ssiz_t keyStart = geoPath.Index(key); + TString keyName = geoPath(keyStart, geoPath.Index("/", keyStart) - keyStart); + Ssiz_t copyNumStart = keyName.Last('_') + 1; + TString copyNumStr = keyName(copyNumStart, keyName.Length() - copyNumStart); + if (!copyNumStr.IsDigit()) { + LOG(warning) << __func__ << ": Expected numerical part from " << geoPath << " using key " << key << " is " + << copyNumStr << " which does not contain only digits!"; + } + else { + copyNum = copyNumStr.Atoi(); + } + } + + return copyNum; +} diff --git a/core/detectors/fsd/CbmFsdGeoHandler.h b/core/detectors/fsd/CbmFsdGeoHandler.h new file mode 100644 index 0000000000..e7ed7f947e --- /dev/null +++ b/core/detectors/fsd/CbmFsdGeoHandler.h @@ -0,0 +1,88 @@ +/* Copyright (C) 2023 Physikalisches Institut, Eberhard Karls Universitaet Tuebingen, Tuebingen + SPDX-License-Identifier: GPL-3.0-only + Authors: Lukas Chlad [committer] */ + +#ifndef CBMFSDGEOHANDLER_H +#define CBMFSDGEOHANDLER_H + +#include <RtypesCore.h> // for Int_t, Bool_t +#include <TString.h> // for TString + +#include <iostream> // for string +#include <map> // for map +#include <vector> // for vector + +struct CbmFsdModuleSpecs; +struct CbmFsdUnitSpecs; +class TVirtualMC; +class TGeoManager; + +class CbmFsdGeoHandler { + +private: + /** Default constructor **/ + CbmFsdGeoHandler(); + + /** Default destructor **/ + ~CbmFsdGeoHandler() = default; + + /** @brief Helper function to extract copy number from geoPath using key word + ** @return integer corresponding to copy number of the key word + **/ + Int_t GetCopyNumberByKey(TString geoPath, TString key) const; + +public: + CbmFsdGeoHandler(const CbmFsdGeoHandler&) = delete; + CbmFsdGeoHandler& operator=(const CbmFsdGeoHandler&) = delete; + + /** + * Return Instance of CbmFsdGeoHandler. + */ + static CbmFsdGeoHandler& GetInstance() + { + static CbmFsdGeoHandler fInstance; + return fInstance; + } + + /* + * \brief Return CbmFsdModuleSpecs by digi moduleId. + */ + CbmFsdModuleSpecs* GetModuleSpecsById(Int_t id); + + /* + * \brief Return CbmFsdUnitSpecs by digi unitId. + */ + CbmFsdUnitSpecs* GetUnitSpecsById(Int_t id); + + /* + * \brief Initialize maps. + */ + void InitMaps(); + + /** @brief Get the unique address from geometry path string + ** @return integer corresponding to CbmFsdAddress scheme + **/ + int32_t GetAddress(TString geoPath) const; + + /** @brief Get the unique address from TVirtualMC + ** @return integer corresponding to CbmFsdAddress scheme + **/ + int32_t GetCurrentAddress(TVirtualMC* vmc) const; + + /** @brief Get the unique address from TGeoManager + ** @return integer corresponding to CbmFsdAddress scheme + **/ + int32_t GetCurrentAddress(TGeoManager* geoMan) const; + +private: + std::map<Int_t, CbmFsdModuleSpecs*> fModuleIdToSpecsMap; + std::map<Int_t, CbmFsdUnitSpecs*> fUnitIdToSpecsMap; + + // these key TStrings must corresponds to what one introduce in create geo macros!! + const TString fBranchStr = "fsd_"; + const TString fUnitStr = "unit"; + const TString fModuleStr = "module"; + const TString fActiveMatStr = "scint"; +}; + +#endif /* CBMFSDGEOHANDLER_H */ diff --git a/sim/detectors/CMakeLists.txt b/sim/detectors/CMakeLists.txt index 8c50987d7d..1399b1cd19 100644 --- a/sim/detectors/CMakeLists.txt +++ b/sim/detectors/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory(bmon) add_subdirectory(much) add_subdirectory(mvd) add_subdirectory(psd) +add_subdirectory(fsd) add_subdirectory(rich) add_subdirectory(sts) add_subdirectory(tof) diff --git a/sim/detectors/fsd/CMakeLists.txt b/sim/detectors/fsd/CMakeLists.txt new file mode 100644 index 0000000000..a73ae12258 --- /dev/null +++ b/sim/detectors/fsd/CMakeLists.txt @@ -0,0 +1,30 @@ +set(INCLUDE_DIRECTORIES + ${CMAKE_CURRENT_SOURCE_DIR} + ) + +set(SRCS + CbmFsdMC.cxx + CbmFsdDigitize.cxx + ) + +set(LIBRARY_NAME CbmFsdSim) +set(LINKDEF ${LIBRARY_NAME}LinkDef.h) +set(PUBLIC_DEPENDENCIES + CbmBase + CbmData + FairRoot::Base + ROOT::Core + ROOT::Physics + ) + +set(PRIVATE_DEPENDENCIES + CbmSimBase + CbmFsdBase + FairRoot::ParBase + FairLogger::FairLogger + ROOT::Geom + ROOT::MathCore + ${VMCLIB} + ) + +generate_cbm_library() diff --git a/sim/detectors/fsd/CbmFsdDigitize.cxx b/sim/detectors/fsd/CbmFsdDigitize.cxx new file mode 100644 index 0000000000..b889b53a55 --- /dev/null +++ b/sim/detectors/fsd/CbmFsdDigitize.cxx @@ -0,0 +1,286 @@ +/* Copyright (C) 2023 Physikalisches Institut Eberhard Karls Universitaet Tuebingen, Tuebingen + SPDX-License-Identifier: GPL-3.0-only + Authors: Alla Maevskaya, Selim Seddiki, Sergey Morozov, Volker Friese, Evgeny Kashirin, Lukas Chlad [committer] */ + +#include "CbmFsdDigitize.h" + +#include "CbmFsdAddress.h" +#include "CbmFsdDigi.h" +#include "CbmFsdDigiPar.h" +#include "CbmFsdPoint.h" +#include "CbmLink.h" +#include "CbmMatch.h" + +#include <FairRootManager.h> +#include <FairRun.h> +#include <FairRuntimeDb.h> +#include <Logger.h> + +#include <TArrayD.h> +#include <TClonesArray.h> +#include <TMath.h> +#include <TRandom3.h> +#include <TStopwatch.h> + +#include <cassert> +#include <iomanip> +#include <iostream> +#include <map> + +using std::cout; +using std::endl; +using std::fixed; +using std::right; +using std::setprecision; +using std::setw; + +using std::map; +using std::pair; + +// ----- Public method Init -------------------------------------------- +InitStatus CbmFsdDigitize::Init() +{ + if (!fEventMode) { LOG(info) << GetName() << " uses TimeBased mode."; } + else { + LOG(info) << GetName() << " uses Events mode."; + } + + // Get RootManager + FairRootManager* ioman = FairRootManager::Instance(); + + // Get input array + fPointArray = dynamic_cast<TClonesArray*>(ioman->GetObject("FsdPoint")); + if (nullptr == fPointArray) { + LOG(error) << GetName() << ": Error in reading from file! No FsdPoint array."; + return kERROR; + } + TString objectName = fPointArray->GetClass()->GetName(); + if (0 != objectName.CompareTo("CbmFsdPoint")) { + LOG(fatal) << GetName() << ": TClonesArray does not contain data of the expected class CbmFsdPoint"; + } + + // Initialise parameters + InitParams(); + + // Create and register output array + RegisterOutput(); + + // Statistics + fNumEvents = 0; + fNumPoints = 0.; + fNumDigis = 0.; + fTimeTot = 0.; + + LOG(info) << GetName() << ": Initialisation successful " << kSUCCESS; + return kSUCCESS; +} +// ------------------------------------------------------------------------- + +void CbmFsdDigitize::SetParContainers() +{ + LOG(info) << GetName() << ": Get the digi parameters for FSD"; + + // Get Base Container + FairRun* ana = FairRun::Instance(); + FairRuntimeDb* rtdb = ana->GetRuntimeDb(); + + fDigiPar = dynamic_cast<CbmFsdDigiPar*>(rtdb->getContainer("CbmFsdDigiPar")); + if (fDigiPar == nullptr) { + LOG(fatal) << GetName() << ": parameter container CbmFsdDigiPar not available in current RuntimeDb!!"; + } +} + +void CbmFsdDigitize::InitParams() +{ + if (!fDigiPar) { LOG(fatal) << GetName() << ": parameter container CbmFsdDigiPar not found!!"; } + + // Get values from loaded parameter container + fNumPhotoDets = fDigiPar->GetNumPhotoDets(); + fNumUnits = fDigiPar->GetNumUnits(); + + if (fNumPhotoDets < 1 || fNumUnits < 1) { + LOG(fatal) << GetName() << ": parameter values for FSD digitization does not meet a sanity check!!"; + } + + fTimeResolution.Set(fNumUnits); + fEnergyResolution.Set(fNumUnits); + fDeadTime.Set(fNumUnits); + + for (Int_t iu = 0; iu < fNumUnits; iu++) { + fTimeResolution[iu] = fDigiPar->GetTimeResolution(iu); + fEnergyResolution[iu] = fDigiPar->GetEnergyResolution(iu); + fDeadTime[iu] = fDigiPar->GetDeadTime(iu); + + if (fDeadTime[iu] < 0. || fTimeResolution[iu] < 0. || fEnergyResolution[iu] < 0.) { + LOG(fatal) << GetName() << ": parameter values for FSD digitization does not meet a sanity check!!"; + } + } +} + +// ----- Public method Exec -------------------------------------------- +void CbmFsdDigitize::Exec(Option_t*) +{ + // Event info (for event time) + GetEventInfo(); + + TStopwatch timer; + timer.Start(); + + Int_t nDigis = 0; + + // digis that are distant in time to this event (and thus can not be modified anymore) should be send to DAQ + if (!fEventMode) ReleaseBuffer(kFALSE); + + + Int_t nPoints = fPointArray->GetEntriesFast(); + LOG(debug) << fName << ": processing event " << fCurrentEvent << " at t = " << fCurrentEventTime << " ns"; + + // Declare some variables + CbmFsdPoint* point = nullptr; + + Int_t modId = -1; + Int_t unitId = -1; + Int_t photodetId = -1; + + if (fNumPhotoDets > 1) { + // random uniform split into photo detectors?! + photodetId = gRandom->Integer(static_cast<UInt_t>(fNumPhotoDets)); + } + else { + photodetId = 0; + } + + // Loop over FsdPoints + for (Int_t iPoint = 0; iPoint < nPoints; iPoint++) { + point = static_cast<CbmFsdPoint*>(fPointArray->At(iPoint)); + if (!point) continue; + + int32_t pointAddress = static_cast<int32_t>(point->GetDetectorID()); + modId = + static_cast<Int_t>(CbmFsdAddress::GetElementId(pointAddress, static_cast<int32_t>(CbmFsdAddress::Level::Module))); + unitId = + static_cast<Int_t>(CbmFsdAddress::GetElementId(pointAddress, static_cast<int32_t>(CbmFsdAddress::Level::Unit))); + Double_t eloss = point->GetEnergyLoss() + gRandom->Gaus(0., fEnergyResolution[unitId]); + Double_t time = fCurrentEventTime + point->GetTime() + gRandom->Gaus(0., fTimeResolution[unitId]); + uint32_t address = static_cast<uint32_t>(CbmFsdAddress::GetAddress( + static_cast<uint32_t>(unitId), static_cast<uint32_t>(modId), static_cast<uint32_t>(photodetId))); + + CbmLink link(eloss, iPoint, fCurrentMCEntry, fCurrentInput); // weight of link is the energy loss + + auto it = fDigiBuffer.find(pointAddress); + if (it != fDigiBuffer.end()) { + // there is already in buffer a digi with this key + Double_t timeDiff = std::fabs(time - it->second.first->GetTime()); + if (timeDiff < fDeadTime[unitId]) { + // modify found digi : add energy deposition, modify time if earlier + it->second.first->SetEdep(it->second.first->GetEdep() + eloss); + if (time < it->second.first->GetTime()) it->second.first->SetTime(time); + // add link to digimatch + it->second.second->AddLink(link); + } + else { + // not within time cut -> send the digi from buffer and replace by the new one + CbmFsdDigi* oldDigi = + new CbmFsdDigi(it->second.first->GetAddress(), it->second.first->GetTime(), it->second.first->GetEdep()); + CbmMatch* oldDigiMatch = new CbmMatch(*it->second.second); + if (fCreateMatches) SendData(oldDigi->GetTime(), oldDigi, oldDigiMatch); + else + SendData(oldDigi->GetTime(), oldDigi); + fDigiBuffer.erase(it); + + CbmFsdDigi* digi = new CbmFsdDigi(address, time, eloss); + CbmMatch* match = new CbmMatch(); + match->AddLink(link); + fDigiBuffer.insert(std::make_pair(pointAddress, std::make_pair(digi, match))); + nDigis++; + } + } + else { + // digi with this key is not yet in buffer -> insert it + CbmFsdDigi* digi = new CbmFsdDigi(address, time, eloss); + CbmMatch* match = new CbmMatch(); + match->AddLink(link); + fDigiBuffer.insert(std::make_pair(pointAddress, std::make_pair(digi, match))); + nDigis++; + } + } // Loop over MCPoints + + // in EventMode send and clear the whole buffer after MCEvent is processed + if (fEventMode) ReleaseBuffer(kTRUE); + + // --- Event log + timer.Stop(); + LOG(info) << "+ " << setw(15) << GetName() << ": Event " << setw(6) << right << fCurrentEvent << " at " << fixed + << setprecision(3) << fCurrentEventTime << " ns, points: " << nPoints << ", digis: " << nDigis + << ". Exec time " << setprecision(6) << timer.RealTime() << " s."; + + // --- Run statistics + fNumEvents++; + fNumPoints += nPoints; + fNumDigis += nDigis; + fTimeTot += timer.RealTime(); +} +// ------------------------------------------------------------------------- + + +// ----- End-of-run ---------------------------------------------------- +void CbmFsdDigitize::Finish() +{ + std::cout << std::endl; + LOG(info) << "====================================="; + LOG(info) << GetName() << ": Finish run"; + if (!fEventMode) ReleaseBuffer(kTRUE); // in time-based mode, send all what is left in buffer to DAQ + LOG(info) << GetName() << ": Run summary"; + LOG(info) << "Events processed : " << fNumEvents; + LOG(info) << "FsdPoint / event : " << setprecision(1) << fNumPoints / Double_t(fNumEvents); + LOG(info) << "FsdDigi / event : " << fNumDigis / Double_t(fNumEvents); + LOG(info) << "Digis per point : " << setprecision(6) << fNumDigis / fNumPoints; + LOG(info) << "Real time per event : " << fTimeTot / Double_t(fNumEvents) << " s"; + LOG(info) << "====================================="; +} +// ------------------------------------------------------------------------- + + +void CbmFsdDigitize::ReleaseBuffer(Bool_t sendEverything) +{ + if (sendEverything) { + // send everything + for (const auto& dp : fDigiBuffer) { + CbmFsdDigi* digi = + new CbmFsdDigi(dp.second.first->GetAddress(), dp.second.first->GetTime(), dp.second.first->GetEdep()); + CbmMatch* digiMatch = new CbmMatch(*dp.second.second); + if (fCreateMatches) SendData(digi->GetTime(), digi, digiMatch); + else + SendData(digi->GetTime(), digi); + } // # digi buffer + fDigiBuffer.clear(); + } + else { + // send only if time difference to the new start of event is larger than deadtime + std::vector<int32_t> keysSent; + for (const auto& dp : fDigiBuffer) { + Int_t unitId = static_cast<Int_t>(CbmFsdAddress::GetElementId(static_cast<int32_t>(dp.second.first->GetAddress()), + static_cast<int32_t>(CbmFsdAddress::Level::Unit))); + Double_t timeDiff = std::fabs(dp.second.first->GetTime() - fCurrentEventTime); + if (timeDiff > fDeadTime[unitId]) { + // send this digi + CbmFsdDigi* digi = + new CbmFsdDigi(dp.second.first->GetAddress(), dp.second.first->GetTime(), dp.second.first->GetEdep()); + CbmMatch* digiMatch = new CbmMatch(*dp.second.second); + if (fCreateMatches) SendData(digi->GetTime(), digi, digiMatch); + else + SendData(digi->GetTime(), digi); + + // save which keys were sent and should be removed + keysSent.push_back(dp.first); + } // ? time + } // # digi buffer + + // remove the sent elements from buffer + for (auto& key : keysSent) { + fDigiBuffer.erase(key); + } + } // ? sendEverything +} + +ClassImp(CbmFsdDigitize) diff --git a/sim/detectors/fsd/CbmFsdDigitize.h b/sim/detectors/fsd/CbmFsdDigitize.h new file mode 100644 index 0000000000..f8c3791a21 --- /dev/null +++ b/sim/detectors/fsd/CbmFsdDigitize.h @@ -0,0 +1,99 @@ +/* Copyright (C) 2023 Physikalisches Institut Eberhard Karls Universitaet Tuebingen, Tuebingen + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergey Morozov, Volker Friese, Lukas Chlad [committer] */ + +/** @class CbmFsdDigitize + ** @date 14.07.2023 + ** @author Lukas Chlad <l.chlad@gsi.de> + ** @brief Class for the digitization of the CBM-FSD + ** + ** The digitizer produces digits of type CbmFsdDigi as sum of Edep of Points and adds smearing in energy and time according to parameters + **/ + + +#ifndef CBMFSDDIGITIZE_H +#define CBMFSDDIGITIZE_H 1 + + +#include "CbmDefs.h" +#include "CbmDigitize.h" +#include "CbmFsdDigi.h" + +#include <TArrayD.h> + +class TClonesArray; +class CbmFsdDigiPar; + +class CbmFsdDigitize : public CbmDigitize<CbmFsdDigi> { + +public: + /** Default constructor **/ + CbmFsdDigitize() : CbmDigitize<CbmFsdDigi>("FsdDigitize") {}; + + /** Destructor **/ + virtual ~CbmFsdDigitize() = default; + + CbmFsdDigitize(const CbmFsdDigitize&) = delete; + CbmFsdDigitize operator=(const CbmFsdDigitize&) = delete; + + ECbmModuleId GetSystemId() const { return ECbmModuleId::kFsd; } + + + /** + ** @brief Inherited from FairTask. + **/ + virtual InitStatus Init(); + + /** + ** @brief Inherited from FairTask. + **/ + virtual void SetParContainers(); + + /** Virtual method Exec **/ + virtual void Exec(Option_t* opt); + + + /** @brief End-of-run action **/ + virtual void Finish(); + + +private: + CbmFsdDigiPar* fDigiPar = nullptr; + + Int_t fNumPhotoDets = -1; + Int_t fNumUnits = -1; + TArrayD fTimeResolution {}; + TArrayD fEnergyResolution {}; + TArrayD fDeadTime {}; + + Int_t fNumEvents = 0; + Double_t fNumPoints = 0.; + Double_t fNumDigis = 0.; + Double_t fTimeTot = 0.; + + /** Input array of CbmFsdPoints **/ + TClonesArray* fPointArray = nullptr; + + // Temporary storage for digis, key is DetectorID from FsdPoint + std::map<int32_t, std::pair<CbmFsdDigi*, CbmMatch*>> fDigiBuffer; + + /** @brief Initialise the parameters **/ + void InitParams(); + + /** @brief release digi from local buffer to CbmDaq + ** TIME BASED + ** - at the beginning of MCEvent loop over digi buffer + ** and send those digis that are too far from start of current event to be possibly edited + ** free the location of sent digis + ** - at the end of whole run do the same only send everything, clear buffer + ** + ** EVENT BASED + ** - at the beginning of MCEvent loop send everything, clear buffer + **/ + void ReleaseBuffer(Bool_t sendEverything); + + + ClassDef(CbmFsdDigitize, 1); +}; + +#endif diff --git a/sim/detectors/fsd/CbmFsdMC.cxx b/sim/detectors/fsd/CbmFsdMC.cxx new file mode 100644 index 0000000000..21880a7520 --- /dev/null +++ b/sim/detectors/fsd/CbmFsdMC.cxx @@ -0,0 +1,135 @@ +/* Copyright (C) 2023 Physikalisches Institut Eberhard Karls Universitaet Tuebingen, Tuebingen + SPDX-License-Identifier: GPL-3.0-only + Authors: Alla Maevskaya, Florian Uhlig, Lukas Chlad [committer] */ + +/** @file CbmFsdMC.cxx + ** @since 14.07.2023 + ** @author Lukas Chlad <l.chlad@gsi.de> + ** + **/ + + +#include "CbmFsdMC.h" + +#include "CbmFsdGeoHandler.h" +#include "CbmFsdPoint.h" +#include "CbmGeometryUtils.h" +#include "CbmModuleList.h" +#include "CbmStack.h" + +#include <FairVolume.h> + +#include <TGeoNode.h> +#include <TGeoVolume.h> +#include <TVirtualMC.h> + +#include <cassert> +#include <string> + +// ----- Destructor ---------------------------------------------------- +CbmFsdMC::~CbmFsdMC() +{ + if (fFsdPoints) { + fFsdPoints->Delete(); + delete fFsdPoints; + } +} +// ------------------------------------------------------------------------- + + +// ----- Construct the geometry from file ------------------------------ +void CbmFsdMC::ConstructGeometry() +{ + LOG(info) << "Importing FSD geometry from ROOT file " << fgeoName.Data(); + Cbm::GeometryUtils::ImportRootGeometry(fgeoName, this); +} +// ------------------------------------------------------------------------- + + +// ----- End of event action ------------------------------------------- +void CbmFsdMC::EndOfEvent() +{ + Print(); // Status output + fFsdPoints->Delete(); +} +// ------------------------------------------------------------------------- + + +// ----- Print --------------------------------------------------------- +void CbmFsdMC::Print(Option_t*) const +{ + LOG(info) << fName << ": " << fFsdPoints->GetEntriesFast() << " points registered in this event."; +} +// ------------------------------------------------------------------------- + +// ----- Initialise ---------------------------------------------------- +void CbmFsdMC::Initialize() +{ + // --- Instantiate the output array + fFsdPoints = new TClonesArray("CbmFsdPoint"); + + // --- Call the Initialise method of the mother class + FairDetector::Initialize(); +} +// ------------------------------------------------------------------------- + + +// ----- Public method ProcessHits -------------------------------------- +Bool_t CbmFsdMC::ProcessHits(FairVolume*) +{ + + // No action for neutral particles + if (TMath::Abs(gMC->TrackCharge()) <= 0) return kFALSE; + + // --- If this is the first step for the track in the volume: + // Reset energy loss and store track parameters + if (gMC->IsTrackEntering()) { + fTrackID = gMC->GetStack()->GetCurrentTrackNumber(); + + fAddress = CbmFsdGeoHandler::GetInstance().GetCurrentAddress(gMC); + gMC->TrackPosition(fPos); + gMC->TrackMomentum(fMom); + fTime = gMC->TrackTime() * 1.0e09; + fLength = gMC->TrackLength(); + fEloss = 0.; + } //? track entering + + // --- For all steps within active volume: sum up differential energy loss + fEloss += gMC->Edep(); + + // --- If track is leaving: get track parameters and create CbmstsPoint + if (gMC->IsTrackExiting() || gMC->IsTrackStop() || gMC->IsTrackDisappeared()) { + + // Create CbmFsdPoint + Int_t size = fFsdPoints->GetEntriesFast(); + new ((*fFsdPoints)[size]) CbmFsdPoint(fTrackID, fAddress, fPos.Vect(), fMom.Vect(), fTime, fLength, fEloss); + + // --- Increment number of FsdPoints for this track in the stack + CbmStack* stack = dynamic_cast<CbmStack*>(gMC->GetStack()); + assert(stack); + stack->AddPoint(ECbmModuleId::kFsd); + + } //? track is exiting or stopped + + return kTRUE; +} +// ------------------------------------------------------------------------- + + +// ----- Register the sensitive volumes -------------------------------- +void CbmFsdMC::RegisterSensitiveVolumes(TGeoNode* node) +{ + + TObjArray* daughters = node->GetVolume()->GetNodes(); + for (Int_t iDaughter = 0; iDaughter < daughters->GetEntriesFast(); iDaughter++) { + TGeoNode* daughter = dynamic_cast<TGeoNode*>(daughters->At(iDaughter)); + assert(daughter); + if (daughter->GetNdaughters() > 0) RegisterSensitiveVolumes(daughter); + TGeoVolume* daughterVolume = daughter->GetVolume(); + if (CheckIfSensitive(daughterVolume->GetName())) { AddSensitiveVolume(daughterVolume); } //? Sensitive volume + } //# Daughter nodes +} +// ------------------------------------------------------------------------- + + +ClassImp(CbmFsdMC) diff --git a/sim/detectors/fsd/CbmFsdMC.h b/sim/detectors/fsd/CbmFsdMC.h new file mode 100644 index 0000000000..ea9dbd96a0 --- /dev/null +++ b/sim/detectors/fsd/CbmFsdMC.h @@ -0,0 +1,165 @@ +/* Copyright (C) 2023 Physikalisches Institut Eberhard Karls Universitaet Tuebingen, Tuebingen + SPDX-License-Identifier: GPL-3.0-only + Authors: Yuri Kharlov, Volker Friese, Lukas Chlad [committer] */ + +/** @file CbmFsdMC.h + ** @class CbmFsdMC + ** @brief Class for the MC transport of the CBM-FSD + ** @since 14.07.2023 + ** @author Lukas Chlad <l.chlad@gsi.de> + ** @version 1.0 + ** + ** The CbmFsdMC defines the behaviour of the FSD system during + ** transport simulation. It constructs the FSD transport geometry + ** and creates objects of type CbmFsdPoints. + **/ + + +#ifndef CBMFSDMC_H +#define CBMFSDMC_H 1 + +#include "CbmDefs.h" // for ECbmModuleId + +#include <FairDetector.h> +#include <FairRootManager.h> + +#include <TClonesArray.h> +#include <TLorentzVector.h> +#include <TString.h> + +class FairVolume; + +class CbmFsdMC : public FairDetector { + +public: + /** @brief Constructor + ** @param active If set true, ProcessHits will be called + ** @param name Name of detector object + **/ + CbmFsdMC(Bool_t active = kTRUE, const char* name = "FSDMC") + : FairDetector(name, active, ToIntegralType(ECbmModuleId::kFsd)) {}; + + + /** Destructor **/ + virtual ~CbmFsdMC(); + + /** Prevent copy constructor and assignment operator **/ + CbmFsdMC(const CbmFsdMC&) = delete; + CbmFsdMC operator=(const CbmFsdMC&) = delete; + + + /** @brief Check whether a volume is sensitive. + ** @param(name) Volume name + ** @value kTRUE if volume is sensitive, else kFALSE + ** + ** The decision is based on the volume name (has to contain "scint"). + ** Virtual from FairModule. + **/ + virtual Bool_t IsSensitive(const std::string& name) + { + return (TString(name).Contains("scint", TString::kIgnoreCase) ? kTRUE : kFALSE); + } + + /** @brief Check whether a volume is sensitive. + ** @param(name) Volume name + ** @value kTRUE if volume is sensitive, else kFALSE + ** + ** The decision is based on the volume name (has to contain "scint"). + ** Virtual from FairModule. + **/ + virtual Bool_t CheckIfSensitive(std::string name) { return IsSensitive(name); } + + + /** @brief Construct the FSD geometry in the TGeoManager. + ** + ** Only ROOT geometries are supported. The file must contain a top + ** volume the name of which starts with "fsd" and a TGeoMatrix for + ** the placement of the top fsd volume in the cave. + ** Virtual from FairModule. + **/ + virtual void ConstructGeometry(); + + + /** @brief Action at end of event + ** + ** Short status log and Reset(). + ** Virtual from FairDetector. + **/ + virtual void EndOfEvent(); + + + /** @brief Initialisation + ** + ** The output array is created. Then, the base + ** class method FairDetector::Initialize() is called. + ** Virtual from FairDetector. + **/ + virtual void Initialize(); + + + /** Accessor to the hit collection **/ + /** @brief Get output array of CbmFsdPoints + ** @param iColl Number of collection. Must be zero, since there is only one. + ** @value Pointer to TClonesArray with CbmFsdPoints + **/ + virtual TClonesArray* GetCollection(Int_t iColl) const { return (iColl ? nullptr : fFsdPoints); } + + + /** @brief Screen log + ** Prints current number of StsPoints in array. + ** Virtual from TObject. + **/ + virtual void Print(Option_t* opt = "") const; + + + /** @brief Stepping action + ** @param volume Pointer to the current volume + ** @value Always kTRUE + ** + ** Defines the action to be taken when a step is inside the + ** active volume. Creates CbmFsdPoints and adds them to the + ** collection. + ** Abstract from FairDetector. + **/ + virtual Bool_t ProcessHits(FairVolume* volume = 0); + + + /** @brief Register the output array + ** + ** Abstract from FairDetector. + **/ + virtual void Register() { FairRootManager::Instance()->Register("FsdPoint", GetName(), fFsdPoints, kTRUE); } + + + /** @brief Clear output array + ** + ** Abstract from FairDetector. + **/ + virtual void Reset() { fFsdPoints->Delete(); }; + +private: + TClonesArray* fFsdPoints = nullptr; //! Output array + + /** Track information to be temporarily stored **/ + Int_t fTrackID = -1; //! track index + Int_t fAddress = -1; //! address (module and layer) + TLorentzVector fPos {}; //! position + TLorentzVector fMom {}; //! momentum + Double_t fTime = -1.; //! time + Double_t fLength = -1.; //! length + Double_t fEloss = -1.; //! energy loss + + /** @brief Register all sensitive volumes + ** @param node Pointer to start node + ** + ** Starting from the specified node, the entire node tree is expanded + ** and all volumes which satisfy the CheckIfSensitive() criterion + ** are added to the list of sensitive volumes. + */ + void RegisterSensitiveVolumes(TGeoNode* node); + + ClassDef(CbmFsdMC, 1) +}; + + +#endif //? CBMFSDMC_H diff --git a/sim/detectors/fsd/CbmFsdSimLinkDef.h b/sim/detectors/fsd/CbmFsdSimLinkDef.h new file mode 100644 index 0000000000..50dd400024 --- /dev/null +++ b/sim/detectors/fsd/CbmFsdSimLinkDef.h @@ -0,0 +1,15 @@ +/* Copyright (C) 2023 Physikalisches Institut Eberhard Karls Universitaet Tuebingen, Tuebingen + SPDX-License-Identifier: GPL-3.0-only + Authors: Florian Uhlig, Lukas Chlad [committer] */ + +#ifdef __CINT__ + +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; + +#pragma link C++ class CbmFsdMC; +#pragma link C++ class CbmDigitize < CbmFsdDigi> + ; +#pragma link C++ class CbmFsdDigitize + ; + +#endif diff --git a/sim/response/CMakeLists.txt b/sim/response/CMakeLists.txt index 88992d439d..3594a5d75b 100644 --- a/sim/response/CMakeLists.txt +++ b/sim/response/CMakeLists.txt @@ -24,6 +24,7 @@ set(PRIVATE_DEPENDENCIES CbmMuchSim CbmMvdSim CbmPsdSim + CbmFsdSim CbmRichSim CbmSimSteer CbmStsSim diff --git a/sim/response/base/CbmDigitization.cxx b/sim/response/base/CbmDigitization.cxx index d59f860a08..5cbc82caca 100644 --- a/sim/response/base/CbmDigitization.cxx +++ b/sim/response/base/CbmDigitization.cxx @@ -11,6 +11,7 @@ #include "CbmBmonDigitize.h" #include "CbmDigitizationSource.h" +#include "CbmFsdDigitize.h" #include "CbmMuchDigitizeGem.h" #include "CbmMvdDigitizer.h" #include "CbmPsdSimpleDigitizer.h" @@ -183,6 +184,11 @@ Int_t CbmDigitization::CreateDefaultDigitizers() ss << "TOF "; nDigis++; break; + case ECbmModuleId::kFsd: + fDigitizers[system]->SetDigitizer(new CbmFsdDigitize()); + ss << "FSD "; + nDigis++; + break; case ECbmModuleId::kPsd: fDigitizers[system]->SetDigitizer(new CbmPsdSimpleDigitizer()); ss << "PSD "; @@ -291,6 +297,7 @@ void CbmDigitization::DefaultInit() // --- Add default parameter files for TRD and TOF TString tofGeo = GetGeoTag(ECbmModuleId::kTof, gGeoManager); TString trdGeo = GetGeoTag(ECbmModuleId::kTrd, gGeoManager); + TString fsdGeo = GetGeoTag(ECbmModuleId::kFsd, gGeoManager); TString srcDir = gSystem->Getenv("VMCWORKDIR"); // top source directory TString parFile; if (trdGeo.Length() > 0) { @@ -307,6 +314,10 @@ void CbmDigitization::DefaultInit() parFile = srcDir + "/parameters/tof/tof_" + tofGeo + ".digibdf.par"; AddParameterAsciiFile(parFile); } + if (fsdGeo.Length() > 0) { + parFile = srcDir + "/parameters/fsd/fsd_" + fsdGeo + ".digi.par"; + AddParameterAsciiFile(parFile); + } delete rtdb; delete parIoRoot; @@ -484,6 +495,7 @@ void CbmDigitization::SetDefaultBranches() fDigitizers[ECbmModuleId::kMuch] = new CbmDigitizeInfo(ECbmModuleId::kMuch, "MuchPoint"); fDigitizers[ECbmModuleId::kTrd] = new CbmDigitizeInfo(ECbmModuleId::kTrd, "TrdPoint"); fDigitizers[ECbmModuleId::kTof] = new CbmDigitizeInfo(ECbmModuleId::kTof, "TofPoint"); + fDigitizers[ECbmModuleId::kFsd] = new CbmDigitizeInfo(ECbmModuleId::kFsd, "FsdPoint"); fDigitizers[ECbmModuleId::kPsd] = new CbmDigitizeInfo(ECbmModuleId::kPsd, "PsdPoint"); fDigitizers[ECbmModuleId::kT0] = new CbmDigitizeInfo(ECbmModuleId::kT0, ""); } diff --git a/sim/transport/base/CbmMCEventFilter.cxx b/sim/transport/base/CbmMCEventFilter.cxx index 13eac68091..963788b7fe 100644 --- a/sim/transport/base/CbmMCEventFilter.cxx +++ b/sim/transport/base/CbmMCEventFilter.cxx @@ -82,6 +82,7 @@ InitStatus CbmMCEventFilter::Init() GetBranch(ECbmDataType::kMuchPoint); GetBranch(ECbmDataType::kTrdPoint); GetBranch(ECbmDataType::kTofPoint); + GetBranch(ECbmDataType::kFsdPoint); GetBranch(ECbmDataType::kPsdPoint); return kSUCCESS; @@ -118,6 +119,7 @@ TString CbmMCEventFilter::GetBranchName(ECbmDataType type) const case ECbmDataType::kMuchPoint: name = "MuchPoint"; break; case ECbmDataType::kTrdPoint: name = "TrdPoint"; break; case ECbmDataType::kTofPoint: name = "TofPoint"; break; + case ECbmDataType::kFsdPoint: name = "FsdPoint"; break; case ECbmDataType::kPsdPoint: name = "PsdPoint"; break; default: name = ""; break; } @@ -159,6 +161,7 @@ std::string CbmMCEventFilter::Statistics() const if (fData.at(ECbmDataType::kMuchPoint)) ss << "MUCH " << GetNofData(ECbmDataType::kMuchPoint) << " "; if (fData.at(ECbmDataType::kTrdPoint)) ss << "TRD " << GetNofData(ECbmDataType::kTrdPoint) << " "; if (fData.at(ECbmDataType::kTofPoint)) ss << "TOF " << GetNofData(ECbmDataType::kTofPoint) << " "; + if (fData.at(ECbmDataType::kFsdPoint)) ss << "FSD " << GetNofData(ECbmDataType::kFsdPoint) << " "; if (fData.at(ECbmDataType::kPsdPoint)) ss << "PSD " << GetNofData(ECbmDataType::kPsdPoint) << " "; return ss.str(); diff --git a/sim/transport/base/CbmStack.cxx b/sim/transport/base/CbmStack.cxx index 331496716d..c08d1a33f9 100644 --- a/sim/transport/base/CbmStack.cxx +++ b/sim/transport/base/CbmStack.cxx @@ -221,7 +221,7 @@ void CbmStack::FillTrackArray() fIndexMap[indexP] = indexT; // Set the number of points in the detectors for this track - for (ECbmModuleId detector = ECbmModuleId::kRef; detector <= ECbmModuleId::kPsd; ++detector) { + for (ECbmModuleId detector = ECbmModuleId::kRef; detector <= ECbmModuleId::kNofSystems; ++detector) { auto it = fPointsMap.find(make_pair(indexP, detector)); if (it != fPointsMap.end()) track->SetNPoints(detector, it->second); } //# detectors diff --git a/sim/transport/geosetup/CMakeLists.txt b/sim/transport/geosetup/CMakeLists.txt index b850211673..bf2b2155a8 100644 --- a/sim/transport/geosetup/CMakeLists.txt +++ b/sim/transport/geosetup/CMakeLists.txt @@ -34,6 +34,7 @@ set(PRIVATE_DEPENDENCIES CbmMvdSim CbmPassive CbmPsdSim + CbmFsdSim CbmRichSim CbmSimBase CbmStsSim diff --git a/sim/transport/geosetup/CbmGeoSetupDbProvider.cxx b/sim/transport/geosetup/CbmGeoSetupDbProvider.cxx index ca4943f4fd..0900029093 100644 --- a/sim/transport/geosetup/CbmGeoSetupDbProvider.cxx +++ b/sim/transport/geosetup/CbmGeoSetupDbProvider.cxx @@ -27,9 +27,9 @@ namespace std::map<Int_t, ECbmModuleId> dbToCbmModuleIdMap = { {0, ECbmModuleId::kCave}, {1, ECbmModuleId::kMagnet}, {2, ECbmModuleId::kPipe}, {4, ECbmModuleId::kMvd}, {8, ECbmModuleId::kSts}, {16, ECbmModuleId::kRich}, - {32, ECbmModuleId::kTrd}, {64, ECbmModuleId::kTof}, {128, ECbmModuleId::kPsd}, + {32, ECbmModuleId::kTrd}, {64, ECbmModuleId::kTof}, {128, ECbmModuleId::kFsd}, {256, ECbmModuleId::kPlatform}, {512, ECbmModuleId::kMuch}, {1024, ECbmModuleId::kHodo}, - {2048, ECbmModuleId::kTarget}, {4096, ECbmModuleId::kShield}, + {2048, ECbmModuleId::kTarget}, {4096, ECbmModuleId::kShield}, {8192, ECbmModuleId::kPsd}, }; /// Default path to field directory diff --git a/sim/transport/geosetup/CbmGeoSetupProvider.cxx b/sim/transport/geosetup/CbmGeoSetupProvider.cxx index c7070dab7d..8a76d708a5 100644 --- a/sim/transport/geosetup/CbmGeoSetupProvider.cxx +++ b/sim/transport/geosetup/CbmGeoSetupProvider.cxx @@ -25,6 +25,7 @@ #include "FairRunSim.h" #include <Logger.h> //#include "CbmEcal.h" +#include "CbmFsdMC.h" #include "CbmPsdMC.h" //#include "CbmShield.h" #include "CbmPlatform.h" @@ -44,7 +45,7 @@ namespace ECbmModuleId::kCave, ECbmModuleId::kMagnet, ECbmModuleId::kPipe, ECbmModuleId::kTarget, // ECbmModuleId::kMvd, ECbmModuleId::kSts, ECbmModuleId::kRich, ECbmModuleId::kMuch, ECbmModuleId::kTrd, ECbmModuleId::kTof, ECbmModuleId::kEcal, ECbmModuleId::kPsd, ECbmModuleId::kMvd, ECbmModuleId::kSts, ECbmModuleId::kRich, ECbmModuleId::kMuch, ECbmModuleId::kTrd, - ECbmModuleId::kTof, ECbmModuleId::kPsd, + ECbmModuleId::kTof, ECbmModuleId::kPsd, ECbmModuleId::kFsd, // ECbmModuleId::kHodo, ECbmModuleId::kShield, ECbmModuleId::kPlatform }; ECbmModuleId::kHodo, ECbmModuleId::kPlatform}; } @@ -106,7 +107,7 @@ void CbmGeoSetupProvider::RegisterSetup() for (auto& string : _geom) { LOG(info) << "-I- RegisterSetup: Registering " << modulName << " " << _tag[counter] - << ((moduleId >= ECbmModuleId::kMvd && moduleId <= ECbmModuleId::kPsd) + << ((moduleId >= ECbmModuleId::kMvd && moduleId <= ECbmModuleId::kNofSystems) ? (isActive ? " -ACTIVE- " : " - INACTIVE- ") : "") << " using " << string; @@ -131,8 +132,9 @@ void CbmGeoSetupProvider::RegisterSetup() fairModule = new CbmTof("TOF", isActive); break; // case ECbmModuleId::kEcal: fairModule = new CbmEcal("Ecal", isActive); break; - case ECbmModuleId::kPsd: - fairModule = new CbmPsdMC(isActive); + case ECbmModuleId::kPsd: fairModule = new CbmPsdMC(isActive); break; + case ECbmModuleId::kFsd: + fairModule = new CbmFsdMC(isActive); break; // case ECbmModuleId::kShield: fairModule = new CbmShield("SHIELD"); break; case ECbmModuleId::kPlatform: fairModule = new CbmPlatform("PLATFORM"); break; diff --git a/sim/transport/geosetup/CbmGeoSetupRepoProvider.cxx b/sim/transport/geosetup/CbmGeoSetupRepoProvider.cxx index b4c5af593e..cde422eedc 100644 --- a/sim/transport/geosetup/CbmGeoSetupRepoProvider.cxx +++ b/sim/transport/geosetup/CbmGeoSetupRepoProvider.cxx @@ -68,6 +68,7 @@ namespace {ECbmModuleId::kTof, {"tofGeoTag", "tof", "tof", "TOF"}}, // { ECbmModuleId::kEcal, {"ecalGeoTag", "ecal", "ecal", "ECAL"} }, {ECbmModuleId::kPsd, {"psdGeoTag", "psd", "psd", "PSD"}}, + {ECbmModuleId::kFsd, {"fsdGeoTag", "fsd", "fsd", "FSD"}}, {ECbmModuleId::kHodo, {"hodoGeoTag", "sts", "sts", "HODO"}}, {ECbmModuleId::kShield, {"shieldGeoTag", "much", "shield", "SHIELD"}}, diff --git a/sim/transport/steer/CbmTransportConfig.cxx b/sim/transport/steer/CbmTransportConfig.cxx index bcf54bcbc1..85384e8cdd 100644 --- a/sim/transport/steer/CbmTransportConfig.cxx +++ b/sim/transport/steer/CbmTransportConfig.cxx @@ -67,6 +67,7 @@ CbmTransportConfig::TagSet_t CbmTransportConfig::GetValidationTags() "geometry.subsystems.trd", "geometry.subsystems.tof", "geometry.subsystems.psd", + "geometry.subsystems.fsd", "geometry.subsystems.hodo", "geometry.subsystems.shield", "geometry.subsystems.platform", -- GitLab