diff --git a/algo/kf/core/geo/KfSetupBuilder.cxx b/algo/kf/core/geo/KfSetupBuilder.cxx index 0d88a20b1c7f89748039e667438338c87587234f..6c300eb53b497a2ede435e70ce3a354cc80889fd 100644 --- a/algo/kf/core/geo/KfSetupBuilder.cxx +++ b/algo/kf/core/geo/KfSetupBuilder.cxx @@ -67,6 +67,7 @@ void SetupBuilder::Init() } if (!bMaterialLoaded) { + fvMaterial.clear(); fvMaterial.reserve(fGeoLayers.size()); } double zLast{fTarget.GetZ() + fTarget.GetDz() * kTargetMaterialOffset}; @@ -124,6 +125,15 @@ bool SetupBuilder::LoadMaterial() try { boost::archive::binary_iarchive ia(ifs); MaterialMap targetMat; + size_t refHash; + ia >> refHash; + if (refHash != fGeoHash) { + LOG(warn) << "kf::SetupBuilder::LoadMaterial: reference hash from input file \"" << fsMaterialCacheFile + << "\" " + "diverges from one, obtained from the actual detector setup geometry. Material budget will be " + "re-generated, and a new file will be created"; + return false; + } ia >> targetMat; ia >> fvMaterial; fTarget.SetMaterial(targetMat); @@ -195,6 +205,7 @@ void SetupBuilder::StoreMaterial() const throw std::runtime_error(msg.str()); } boost::archive::binary_oarchive oa(ofs); + oa << fGeoHash; oa << fTarget.GetMaterial(); oa << fvMaterial; } diff --git a/algo/kf/core/geo/KfSetupBuilder.h b/algo/kf/core/geo/KfSetupBuilder.h index 649f64e279964b3254062819909118c335507337..bebd43ad57779ee75c2d8a0d40bf690efde7e30a 100644 --- a/algo/kf/core/geo/KfSetupBuilder.h +++ b/algo/kf/core/geo/KfSetupBuilder.h @@ -122,11 +122,17 @@ namespace cbm::algo::kf /// \brief Sets the material budget cache file name /// \param filename Material budget cache file name + /// \param refHash Reference hash of the geometry /// /// 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; } + /// and stored to the file. If the reference hash differs from one, read from the file, a warning will be produced, + /// and the new cache file will be generated. + void SetMaterialCacheFile(const std::string& filename, size_t refHash) + { + fsMaterialCacheFile = filename; + fGeoHash = refHash; + } /// \brief Sets target initialization properties /// \param x Target x-coordinate [cm] @@ -187,6 +193,7 @@ namespace cbm::algo::kf ModuleIndexMapFactory fModuleIndexFactory; ///< Module index factory FieldFactory fFieldFactory; ///< Instance of field factory Target<double> fTarget; ///< Target properties + size_t fGeoHash{0}; ///< A hash of the geometry int fMatMapNofBins{100}; ///< Number of bins in material maps bool fbIfTargetSet{false}; ///< Target initialized diff --git a/reco/kfnew/CbmKfTrackingSetupBuilder.cxx b/reco/kfnew/CbmKfTrackingSetupBuilder.cxx index 347f7c6931577ff40b39bc8f6726c92a97fbd114..338a86b63d4ca0ad6974f03ae248b3e5fa91af45 100644 --- a/reco/kfnew/CbmKfTrackingSetupBuilder.cxx +++ b/reco/kfnew/CbmKfTrackingSetupBuilder.cxx @@ -25,6 +25,8 @@ #include "KfMaterialMapFactory.h" #include "Logger.h" +#include <boost/filesystem.hpp> + #include <functional> using cbm::algo::ca::EDetectorID; @@ -134,20 +136,28 @@ catch (const std::exception& err) { // TrackingSetupBuilder* TrackingSetupBuilder::Instance() { + namespace fs = boost::filesystem; if (fpInstance == nullptr) { std::lock_guard<std::mutex> lock(fMutex); fpInstance = new TrackingSetupBuilder{}; fpInstance->CheckDetectorPresence(); + // Retrieve the geometry tag 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); + // Retrieve the data directory (the same as for the sink file) + TString sinkName = FairRootManager::Instance()->GetSink()->GetFileName(); + auto sinkPath = fs::path{sinkName.Data()}; + std::string sDataDir = sinkPath.parent_path().string(); + if (sDataDir.empty()) { + sDataDir = "."; + } + + std::string sCacheFile = Form("%s/%s.mat.kf.bin", sDataDir.c_str(), setupTag.c_str()); + fpInstance->SetMaterialCacheFile(sCacheFile, CbmSetup::Instance()->GetHash()); } return fpInstance; } diff --git a/reco/kfnew/CbmKfTrackingSetupBuilder.h b/reco/kfnew/CbmKfTrackingSetupBuilder.h index a4754c4efee2f0a32a9fd60506281ad701a29a4b..1263cd9e3336865849abb4bd825ce3ece7924cbc 100644 --- a/reco/kfnew/CbmKfTrackingSetupBuilder.h +++ b/reco/kfnew/CbmKfTrackingSetupBuilder.h @@ -54,14 +54,6 @@ 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>; @@ -79,6 +71,19 @@ namespace cbm::kf /// \brief Check detector presence void CheckDetectorPresence(); + /// \brief Sets the material budget cache file name + /// \param filename Material budget cache file name + /// \param geoHash A hash of the geometry + /// + /// 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. If the reference hash differs from one, read from the file, a warning will be produced, + /// and the new cache file will be generated. + void SetMaterialCacheFile(const TString& filename, size_t geoHash) + { + fBuilder.SetMaterialCacheFile(filename.Data(), geoHash); + } + /// \brief Initializes the instance /// \note Is executed on the first call of MakeSetup function void Init(); diff --git a/sim/transport/steer/CbmSetup.cxx b/sim/transport/steer/CbmSetup.cxx index 88ed27f365c69ead1bda4c567e05b5a0c4a6ca86..d8a3480f1dd4e88b96a8034370fa1d0cf4394d38 100644 --- a/sim/transport/steer/CbmSetup.cxx +++ b/sim/transport/steer/CbmSetup.cxx @@ -15,11 +15,8 @@ #include "CbmFieldMapData.h" #include "CbmFieldMapSym2.h" #include "CbmFieldMapSym3.h" - #include "FairModule.h" #include "FairRunSim.h" -#include <Logger.h> - #include "TFile.h" #include "TGeoMatrix.h" #include "TGeoNode.h" @@ -27,8 +24,11 @@ #include "TKey.h" #include "TSystem.h" +#include <Logger.h> + #include <iomanip> #include <sstream> +#include <string> // for std::hash<string_view> using std::string; using std::stringstream; @@ -138,6 +138,24 @@ Bool_t CbmSetup::GetGeoTag(ECbmModuleId moduleId, TString& tag) // ------------------------------------------------------------------------- +// ----- Get a hash of the setup ----------------------------------------- +size_t CbmSetup::GetHash() +{ + // TODO: make all getters constant (up to the CbmGeoSetupModule and co. classes) + std::string hashString{""}; + auto& moduleMap = fProvider->GetSetup().GetModuleMap(); + for (auto& entry : moduleMap) { + if (!hashString.empty()) { + hashString += ";"; + } + hashString += entry.second.GetName() + ":" + entry.second.GetTag(); + } + //LOG(info) << "CbmSetup::GetHash(): " << hashString; + return std::hash<std::string>{}(hashString); +} +// ------------------------------------------------------------------------- + + // ----- Instance ------------------------------------------------------ CbmSetup* CbmSetup::Instance() { diff --git a/sim/transport/steer/CbmSetup.h b/sim/transport/steer/CbmSetup.h index 8ff24d4d008c957884e0132c314b2a081b4d2206..c31338c5a106681a6246fb84a9c515028283a22b 100644 --- a/sim/transport/steer/CbmSetup.h +++ b/sim/transport/steer/CbmSetup.h @@ -96,6 +96,15 @@ public: Bool_t GetGeoFileName(ECbmModuleId moduleId, TString& fileName); + /** Get a hash of the setup + ** @return A 64-bit integer, representing the hash value + ** + ** The hash is formed from a string of pairs "module name -- module tag", separated by semicolon. Only + ** active modules are considered. + **/ + size_t GetHash(); + + /** Get number of modules in the setup ** @value Number of modules in setup **/