From 2bcccc69579ab559654a99829771be6f1e2aafd2 Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Tue, 29 Oct 2024 14:19:01 +0100 Subject: [PATCH] KF: adding the material budget maps cacheing option to the KF-setup builder class --- algo/kf/core/geo/KfSetupBuilder.cxx | 69 +++++++++++++++++++++--- algo/kf/core/geo/KfSetupBuilder.h | 19 ++++++- algo/kf/core/geo/KfTarget.cxx | 11 ++++ algo/kf/core/geo/KfTarget.h | 4 ++ macro/mcbm/mcbm_qa.C | 1 + macro/mcbm/mcbm_reco_event.C | 1 + reco/kfnew/CbmKfTrackingSetupBuilder.cxx | 12 ++++- reco/kfnew/CbmKfTrackingSetupBuilder.h | 10 ++++ 8 files changed, 119 insertions(+), 8 deletions(-) diff --git a/algo/kf/core/geo/KfSetupBuilder.cxx b/algo/kf/core/geo/KfSetupBuilder.cxx index 78767a5a34..0d88a20b1c 100644 --- a/algo/kf/core/geo/KfSetupBuilder.cxx +++ b/algo/kf/core/geo/KfSetupBuilder.cxx @@ -41,8 +41,13 @@ void SetupBuilder::Init() } } + bool bMaterialLoaded{false}; + if (!fsMaterialCacheFile.empty()) { + bMaterialLoaded = this->LoadMaterial(); + } + // Add material to the target: - { + if (!bMaterialLoaded) { // Material budget double zMin{fTarget.GetZ() + kTargetCenterOffset}; double zMax{fTarget.GetZ() + fTarget.GetDz() * kTargetMaterialOffset}; @@ -61,7 +66,9 @@ void SetupBuilder::Init() acceptanceSlope = std::max(acceptanceSlope, tCurr); } - fvMaterial.reserve(fGeoLayers.size()); + if (!bMaterialLoaded) { + fvMaterial.reserve(fGeoLayers.size()); + } double zLast{fTarget.GetZ() + fTarget.GetDz() * kTargetMaterialOffset}; for (auto layerIt = fGeoLayers.cbegin(); layerIt != fGeoLayers.cend(); ++layerIt) { double z1 = layerIt->fZmax; @@ -71,17 +78,25 @@ void SetupBuilder::Init() } double zNew{0.5 * (z1 + z2)}; double xyMax{acceptanceSlope * (layerIt->fZref - fTarget.GetZ())}; - auto material{fpMaterialMapFactory->GenerateMaterialMap(layerIt->fZref, zLast, zNew, xyMax, fMatMapNofBins)}; - fvMaterial.push_back(std::move(material)); + if (!bMaterialLoaded) { + auto material{fpMaterialMapFactory->GenerateMaterialMap(layerIt->fZref, zLast, zNew, xyMax, fMatMapNofBins)}; + fvMaterial.push_back(std::move(material)); + } + // Note: square material maps to follow the material budget map regions fFieldFactory.AddSliceReference(xyMax, xyMax, layerIt->fZref); fModuleIndexFactory.AddComponent<int>(layerIt->fDetID, layerIt->fLocID, layerIt->fZref); zLast = zNew; } } + + if (!bMaterialLoaded && !fsMaterialCacheFile.empty()) { + this->StoreMaterial(); + } + fbIfGeoLayersInit = true; fbReady = true; - LOG(info) << "kf::SetupBuilder initilization: done"; + LOG(info) << "kf::SetupBuilder initialization: done"; } // --------------------------------------------------------------------------------------------------------------------- @@ -98,6 +113,33 @@ std::string SetupBuilder::InitStatusMsg() const return msg.str(); } +// --------------------------------------------------------------------------------------------------------------------- +// +bool SetupBuilder::LoadMaterial() +{ + std::ifstream ifs(fsMaterialCacheFile, std::ios::binary); + if (!ifs) { // File does not exist yet + return false; + } + try { + boost::archive::binary_iarchive ia(ifs); + MaterialMap targetMat; + ia >> targetMat; + ia >> fvMaterial; + fTarget.SetMaterial(targetMat); + // TODO: Provide consistency check (geometry hash) + } + catch (const std::exception& err) { + LOG(warn) << "kf::SetupBuilder::LoadMaterial: input file \"" << fsMaterialCacheFile + << "\" has inconsistent format " + "or was corrupted. The material maps will be generated"; + return false; + } + LOG(info) << "kf::SetupBuilder::LoadMaterial: the material maps were loaded from cache file \"" << fsMaterialCacheFile + << "\""; + return true; +} + // --------------------------------------------------------------------------------------------------------------------- // void SetupBuilder::Reset() @@ -135,9 +177,24 @@ void SetupBuilder::Store(const Setup<double>& setup, const std::string& fileName std::ofstream ofs(fileName, std::ios::binary); if (!ofs) { std::stringstream msg; - msg << "kf::SetupBuilder::Store: failed openning file \"" << fileName << "\" to store the setup"; + msg << "kf::SetupBuilder::Store: failed opening file \"" << fileName << "\" to store the setup"; throw std::runtime_error(msg.str()); } boost::archive::binary_oarchive oa(ofs); oa << setup; } + +// --------------------------------------------------------------------------------------------------------------------- +// +void SetupBuilder::StoreMaterial() const +{ + std::ofstream ofs(fsMaterialCacheFile, std::ios::binary); + if (!ofs) { + std::stringstream msg; + msg << "kf::SetupBuilder::Store: failed opening cache file \"" << fsMaterialCacheFile << "\" to store the setup"; + throw std::runtime_error(msg.str()); + } + boost::archive::binary_oarchive oa(ofs); + oa << fTarget.GetMaterial(); + oa << fvMaterial; +} diff --git a/algo/kf/core/geo/KfSetupBuilder.h b/algo/kf/core/geo/KfSetupBuilder.h index 4e360a05e8..649f64e279 100644 --- a/algo/kf/core/geo/KfSetupBuilder.h +++ b/algo/kf/core/geo/KfSetupBuilder.h @@ -120,6 +120,14 @@ namespace cbm::algo::kf fpMaterialMapFactory = pMaterialFactory; } + /// \brief Sets the material budget cache file name + /// \param filename Material budget cache file name + /// + /// If provided, the instance will try to read the material budget maps from the file. If the file does not exist, + /// or the geometry hash was changed since the last time, the material budget maps will be recreated on the flight + /// and stored to the file. + void SetMaterialCacheFile(const std::string& filename) { fsMaterialCacheFile = filename; } + /// \brief Sets target initialization properties /// \param x Target x-coordinate [cm] /// \param y Target y-coordinate [cm] @@ -149,7 +157,7 @@ namespace cbm::algo::kf static Setup<T> Load(const std::string& fileName); private: - /// \brief Initializes, validates and cashes the parameters + /// \brief Initializes, validates and caches the parameters /// \throw std::runtime_error If pre-initialization was incomplete /// \note Does not touch the field function and field type/mode void Init(); @@ -157,6 +165,14 @@ namespace cbm::algo::kf /// \brief Prints initialization status message std::string InitStatusMsg() const; + /// \brief Reads material from file + /// \return true Material budget was read from file + /// \return false Material budget could not read (file does not exist or has incorrect properties) + bool LoadMaterial(); + + /// \brief Stores material to file + void StoreMaterial() const; + // TODO: Define target material more precisely static constexpr double kTargetCenterOffset{0.05}; // Offset from target center [cm] static constexpr double kTargetMaterialOffset{2.}; // Offset of the target material [in dz] @@ -165,6 +181,7 @@ namespace cbm::algo::kf static constexpr int kTargetMaterialMapNofBins{20}; std::set<GeoLayer<int>> fGeoLayers{}; ///< Set of geo layers + std::string fsMaterialCacheFile{""}; ///< A cache file for the material std::vector<MaterialMap> fvMaterial{}; ///< Material map container std::shared_ptr<IMaterialMapFactory> fpMaterialMapFactory{nullptr}; ///< Material map creator ModuleIndexMapFactory fModuleIndexFactory; ///< Module index factory diff --git a/algo/kf/core/geo/KfTarget.cxx b/algo/kf/core/geo/KfTarget.cxx index bc8b00a188..1552f28d1d 100644 --- a/algo/kf/core/geo/KfTarget.cxx +++ b/algo/kf/core/geo/KfTarget.cxx @@ -37,6 +37,17 @@ void Target<T>::SetMaterial(const MaterialMap& material) fMaterial = material; } +// --------------------------------------------------------------------------------------------------------------------- +// +template<typename T> +void Target<T>::SetMaterial(MaterialMap&& material) +{ + if (material.IsUndefined()) { + throw std::logic_error("Target:ReceiveMaterial(): attempt to pass an undefined instance of the material map"); + } + fMaterial = std::move(material); +} + // --------------------------------------------------------------------------------------------------------------------- // template<typename T> diff --git a/algo/kf/core/geo/KfTarget.h b/algo/kf/core/geo/KfTarget.h index e901c6c58f..000828896f 100644 --- a/algo/kf/core/geo/KfTarget.h +++ b/algo/kf/core/geo/KfTarget.h @@ -79,6 +79,10 @@ namespace cbm::algo::kf /// \param material Material map void SetMaterial(const MaterialMap& material); + /// \brief Sets material map (move semantics) + /// \param material Material map + void SetMaterial(MaterialMap&& material); + /// \brief Sets x-coordinate of the nominal target center /// \param x x-coordinate [cm] void SetX(const T& x) { fX = x; } diff --git a/macro/mcbm/mcbm_qa.C b/macro/mcbm/mcbm_qa.C index 8f41a3c635..5310cba1e0 100644 --- a/macro/mcbm/mcbm_qa.C +++ b/macro/mcbm/mcbm_qa.C @@ -135,6 +135,7 @@ void mcbm_qa(Int_t nEvents = 0, gROOT->LoadMacro(setupFile); gROOT->ProcessLine(setupFunct); CbmSetup* setup = CbmSetup::Instance(); + setup->GetProvider()->GetSetup().SetTag(setupName.Data()); // setup->RemoveModule(ECbmModuleId::kTrd); // ------------------------------------------------------------------------ diff --git a/macro/mcbm/mcbm_reco_event.C b/macro/mcbm/mcbm_reco_event.C index 157b7a3580..7ece135982 100644 --- a/macro/mcbm/mcbm_reco_event.C +++ b/macro/mcbm/mcbm_reco_event.C @@ -55,6 +55,7 @@ void mcbm_reco_event(Int_t nEvents = 10, TString dataset = "data/test", gROOT->LoadMacro(setupFile); gROOT->ProcessLine(setupFunct); CbmSetup* setup = CbmSetup::Instance(); + setup->GetProvider()->GetSetup().SetTag(setupName); // setup->RemoveModule(ECbmModuleId::kTrd); // ------------------------------------------------------------------------ diff --git a/reco/kfnew/CbmKfTrackingSetupBuilder.cxx b/reco/kfnew/CbmKfTrackingSetupBuilder.cxx index 1b4a0d62d6..07c29edc06 100644 --- a/reco/kfnew/CbmKfTrackingSetupBuilder.cxx +++ b/reco/kfnew/CbmKfTrackingSetupBuilder.cxx @@ -144,7 +144,17 @@ TrackingSetupBuilder* TrackingSetupBuilder::Instance() if (fpInstance == nullptr) { std::lock_guard<std::mutex> lock(fMutex); fpInstance = new TrackingSetupBuilder{}; - fpInstance->Init(); // Init for the first time? + fpInstance->CheckDetectorPresence(); + + auto setupTag = CbmSetup::Instance()->GetProvider()->GetSetup().GetTag(); + if (setupTag.empty()) { + throw std::logic_error("The setup tag in CbmSetup is not defined"); + } + //TString sinkName = FairRootManager::Instance()->GetSink()->GetFileName(); + + // Creating the cache file in "./", so the macros from different directories could use the same file + std::string sCacheFile = Form("./%s.mat.kf.bin", setupTag.c_str()); + fpInstance->SetMaterialCacheFile(sCacheFile); } return fpInstance; } diff --git a/reco/kfnew/CbmKfTrackingSetupBuilder.h b/reco/kfnew/CbmKfTrackingSetupBuilder.h index 00ab71c5a5..a3d2ff0cec 100644 --- a/reco/kfnew/CbmKfTrackingSetupBuilder.h +++ b/reco/kfnew/CbmKfTrackingSetupBuilder.h @@ -12,6 +12,7 @@ #include "CbmDefs.h" #include "CbmEnumArray.h" #include "KfSetupBuilder.h" +#include "TString.h" #include <mutex> #include <tuple> @@ -50,6 +51,14 @@ namespace cbm::kf TrackingSetupBuilder& operator=(const TrackingSetupBuilder&) = delete; TrackingSetupBuilder& operator=(TrackingSetupBuilder&&) = delete; + /// \brief Sets a name for the material budget cache-file + /// \param filename A name of the file + /// + /// If provided, the instance will try to read the material budget maps from the file. If the file does not exist, + /// or the geometry hash was changed since the last time, the material budget maps will be recreated on the flight + /// and stored to the file. + void SetMaterialCacheFile(const TString& filename) { fBuilder.SetMaterialCacheFile(filename.Data()); } + private: template<typename T> using DetectorIDArray_t = cbm::core::EnumArray<cbm::algo::ca::EDetectorID, T>; @@ -68,6 +77,7 @@ namespace cbm::kf void CheckDetectorPresence(); /// \brief Initializes the instance + /// \note Is executed on the first call of MakeSetup function void Init(); // Material map creator properties (TODO: Provide setters, if needed) -- GitLab