diff --git a/reco/kf/CMakeLists.txt b/reco/kf/CMakeLists.txt index 0bc036a5d297f3619c0ae68f70c68776414cf240..9a5e8b40448fcddabfdd3c1ebce03f8acd373d32 100644 --- a/reco/kf/CMakeLists.txt +++ b/reco/kf/CMakeLists.txt @@ -3,6 +3,7 @@ set(INCLUDE_DIRECTORIES ) set(SRCS + ${CMAKE_CURRENT_SOURCE_DIR}/CbmKfTarget.cxx ${CMAKE_CURRENT_SOURCE_DIR}/CbmKfTrackingSetupInitializer.cxx ) @@ -68,6 +69,7 @@ install(TARGETS CbmKf DESTINATION lib) install( FILES + CbmKfTarget.h CbmKfTrackingSetupInitializer.h DESTINATION include/ diff --git a/reco/kf/CbmKfTarget.cxx b/reco/kf/CbmKfTarget.cxx new file mode 100644 index 0000000000000000000000000000000000000000..a572edec2a9abc90a5807ed8c76c1b6a2e7c44b1 --- /dev/null +++ b/reco/kf/CbmKfTarget.cxx @@ -0,0 +1,97 @@ +/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CbmKfTarget.h +/// \brief Target property initialization and access in CBM (source) +/// \since 02.09.2024 +/// \author Sergei Zharko <s.zharko@gsi.de> + +// TODO: Move this class somewhere in the cbmroot/core + +#include "CbmKfTarget.h" + +#include "Logger.h" +#include "TGeoManager.h" +#include "TGeoNode.h" +#include "TGeoTube.h" +#include "TGeoVolume.h" + +#include <iomanip> + +using cbm::kf::Target; + +Target* Target::fpInstance{nullptr}; +std::mutex Target::fMutex; + +// --------------------------------------------------------------------------------------------------------------------- +// +Target* Target::Instance() +{ + std::lock_guard<std::mutex> lock(fMutex); + if (!fpInstance) { + fpInstance = new Target(); + fpInstance->Init(); + } + return fpInstance; +} + +// --------------------------------------------------------------------------------------------------------------------- +// +void Target::Init() +{ + if (!gGeoManager) { + throw std::logic_error("cbm::kf::Target: the TGeoManager instance is not initialized on this step. Please be " + "ensured to call the Target::Init() after the TGeoManager initialization."); + } + + std::function<void(TString&, TGeoNode*)> FindTargetNode = [&](TString& targetPath, TGeoNode* targetNode) -> void { + if (!targetNode) { // init at the top of the tree + targetNode = gGeoManager->GetTopNode(); + targetPath = "/" + TString(targetNode->GetName()); + } + + if (TString(targetNode->GetName()).Contains("target")) { + return; + } + + for (Int_t iNode = 0; iNode < targetNode->GetNdaughters(); ++iNode) { + TGeoNode* newNode = targetNode->GetDaughter(iNode); + TString newPath = targetPath + "/" + newNode->GetName(); + FindTargetNode(newPath, newNode); + if (newNode) { + targetPath = newPath; + targetNode = newNode; + return; + } + } + targetPath = ""; + targetNode = nullptr; + }; + + TString targetPath; + TGeoNode* pTargetNode{nullptr}; + FindTargetNode(targetPath, pTargetNode); + + if (!pTargetNode) { + throw std::runtime_error("cbm::kf::Target: the target node is not found in the setup"); + } + + Double_t local[3] = {0., 0., 0.}; // target centre, local c.s. + Double_t global[3] = {0}; // target centre, global c.s. + gGeoManager->cd(targetPath); + gGeoManager->GetCurrentMatrix()->LocalToMaster(local, global); + fX = global[0]; + fY = global[1]; + fZ = global[2]; + + if (const auto* pTube = dynamic_cast<TGeoTube*>(pTargetNode->GetVolume()->GetShape())) { + fDz = pTube->GetDz(); + fRmax = pTube->GetRmax(); + } + else { + throw std::logic_error("cbm::kf::Target: target is supposed to be a Tube, but it is not. Please, " + "provide a proper handling of the new target shape (return it's reference central point " + "and half of its thickness)"); + } +} diff --git a/reco/kf/CbmKfTarget.h b/reco/kf/CbmKfTarget.h new file mode 100644 index 0000000000000000000000000000000000000000..2440ad513e264b7b2bbd25075174e40661e65ad8 --- /dev/null +++ b/reco/kf/CbmKfTarget.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2024 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// \file CbmKfTarget.h +/// \brief Target property initialization and access in CBM (header) +/// \since 02.09.2024 +/// \author Sergei Zharko <s.zharko@gsi.de> + +// TODO: Move this class somewhere in the cbmroot/core + +#pragma once + +#include "KfDefs.h" + +#include <mutex> + +namespace cbm::kf +{ + /// \class Target + /// \brief CBM target accessor and property handler + class Target { + public: + /// \brief Gets target center x-coordinate [cm] + double GetX() const { return fX; } + + /// \brief Gets target center y-coordinate [cm] + double GetY() const { return fY; } + + /// \brief Gets target center z-coordinate [cm] + double GetZ() const { return fZ; } + + /// \brief Gets target half thickness [cm] + double GetDz() const { return fDz; } + + /// \brief Gets target transverse size [cm] + double GetRmax() const { return fRmax; } + + /// \brief Instance access + static Target* Instance(); + + // Copy and move elimination + Target(const Target&) = delete; + Target(Target&&) = delete; + Target& operator=(const Target&) = delete; + Target& operator=(Target&&) = delete; + + protected: + /// \brief Default constructor + Target() = default; + + /// \brief Destructor + ~Target() = default; + + /// \brief Target initializer + void Init(); + + double fX{cbm::algo::kf::defs::Undef<double>}; ///< reference x-coordinate of the target position [cm] + double fY{cbm::algo::kf::defs::Undef<double>}; ///< reference y-coordinate of the target position [cm] + double fZ{cbm::algo::kf::defs::Undef<double>}; ///< reference z-coordinate of the target position [cm] + double fDz{cbm::algo::kf::defs::Undef<double>}; ///< target half-thickness [cm] + double fRmax{cbm::algo::kf::defs::Undef<double>}; ///< target transverse size [cm] + + private: + static Target* fpInstance; + static std::mutex fMutex; + }; +} // namespace cbm::kf diff --git a/reco/kf/CbmKfTrackingSetupInitializer.cxx b/reco/kf/CbmKfTrackingSetupInitializer.cxx index bb6f465d3a1f0a1307093f487822b5d0055259a2..4a418301bca9f8fe4d37442764546ae914f4a346 100644 --- a/reco/kf/CbmKfTrackingSetupInitializer.cxx +++ b/reco/kf/CbmKfTrackingSetupInitializer.cxx @@ -9,6 +9,7 @@ #include "CbmKfTrackingSetupInitializer.h" +#include "CbmKfTarget.h" #include "CbmMuchTrackingInterface.h" #include "CbmMvdTrackingInterface.h" #include "CbmSetup.h" @@ -19,10 +20,6 @@ #include "FairRunAna.h" #include "KfDefs.h" #include "KfMaterialMapCreator.h" -#include "TGeoManager.h" -#include "TGeoNode.h" -#include "TGeoTube.h" -#include "TGeoVolume.h" #include <functional> @@ -85,26 +82,26 @@ try { CollectStations(fbUseTof ? CbmTofTrackingInterface::Instance() : nullptr); // Retriev target properties - // TODO: Provide some beter handler for target properties access - auto [targX, targY, targZ, targHalfThick, targRadius] = this->GetTarget(); + const auto* pTarget = Target::Instance(); // Init material map creator MaterialMapCreator materialCreator{}; materialCreator.SetSafeMaterialInitialization(kMatCreatorSafeMode); - materialCreator.SetDoRadialProjection(targZ); + materialCreator.SetDoRadialProjection(pTarget->GetZ()); materialCreator.SetNraysPerDim(kMatCreatorNrays); // Target initialization - double zLast = targZ + targHalfThick + kTargMaterialOffset; // z-coordinate of the target material upper limit + double zLast = + pTarget->GetZ() + pTarget->GetDz() + kTargMaterialOffset; // z-coordinate of the target material upper limit { // Material of the target - double xyMax{1.3 * targRadius}; + double xyMax{1.3 * pTarget->GetRmax()}; int nBins{std::min(static_cast<int>(std::ceil(2. * xyMax / kMatCreatorPitch)), kMatCreatorMaxNbins)}; assert(nBins > 0); - double zFirst{targZ - targHalfThick}; // z-coordinate of the target material lower limit + double zFirst{pTarget->GetZ() + pTarget->GetDz()}; // z-coordinate of the target material lower limit LOG(info) << "- collecting target material (z = " << zFirst << " - " << zLast << ", size = " << xyMax << ")\n"; - this->SetTargetProperties(targX, targY, targZ, kTargFieldInitStep, - materialCreator.GenerateMaterialMap(targZ, zFirst, zLast, xyMax, nBins)); + this->SetTargetProperties(pTarget->GetX(), pTarget->GetY(), pTarget->GetZ(), kTargFieldInitStep, + materialCreator.GenerateMaterialMap(pTarget->GetZ(), zFirst, zLast, xyMax, nBins)); } // Material and field layers initialization @@ -142,59 +139,3 @@ void TrackingSetupInitializer::Use(bool mvd, bool sts, bool much, bool trd, bool fbUseTrd = trd; fbUseTof = tof; } - -// --------------------------------------------------------------------------------------------------------------------- -// -std::tuple<double, double, double, double, double> TrackingSetupInitializer::GetTarget() -{ - std::function<void(TString&, TGeoNode*)> FindTargetNode = [&](TString& targetPath, TGeoNode* targetNode) -> void { - if (!targetNode) { // init at the top of the tree - targetNode = gGeoManager->GetTopNode(); - targetPath = "/" + TString(targetNode->GetName()); - } - - if (TString(targetNode->GetName()).Contains("target")) { - return; - } - - for (Int_t iNode = 0; iNode < targetNode->GetNdaughters(); ++iNode) { - TGeoNode* newNode = targetNode->GetDaughter(iNode); - TString newPath = targetPath + "/" + newNode->GetName(); - FindTargetNode(newPath, newNode); - if (newNode) { - targetPath = newPath; - targetNode = newNode; - return; - } - } - targetPath = ""; - targetNode = nullptr; - }; - - TString targetPath; - TGeoNode* pTargetNode{nullptr}; - FindTargetNode(targetPath, pTargetNode); - - if (!pTargetNode) { - throw std::runtime_error("kf::TrackingSetupInitializer: target node is not found in the setup"); - } - - Double_t local[3] = {0., 0., 0.}; // target centre, local c.s. - Double_t global[3]; // target centre, global c.s. - gGeoManager->cd(targetPath); - gGeoManager->GetCurrentMatrix()->LocalToMaster(local, global); - - double halfThick{cbm::algo::kf::defs::Undef<double>}; - double outerRadius{cbm::algo::kf::defs::Undef<double>}; - if (const auto* pTube = dynamic_cast<TGeoTube*>(pTargetNode->GetVolume()->GetShape())) { - halfThick = pTube->GetDz(); - outerRadius = pTube->GetRmax(); - } - else { - throw std::logic_error("kf::TrackingSetupInitializer: target is supposed to be a Tube, but it is not. Please, " - "provide a proper handling of the new target shape (return it's reference central point " - "and half of its thickness)"); - } - - return std::make_tuple(local[0], local[1], local[2], halfThick, outerRadius); -} diff --git a/reco/kf/CbmKfTrackingSetupInitializer.h b/reco/kf/CbmKfTrackingSetupInitializer.h index 62f22cb68dd86bdd651eefee671ea0ea961f97ed..4148c1ff636c7410c302217dbf94e6a21fb17185 100644 --- a/reco/kf/CbmKfTrackingSetupInitializer.h +++ b/reco/kf/CbmKfTrackingSetupInitializer.h @@ -19,10 +19,12 @@ namespace cbm::kf /// \brief Encapsulation of the kf::Setup initialization routines for CBM class TrackingSetupInitializer : public cbm::algo::kf::SetupInitializer { public: - /// \brief Default constructor - TrackingSetupInitializer(); - /// \brief Initializes the instance + /// \param mvd Is MVD used + /// \param sts Is STS used + /// \param much Is MuCh used + /// \param trd Is TRD used + /// \param tof Is TOF used bool InitProperties() override; /// \brief Enables/disables detector subsystems in the setup @@ -34,18 +36,13 @@ namespace cbm::kf void Use(bool mvd, bool sts, bool much, bool trd, bool tof); private: - /// \brief Gets target position and half-thickness - /// \return tuple(x, y, z, half-thickness, outer radius) [cm] - std::tuple<double, double, double, double, double> GetTarget(); - // Material map creator properties (TODO: Provide setters, if needed) - static constexpr double kMatCreatorPitch{0.1}; ///< Material budget map minimal bin size [cm] - static constexpr int kMatCreatorMaxNbins{100}; ///< Max number of bins in the material budget map in x(y) axis - static constexpr int kMatCreatorNrays{3}; ///< Number of rays per dimension for the material budget - static constexpr bool kMatCreatorSafeMode{true}; ///< Safe mode of the material map creation - static constexpr double kTargFieldInitStep{2.5}; ///< Step between nodes in the target field initialization [cm] - static constexpr double kTargMaterialOffset{ - 0.2}; ///< Offset between target volume and the corresponding material zMax [cm] + static constexpr double kMatCreatorPitch{0.1}; ///< Material budget map minimal bin size [cm] + static constexpr int kMatCreatorMaxNbins{100}; ///< Max number of bins in the material budget map in x(y) axis + static constexpr int kMatCreatorNrays{3}; ///< Number of rays per dimension for the material budget + static constexpr bool kMatCreatorSafeMode{true}; ///< Safe mode of the material map creation + static constexpr double kTargFieldInitStep{2.5}; ///< Step between nodes in the target field initialization [cm] + static constexpr double kTargMaterialOffset{0.2}; ///< Offset between target upper limit and its material zMax [cm] bool fbUseMvd{false}; ///< Are MVD stations included in the tracking setup bool fbUseSts{false}; ///< Are STS stations included in the tracking setup