From 3767a70832e38d8f8c6fc2300f2becb37e67507c Mon Sep 17 00:00:00 2001 From: "s.zharko@gsi.de" <s.zharko@gsi.de> Date: Wed, 28 Jun 2023 20:30:41 +0200 Subject: [PATCH] CA: Config and uniform distribution for ideal hit finder --- core/base/CbmMatchRecoToMC.cxx | 30 +-- core/base/CbmMatchRecoToMC.h | 8 +- core/base/CbmTrackingDetectorInterfaceBase.h | 2 +- core/data/tof/CbmTofHit.cxx | 1 + macro/CMakeLists.txt | 1 + macro/L1/CMakeLists.txt | 1 + macro/L1/configs/CMakeLists.txt | 4 + macro/L1/configs/README | 8 + macro/L1/configs/config_ideal_hits_mcbm.yaml | 42 ++++ macro/mcbm/mcbm_reco_event.C | 17 +- macro/qa/qa_compare_ca.C | 45 ++++ macro/run/run_reco.C | 34 --- reco/L1/L1Algo/utils/CaAlgoRandom.h | 20 +- reco/L1/utils/CbmCaIdealHitProducer.cxx | 42 +--- reco/L1/utils/CbmCaIdealHitProducer.h | 21 +- reco/L1/utils/CbmCaIdealHitProducerDet.h | 231 ++++++++++++------- 16 files changed, 314 insertions(+), 193 deletions(-) create mode 100644 macro/L1/CMakeLists.txt create mode 100644 macro/L1/configs/CMakeLists.txt create mode 100644 macro/L1/configs/README create mode 100644 macro/L1/configs/config_ideal_hits_mcbm.yaml create mode 100644 macro/qa/qa_compare_ca.C diff --git a/core/base/CbmMatchRecoToMC.cxx b/core/base/CbmMatchRecoToMC.cxx index a01144afa2..3e11ab73f4 100644 --- a/core/base/CbmMatchRecoToMC.cxx +++ b/core/base/CbmMatchRecoToMC.cxx @@ -118,7 +118,7 @@ InitStatus CbmMatchRecoToMC::Init() ReadAndCreateDataBranches(); // Notification to a user about matching suppression - if (fbSuppressMatching) { + if (fbSuppressReMatching) { std::stringstream msg; msg << "\033[1;31mCbmMatchRecoToMC (\"" << fName << "\"): the cluster and hit matching routines for MVD, STS, "; msg << "MuCh, TRD, TOF will be suppressed by a request from CbmMatchRecoToMC::SuppressHitMatching():\033[0m\n"; @@ -130,7 +130,7 @@ InitStatus CbmMatchRecoToMC::Init() void CbmMatchRecoToMC::Exec(Option_t* /*opt*/) { - if (!fbSuppressMatching) { + if (!fbSuppressReMatching) { if (fMvdHitMatches != nullptr) fMvdHitMatches->Delete(); if (fMvdClusterMatches != nullptr) fMvdClusterMatches->Delete(); if (fStsClusterMatches != nullptr) fStsClusterMatches->Delete(); @@ -149,7 +149,7 @@ void CbmMatchRecoToMC::Exec(Option_t* /*opt*/) // ----- MVD ----- - if (!fbSuppressMatching) { + if (!fbSuppressReMatching) { // MVD: digi->hit if (fMvdHits && fMvdHitMatches && !fMvdCluster) { MatchHitsMvd(fMvdHits, fMvdHitMatches); } else { @@ -161,7 +161,7 @@ void CbmMatchRecoToMC::Exec(Option_t* /*opt*/) } // ----- STS ----- - if (!fbSuppressMatching) { + if (!fbSuppressReMatching) { // STS: digi->cluster MatchClusters(ECbmModuleId::kSts, fStsClusters, fStsClusterMatches); // STS: cluster->hit @@ -171,7 +171,7 @@ void CbmMatchRecoToMC::Exec(Option_t* /*opt*/) MatchStsTracks(fMvdHitMatches, fStsHitMatches, fMvdPoints, fStsPoints, fStsTracks, fStsTrackMatches); // ----- MUCH ----- - if (!fbSuppressMatching) { + if (!fbSuppressReMatching) { // MUCH: digi->cluster MatchClusters(ECbmModuleId::kMuch, fMuchClusters, fMuchClusterMatches); // MUCH: cluster->hit @@ -188,19 +188,19 @@ void CbmMatchRecoToMC::Exec(Option_t* /*opt*/) // TRD if (fTrdClusters && fTrdHits) { // MC->digi->cluster->hit->track - if (!fbSuppressMatching) { + if (!fbSuppressReMatching) { MatchClusters(ECbmModuleId::kTrd, fTrdClusters, fTrdClusterMatches); MatchHits(fTrdClusterMatches, fTrdHits, fTrdHitMatches); } MatchTracks(fTrdHitMatches, fTrdPoints, fTrdTracks, fTrdTrackMatches); } else if (fTrdHits) { // MC->hit->track - if (!fbSuppressMatching) { MatchHitsToPoints(fTrdPoints, fTrdHits, fTrdHitMatches); } + if (!fbSuppressReMatching) { MatchHitsToPoints(fTrdPoints, fTrdHits, fTrdHitMatches); } MatchTracks(fTrdHitMatches, fTrdPoints, fTrdTracks, fTrdTrackMatches); } // TOF: (Digi->MC)+(Hit->Digi)=>(Hit->MC) - if (!fbSuppressMatching) { MatchHitsTof(fTofHitDigiMatches, fTofHits, fTofHitMatches); } + if (!fbSuppressReMatching) { MatchHitsTof(fTofHitDigiMatches, fTofHits, fTofHitMatches); } //static Int_t eventNo = 0; LOG(info) << "CbmMatchRecoToMC::Exec eventNo=" << fEventNumber++; } @@ -236,7 +236,7 @@ void CbmMatchRecoToMC::ReadAndCreateDataBranches() if (nullptr != fStsClusters) { fStsClusterMatches = static_cast<TClonesArray*>(ioman->GetObject("StsClusterMatch")); if (nullptr == fStsClusterMatches) { - fbSuppressMatching = false; // Never the less, do matching, because there are no matches + fbSuppressReMatching = false; // Ensure, that matching is done, if matches are absent fStsClusterMatches = new TClonesArray("CbmMatch", 100); ioman->Register("StsClusterMatch", "STS", fStsClusterMatches, IsOutputBranchPersistent("StsClusterMatch")); } @@ -246,7 +246,7 @@ void CbmMatchRecoToMC::ReadAndCreateDataBranches() if (nullptr != fStsHits) { fStsHitMatches = static_cast<TClonesArray*>(ioman->GetObject("StsHitMatch")); if (nullptr == fStsHitMatches) { - fbSuppressMatching = false; // Never the less, do matching, because there are no matches + fbSuppressReMatching = false; // Ensure, that matching is done, if matches are absent fStsHitMatches = new TClonesArray("CbmMatch", 100); ioman->Register("StsHitMatch", "STS", fStsHitMatches, IsOutputBranchPersistent("StsHitMatch")); } @@ -280,7 +280,7 @@ void CbmMatchRecoToMC::ReadAndCreateDataBranches() if (nullptr != fTrdClusters) { fTrdClusterMatches = static_cast<TClonesArray*>(ioman->GetObject("TrdClusterMatch")); if (nullptr == fTrdClusterMatches) { - fbSuppressMatching = false; // Never the less, do matching, because there are no matches + fbSuppressReMatching = false; // Ensure, that matching is done, if matches are absent fTrdClusterMatches = new TClonesArray("CbmMatch", 100); ioman->Register("TrdClusterMatch", "TRD", fTrdClusterMatches, IsOutputBranchPersistent("TrdClusterMatch")); } @@ -290,7 +290,7 @@ void CbmMatchRecoToMC::ReadAndCreateDataBranches() if (nullptr != fTrdHits) { fTrdHitMatches = static_cast<TClonesArray*>(ioman->GetObject("TrdHitMatch")); if (nullptr == fTrdHitMatches) { - fbSuppressMatching = false; // Never the less, do matching, because there are no matches + fbSuppressReMatching = false; // Ensure, that matching is done, if matches are absent fTrdHitMatches = new TClonesArray("CbmMatch", 100); ioman->Register("TrdHitMatch", "TRD", fTrdHitMatches, IsOutputBranchPersistent("TrdHitMatch")); } @@ -314,7 +314,7 @@ void CbmMatchRecoToMC::ReadAndCreateDataBranches() if (nullptr != fMuchClusters) { fMuchClusterMatches = static_cast<TClonesArray*>(ioman->GetObject("MuchClusterMatch")); if (nullptr == fMuchClusterMatches) { - fbSuppressMatching = false; // Never the less, do matching, because there are no matches + fbSuppressReMatching = false; // Ensure, that matching is done, if matches are absent fMuchClusterMatches = new TClonesArray("CbmMatch", 100); ioman->Register("MuchClusterMatch", "MUCH", fMuchClusterMatches, IsOutputBranchPersistent("MuchClusterMatch")); } @@ -324,7 +324,7 @@ void CbmMatchRecoToMC::ReadAndCreateDataBranches() if (nullptr != fMuchPixelHits) { fMuchPixelHitMatches = static_cast<TClonesArray*>(ioman->GetObject("MuchPixelHitMatch")); if (nullptr == fMuchPixelHitMatches) { - fbSuppressMatching = false; // Never the less, do matching, because there are no matches + fbSuppressReMatching = false; // Ensure, that matching is done, if matches are absent fMuchPixelHitMatches = new TClonesArray("CbmMatch", 100); ioman->Register("MuchPixelHitMatch", "MUCH", fMuchPixelHitMatches, IsOutputBranchPersistent("MuchPixelHitMatch")); } @@ -346,6 +346,7 @@ void CbmMatchRecoToMC::ReadAndCreateDataBranches() if (nullptr != fMvdCluster) { fMvdClusterMatches = static_cast<TClonesArray*>(ioman->GetObject("MvdClusterMatch")); if (nullptr == fMvdClusterMatches) { + fbSuppressReMatching = false; // Ensure, that matching is done, if matches are absent fMvdClusterMatches = new TClonesArray("CbmMatch", 100); ioman->Register("MvdClusterMatch", "MVD", fMvdClusterMatches, IsOutputBranchPersistent("MvdClusterMatch")); } @@ -355,6 +356,7 @@ void CbmMatchRecoToMC::ReadAndCreateDataBranches() if (nullptr != fMvdHits) { fMvdHitMatches = static_cast<TClonesArray*>(ioman->GetObject("MvdHitMatch")); if (nullptr == fMvdHitMatches) { + fbSuppressReMatching = false; // Ensure, that matching is done, if matches are absent fMvdHitMatches = new TClonesArray("CbmMatch", 100); ioman->Register("MvdHitMatch", "MVD", fMvdHitMatches, IsOutputBranchPersistent("MvdHitMatch")); } diff --git a/core/base/CbmMatchRecoToMC.h b/core/base/CbmMatchRecoToMC.h index f093b98ec2..b686757696 100644 --- a/core/base/CbmMatchRecoToMC.h +++ b/core/base/CbmMatchRecoToMC.h @@ -135,14 +135,14 @@ public: ** of the branch is absent (and the corresponding cluster and hit branches are present), the flag will be set to ** false, and the cluster/hit matching will be executed. **/ - void SuppressReMatching() { fbSuppressMatching = true; } + void SuppressReMatching() { fbSuppressReMatching = true; } private: static Int_t fEventNumber; - Bool_t fIsMvdActive = kTRUE; // is the Mvd module active - Bool_t fbDigiExpUsed = kTRUE; // Usage of CbmTofDigiExp instead of CbmTofDigi - bool fbSuppressMatching = false; // Suppression of MC->hit matching, if the matches are already there + Bool_t fIsMvdActive = kTRUE; // is the Mvd module active + Bool_t fbDigiExpUsed = kTRUE; // Usage of CbmTofDigiExp instead of CbmTofDigi + bool fbSuppressReMatching = false; // Suppression of MC->hit matching, if the matches are already there CbmMCDataArray* fMCTracks = nullptr; //! Monte-Carlo tracks CbmDigiManager* fDigiManager = nullptr; //! Interface to digi branches diff --git a/core/base/CbmTrackingDetectorInterfaceBase.h b/core/base/CbmTrackingDetectorInterfaceBase.h index c96a2457f7..2f53e4a81c 100644 --- a/core/base/CbmTrackingDetectorInterfaceBase.h +++ b/core/base/CbmTrackingDetectorInterfaceBase.h @@ -148,7 +148,7 @@ public: /// Checks detector interface: boundary conditions of the parameters bool Check() const; - /// Prints all the parameters into table and saves the table as a strinG + /// Prints all the parameters into table and saves the table as a string std::string ToString() const; protected: diff --git a/core/data/tof/CbmTofHit.cxx b/core/data/tof/CbmTofHit.cxx index 1d8cf94803..fda9f18278 100644 --- a/core/data/tof/CbmTofHit.cxx +++ b/core/data/tof/CbmTofHit.cxx @@ -69,6 +69,7 @@ string CbmTofHit::ToString() const ss << "CbmTofHit: address=" << GetAddress() << " pos=(" << GetX() << "," << GetY() << "," << GetZ() << ") err=(" << GetDx() << "," << GetDy() << "," << GetDz() << ") dxy=" << GetDxy() //<< " refId=" << GetRefId() << Form(" time=%8.2f", GetTime()) << " flag=" << GetFlag(); + // << " channel=" << GetCh(); // << endl; return ss.str(); } diff --git a/macro/CMakeLists.txt b/macro/CMakeLists.txt index 4cb8c24a73..32422c037a 100644 --- a/macro/CMakeLists.txt +++ b/macro/CMakeLists.txt @@ -2,6 +2,7 @@ add_subdirectory(run) add_subdirectory(qa) add_subdirectory(mcbm) +add_subdirectory(L1) add_subdirectory(mvd) add_subdirectory(much) add_subdirectory(include) diff --git a/macro/L1/CMakeLists.txt b/macro/L1/CMakeLists.txt new file mode 100644 index 0000000000..bbc2a4ac08 --- /dev/null +++ b/macro/L1/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(configs) diff --git a/macro/L1/configs/CMakeLists.txt b/macro/L1/configs/CMakeLists.txt new file mode 100644 index 0000000000..2d297127cd --- /dev/null +++ b/macro/L1/configs/CMakeLists.txt @@ -0,0 +1,4 @@ +Install(FILES config_ideal_hits_mcbm.yaml + DESTINATION share/cbmroot/macro/L1/configs + ) +#Install(DIRECTORY modules DESTINATION share/cbmroot/macro/L1/configs) diff --git a/macro/L1/configs/README b/macro/L1/configs/README new file mode 100644 index 0000000000..94b5e815e9 --- /dev/null +++ b/macro/L1/configs/README @@ -0,0 +1,8 @@ +DIRECTORY: ${VMCWORKDIR}/macro/L1/configs + +DESCRIPTION: + Directory to store example configuration files, related to CA tracking. + +FILES: + config_ideal_hits_mcbm.yaml + Example of a configuration file for the cbm::ca::IdealHitProducer task for mCBM. diff --git a/macro/L1/configs/config_ideal_hits_mcbm.yaml b/macro/L1/configs/config_ideal_hits_mcbm.yaml new file mode 100644 index 0000000000..6d21e28eff --- /dev/null +++ b/macro/L1/configs/config_ideal_hits_mcbm.yaml @@ -0,0 +1,42 @@ +# Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt +# SPDX-License-Identifier: GPL-3.0-only +# Authors: Sergei Zharko [committer] +# +## @file CbmCaIdealHitProducerConfig.yaml +## @brief Configuration file for ideal hit producers +## @since 28.06.2023 +## @author Sergei Zharko <s.zharko@gsi.de> + +ideal_hit_producer: + # + # Flags are defined for each station + # 0 - real hits + # 1 - real hit position and time are adjusted with MC (exact quantity values are used) + # 2 - real hit position and time are adjusted with MC (true values are smeared within corresponding error) + # 3 - ideal hits are created (exact quantity values are used) + # 4 - ideal hits are created (true values are smeared withing errors, defined in section parameters) + flags: + sts: + 0: 0 + 1: 0 + trd: + 0: 0 + 1: 0 + 2: 0 + # + # Notes: + # 1) For MVD, MuCh, TRD and TOF du corresponds to dx, and dv corresponds to dy + # 2) Spatial errors are expressed in cm, time errors are expressed in ns + # 3) pdf stands for probability density function + # + # Available PDFs: + # g: bounded gaussian distribution + # u: uniform distribution + parameters: + sts: + 0: { du: { value: 1.e-3, pdf: g }, dv: { value: 1.e-3, pdf: g }, dt: { value: 5., pdf: g }} + 1: { du: { value: 1.e-3, pdf: g }, dv: { value: 1.e-3, pdf: g }, dt: { value: 5., pdf: g }} + trd: + 0: { du: { value: .1, pdf: g }, dv: { value: .1, pdf: g }, dt: { value: 10., pdf: g }} + 1: { du: { value: .1, pdf: g }, dv: { value: .1, pdf: u }, dt: { value: 10., pdf: g }} + 2: { du: { value: .1, pdf: u }, dv: { value: .1, pdf: g }, dt: { value: 10., pdf: g }} diff --git a/macro/mcbm/mcbm_reco_event.C b/macro/mcbm/mcbm_reco_event.C index b2ad563f1f..6d80f6d61a 100644 --- a/macro/mcbm/mcbm_reco_event.C +++ b/macro/mcbm/mcbm_reco_event.C @@ -372,22 +372,7 @@ void mcbm_reco_event(Int_t nEvents = 10, TString dataset = "data/test", if (debugWithMC) { auto* pIdealHitProducer = new cbm::ca::IdealHitProducer("IdealHitProducer", 3); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 0, true); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 1, true); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTrd, 0, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTrd, 1, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTrd, 2, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTof, 0, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTof, 1, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTof, 2, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTof, 3, false); - //pIdealHitProducer->CreateNewHits(L1DetectorID::kSts, 0, true, 1.e-3, 1.e-3, 5.); - //pIdealHitProducer->CreateNewHits(L1DetectorID::kSts, 1, true, 1.e-3, 1.e-3, 5.); - //pIdealHitProducer->CreateNewHits(L1DetectorID::kTrd, 0, true, .1, .1, 10.); - //pIdealHitProducer->CreateNewHits(L1DetectorID::kTrd, 1, true, .1, .1, 10.); - //pIdealHitProducer->CreateNewHits(L1DetectorID::kTrd, 2, false, .1, .1, 10.); - //pIdealHitProducer->CreateNewHits(L1DetectorID::kTrd, 1, false, .1, .1, 10.); - //pIdealHitProducer->CreateNewHits(L1DetectorID::kTrd, 2, false, .1, .1, 10.); + pIdealHitProducer->SetConfigName(srcDir + "/macro/L1/configs/config_ideal_hits_mcbm.yaml"); //run->AddTask(pIdealHitProducer); } diff --git a/macro/qa/qa_compare_ca.C b/macro/qa/qa_compare_ca.C new file mode 100644 index 0000000000..3bc59effd5 --- /dev/null +++ b/macro/qa/qa_compare_ca.C @@ -0,0 +1,45 @@ +/* Copyright (C) 2023 GSI Helmholtzzentrum fuer Schwerionenforschung, Darmstadt + SPDX-License-Identifier: GPL-3.0-only + Authors: Sergei Zharko [committer] */ + +/// @file qa_compare_ca.C +/// @author Sergei Zharko <s.zharko@gsi.de> +/// @since 22.06.2023 +/// @brief ROOT macro to run QA-Checker framework comparison of the old and new ROOT-file versions (CA). + +/// @brief Function to compare two different versions of ROOT-files +/// @param configName Name of config containing file-object map +/// @param outputName Name of the QA-Checker output (default is "QaCheckerResult.root") +/// @return Result flag: +/// - 0: all objects are the same within defined comparison procedure (point-by-point for now) +/// - 1: some of the objects differ + + +/// NOTE: Disable clang formatting to keep easy parameters overview +/* clang-format off */ +int qa_compare_ca( + const char* configName = "objects2.yaml", + const char* outputName = "QACheckerOutput.root" // TODO: Add tag of a merge request or commit + ) +/* clang-format on */ +{ + // ----- Logger settings + FairLogger::GetLogger()->SetLogScreenLevel("INFO"); + FairLogger::GetLogger()->SetColoredLog(true); + + //// ----- Style settings + gStyle->SetPalette(kRainBow); + + //// ----- Configure QA-Checker + auto pQaChecker = std::make_unique<cbm::qa::checker::Core>(); + pQaChecker->RegisterOutFile(outputName); // Set name of the output file + pQaChecker->SetFromYAML(configName); // Read file-object map + + //// ----- Run comparision routine + pQaChecker->Process("P"); + + //// ----- Scan results + bool res = pQaChecker->Scan(); // true - objects are the same, false - objects differ + std::cout << "Macro finished successfully." << std::endl; + return !res; +} diff --git a/macro/run/run_reco.C b/macro/run/run_reco.C index 71b5c867fb..9f3be86520 100644 --- a/macro/run/run_reco.C +++ b/macro/run/run_reco.C @@ -387,40 +387,6 @@ void run_reco(TString input = "", Int_t nTimeSlices = -1, Int_t firstTimeSlice = auto kalman = new CbmKF(); run->AddTask(kalman); - if (debugWithMC) { - auto* pIdealHitProducer = new cbm::ca::IdealHitProducer("IdealHitProducer", 3); - for (int iSt = 0; iSt < 8; ++iSt) { - if (iSt == 2) continue; - pIdealHitProducer->CreateNewHits(L1DetectorID::kSts, iSt, false, 1.e-3, 1.e-3, 5.); - } - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 0, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 1, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 2, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 3, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 4, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 5, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 6, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kSts, 7, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 0, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 1, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 2, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 3, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 4, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 5, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 6, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 7, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 8, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 9, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 10, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kMuch, 11, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTrd, 0, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTrd, 1, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTrd, 2, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTrd, 3, false); - //pIdealHitProducer->AdjustExistingHits(L1DetectorID::kTof, 0, false); - //run->AddTask(pIdealHitProducer); - } - // L1 tracking auto l1 = (debugWithMC) ? new CbmL1("CA", 2, 3) : new CbmL1("CA"); diff --git a/reco/L1/L1Algo/utils/CaAlgoRandom.h b/reco/L1/L1Algo/utils/CaAlgoRandom.h index d506496c5c..ba3dd2a702 100644 --- a/reco/L1/L1Algo/utils/CaAlgoRandom.h +++ b/reco/L1/L1Algo/utils/CaAlgoRandom.h @@ -59,13 +59,21 @@ namespace ca::algo void SetSeed(int seed); /// @brief Returns a normally distributed random value, limited within a selected sigma range - /// @tparam T Type of floating point + /// @tparam T Type of floating point numbers /// @param mean Mean of the distribution /// @param sigma Sigma of the distribution /// @param nSigmas Half-width of the generated numbers domain, expressed in number of sigmas template<typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true> T BoundedGaus(const T& mean, const T& sigma, const T& nSigmas) const; + /// @brief Returns a random value, addressed with a continuous uniform distribution + /// @tparam T Type of floating point numbers + /// @param mean Mean of the distribution + /// @param sigma Sigma of the distribution + template<typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true> + T Uniform(const T& mean, const T& sigma) const; + + private: mutable GeneratorType_t fGenerator; ///< Random number generator unsigned int fSeed = 1; ///< Random number seed @@ -93,5 +101,15 @@ T ca::algo::Random::BoundedGaus(const T& mean, const T& sigma, const T& nSigmas) return res; } +// --------------------------------------------------------------------------------------------------------------------- +// +template<typename T, std::enable_if_t<std::is_floating_point<T>::value, bool>> +T ca::algo::Random::Uniform(const T& mean, const T& sigma) const +{ + LOG_IF(fatal, !(sigma > 0 && std::isfinite(sigma))) << "ca::algo::Random::Uniform sigma = " << sigma << " is illegal"; + std::uniform_real_distribution rnd {-sigma * std::sqrt(3) + mean, sigma * std::sqrt(3) + mean}; + return rnd(fGenerator); +} + #endif // CaAlgoRandom_h diff --git a/reco/L1/utils/CbmCaIdealHitProducer.cxx b/reco/L1/utils/CbmCaIdealHitProducer.cxx index 873787954d..441dc328b2 100644 --- a/reco/L1/utils/CbmCaIdealHitProducer.cxx +++ b/reco/L1/utils/CbmCaIdealHitProducer.cxx @@ -11,40 +11,11 @@ #include "CbmSetup.h" + using cbm::ca::IdealHitProducer; ClassImp(cbm::ca::IdealHitProducer); -// --------------------------------------------------------------------------------------------------------------------- -// -void IdealHitProducer::AdjustExistingHits(L1DetectorID detID, int iSt, bool ifSmear) -{ - switch (detID) { - case L1DetectorID::kMvd: fHitProducerMvd.AdjustExistingHits(iSt, ifSmear); break; - case L1DetectorID::kSts: fHitProducerSts.AdjustExistingHits(iSt, ifSmear); break; - case L1DetectorID::kMuch: fHitProducerMuch.AdjustExistingHits(iSt, ifSmear); break; - case L1DetectorID::kTrd: fHitProducerTrd.AdjustExistingHits(iSt, ifSmear); break; - case L1DetectorID::kTof: fHitProducerTof.AdjustExistingHits(iSt, ifSmear); break; - case L1DetectorID::kEND: - LOG(fatal) << fName << "::AdjustExistingHits(): L1DetectorID::kEND cannot be passed as a detID"; - } -} - -// --------------------------------------------------------------------------------------------------------------------- -// -void IdealHitProducer::CreateNewHits(L1DetectorID detID, int iSt, bool ifSmear, double du, double dv, double dt) -{ - switch (detID) { - case L1DetectorID::kMvd: fHitProducerMvd.CreateNewHits(iSt, ifSmear, du, dv, dt); break; - case L1DetectorID::kSts: fHitProducerSts.CreateNewHits(iSt, ifSmear, du, dv, dt); break; - case L1DetectorID::kMuch: fHitProducerMuch.CreateNewHits(iSt, ifSmear, du, dv, dt); break; - case L1DetectorID::kTrd: fHitProducerTrd.CreateNewHits(iSt, ifSmear, du, dv, dt); break; - case L1DetectorID::kTof: fHitProducerTof.CreateNewHits(iSt, ifSmear, du, dv, dt); break; - case L1DetectorID::kEND: - LOG(fatal) << fName << "::AdjustExistingHits(): L1DetectorID::kEND cannot be passed as a detID"; - } -} - // --------------------------------------------------------------------------------------------------------------------- // InitStatus IdealHitProducer::Init() @@ -75,3 +46,14 @@ void IdealHitProducer::Exec(Option_t* option) if (fbUseDet[L1DetectorID::kTrd]) { fHitProducerTrd.Exec(option); } if (fbUseDet[L1DetectorID::kTof]) { fHitProducerTof.Exec(option); } } + +// --------------------------------------------------------------------------------------------------------------------- +// +void IdealHitProducer::SetConfigName(const char* name) +{ + fHitProducerMvd.SetConfigName(name); + fHitProducerSts.SetConfigName(name); + fHitProducerMuch.SetConfigName(name); + fHitProducerTrd.SetConfigName(name); + fHitProducerTof.SetConfigName(name); +} diff --git a/reco/L1/utils/CbmCaIdealHitProducer.h b/reco/L1/utils/CbmCaIdealHitProducer.h index 6530c0de5a..0b5e175317 100644 --- a/reco/L1/utils/CbmCaIdealHitProducer.h +++ b/reco/L1/utils/CbmCaIdealHitProducer.h @@ -15,6 +15,8 @@ #include "FairTask.h" +#include <string> + namespace cbm::ca { /// @brief Ideal hit producer task for CA tracking @@ -40,21 +42,6 @@ namespace cbm::ca /// @brief Move assignment operator IdealHitProducer& operator=(IdealHitProducer&&) = delete; - /// @brief Sets a mode to adjust existing hits to MC points for a selected tracking station - /// @param detID Detector ID - /// @param iSt Index of station - /// @param ifSmear Flag: true - MC true position and time are smeared within error - void AdjustExistingHits(L1DetectorID detID, int iSt, bool ifSmear); - - /// @brief Sets a mode to create hits from MC points for a selected tracking station - /// @param detID Detector ID - /// @param iSt Index of station - /// @param ifSmear Flag: true - MC true position and time are smeared within error - /// @param du Error of u-coordinate measurement [cm] - /// @param dv Error of v-coordinate measurement [cm] - /// @param dt Error of time measurement [ns] - void CreateNewHits(L1DetectorID detID, int iSt, bool ifSmear, double du, double dv, double dt); - /// @brief Initialization of the task InitStatus Init(); @@ -64,6 +51,10 @@ namespace cbm::ca /// @brief Execution of the task void Exec(Option_t* option); + /// @brief Sets YAML configuration file with defined smearing parameters + /// @param name Name of the configuration file + void SetConfigName(const char* name); + ClassDef(IdealHitProducer, 1); private: diff --git a/reco/L1/utils/CbmCaIdealHitProducerDet.h b/reco/L1/utils/CbmCaIdealHitProducerDet.h index cd40487f4f..b4f28a8be3 100644 --- a/reco/L1/utils/CbmCaIdealHitProducerDet.h +++ b/reco/L1/utils/CbmCaIdealHitProducerDet.h @@ -36,10 +36,7 @@ #include "CbmTrdPoint.h" #include "CbmTrdTrackingInterface.h" -<<<<<<< HEAD #include "FairRootManager.h" -======= ->>>>>>> CA: Bugfix in ideal hit finder #include "FairTask.h" #include "Logger.h" @@ -47,9 +44,14 @@ #include "TVector3.h" #include <array> +#include <optional> +#include <sstream> +#include <string> #include <tuple> #include <unordered_map> +#include <yaml-cpp/yaml.h> + #include "CaAlgoRandom.h" #include "L1Constants.h" #include "L1Def.h" @@ -84,19 +86,6 @@ namespace cbm::ca /// @brief Move assignment operator IdealHitProducerDet& operator=(IdealHitProducerDet&&) = delete; - /// @brief Sets a mode to adjust existing hits to MC points for a selected tracking station - /// @param iSt Index of station - /// @param ifSmear Flag: true - MC true position and time are smeared within error - void AdjustExistingHits(int iSt, bool ifSmear); - - /// @brief Sets a mode to create hits from MC points for a selected tracking station - /// @param iSt Index of station - /// @param ifSmear Flag: true - MC true position and time are smeared within error - /// @param du Error of u-coordinate measurement [cm] - /// @param dv Error of v-coordinate measurement [cm] - /// @param dt Error of time measurement [ns] - void CreateNewHits(int iSt, bool ifSmear, double du, double dv, double dt); - /// @brief Initialization of the task InitStatus Init(); @@ -110,6 +99,10 @@ namespace cbm::ca /// @param seed Random seed void SetRandomSeed(int seed) { fRandom.SetSeed(seed); } + /// @brief Sets YAML configuration file name + /// @param name Name of the configuration file + void SetConfigName(const char* name) { fsConfigName = name; } + private: static constexpr double kHitWSize = 3.5; ///< half-width for the bounded gaussian [sigma] @@ -118,34 +111,42 @@ namespace cbm::ca /// @return link to matched point std::optional<CbmLink> GetMatchedPointLink(int iH); + /// @brief Parses the YAML configuration file + void ParseConfig(); + /// @brief Pushes back a hit into the hits branch /// @param pHit Pointer to source hit void PushBackHit(const Hit_t* pHit); + /// @brief Smears the value by a given standard deviation with a selected function + /// @param value Value to be smeared + /// @param sigma Value of the standard deviation + /// @param opt Function (0 - BoundedGaus, 1 - Uniform) + void SmearValue(double& value, double sigma, int opt); /// @brief A structure to keep hit adjustment/creation settings for each station - struct StationSetting { + struct HitParameters { double fDu = undef::kD; ///< Error of u-coordinate measurement [cm] double fDv = undef::kD; ///< Error of v-coordinate measurement [cm] double fDt = undef::kD; ///< Error of time measurement [ns] + /// PDFs selection for different quantities + /// - 0: Bounded Gaussian distribution + /// - 1: Uniform distribution + short fPdfU = -1; + short fPdfV = -1; + short fPdfT = -1; + /// @brief Mode: - /// - 0: do nothing with hits - /// - 1: adjust measured hits with matched point info (hit errors used) - /// - 2: create new hits from points + /// - 0: real hits + /// - 1: existing hits are improved from MC points + /// - 2: new hits are created from MC points short fMode = 0; /// @brief Flag: /// - true: MC point quantities are smeared with gaussian using error /// - false: Precise MC point quantities are used bool fbSmear = false; - - /// @brief String representation of the structure object - /// @param verbose Verbosity level: - /// - 0: prints nothing - /// - 1: prints one-line log - /// - 2: prints verbose log - std::string ToString(int verbose = 1) const; }; CbmTrackingDetectorInterfaceBase* fpDetInterface = nullptr; ///< Detector interface @@ -162,13 +163,16 @@ namespace cbm::ca TClonesArray* fpBrHitsTmp = nullptr; ///< Temporary array of hits TClonesArray* fpBrHitMatchesTmp = nullptr; ///< Temporary array of hit matches - std::unordered_map<int, StationSetting> fmStationPars; ///< List of settings vs. tracking station + std::string fsConfigName = ""; ///< Name of configuration file + + std::vector<HitParameters> fvStationPars; ///< Parameters, stored for each station ::ca::algo::Random fRandom {1}; ///< Random generator /// @brief Management flag, which does run the routine if there was a request bool fbRunTheRoutine = true; + int fHitCounter = 0; ///< Hit counter in a new branch }; @@ -195,31 +199,6 @@ namespace cbm::ca } } - // ------------------------------------------------------------------------------------------------------------------ - // - template<L1DetectorID DetID> - void IdealHitProducerDet<DetID>::AdjustExistingHits(int iSt, bool ifSmear) - { - StationSetting pars {}; - pars.fMode = 1; - pars.fbSmear = ifSmear; - fmStationPars[iSt] = pars; - } - - // ------------------------------------------------------------------------------------------------------------------ - // - template<L1DetectorID DetID> - void IdealHitProducerDet<DetID>::CreateNewHits(int iSt, bool ifSmear, double du, double dv, double dt) - { - StationSetting pars {}; - pars.fMode = 2; - pars.fbSmear = ifSmear; - pars.fDu = du; - pars.fDv = dv; - pars.fDt = dt; - fmStationPars[iSt] = pars; - } - // ------------------------------------------------------------------------------------------------------------------ // template<L1DetectorID DetID> @@ -293,26 +272,21 @@ namespace cbm::ca } // ------ Checks of the settings of hit creation/adjustment mode - int nStations = fpDetInterface->GetNtrackingStations(); - for (int iSt = 0; iSt < nStations; ++iSt) { - if (fmStationPars.find(iSt) == fmStationPars.end()) { - StationSetting pars {}; - pars.fMode = 0; - fmStationPars[iSt] = pars; - } + if (fsConfigName.size() != 0) { + this->ParseConfig(); + // Skip event/time slice processing, if there are no requests for hit modification of the detector + // (fbRunTheRoutine = true, if there is at least one station with fMode > 0) + fbRunTheRoutine = + std::any_of(fvStationPars.begin(), fvStationPars.end(), [](const auto& p) { return p.fMode > 0; }); + } + else { + fbRunTheRoutine = false; } - - // Skip event/time slice processing, if there are no requests for hit modification of the detector - // (fbRunTheRoutine = true, if there is at least one station with fMode > 0) - fbRunTheRoutine = - std::any_of(fmStationPars.begin(), fmStationPars.end(), [](const auto& p) { return p.second.fMode > 0; }); std::stringstream msg; msg << "\033[1;31mATTENTION! IDEAL HIT PRODUCER IS USED FOR " << kDetName[DetID] << "\033[0m"; - LOG_IF(info, fbRunTheRoutine) << msg.str(); - return kSUCCESS; } catch (const std::logic_error& error) { @@ -321,6 +295,94 @@ namespace cbm::ca return kERROR; } + // ------------------------------------------------------------------------------------------------------------------- + // + template<L1DetectorID DetID> + void IdealHitProducerDet<DetID>::ParseConfig() + { + int nStations = fpDetInterface->GetNtrackingStations(); + fvStationPars.clear(); + fvStationPars.resize(nStations); + + // Read file + YAML::Node config; + try { + config = YAML::LoadFile(fsConfigName)["ideal_hit_producer"]; + + std::string detBranchName = ""; + if constexpr (L1DetectorID::kMvd == DetID) { detBranchName = "mvd"; } + else if constexpr (L1DetectorID::kSts == DetID) { + detBranchName = "sts"; + } + else if constexpr (L1DetectorID::kMuch == DetID) { + detBranchName = "much"; + } + else if constexpr (L1DetectorID::kTrd == DetID) { + detBranchName = "trd"; + } + else if constexpr (L1DetectorID::kTof == DetID) { + detBranchName = "tof"; + } + + const auto& parNode = config["parameters"][detBranchName]; + const auto& flagNode = config["flags"][detBranchName]; + + for (int iSt = 0; iSt < nStations; ++iSt) { + auto& par = fvStationPars[iSt]; + auto& node = parNode[iSt]; + short mode = flagNode[iSt].as<int>(0); + if (mode > 0) { + par.fDu = node["du"]["value"].as<double>(); + switch (node["du"]["pdf"].as<char>()) { + case 'g': par.fPdfU = 0; break; + case 'u': par.fPdfU = 1; break; + default: par.fPdfU = -1; break; + } + par.fDv = node["dv"]["value"].as<double>(); + switch (node["dv"]["pdf"].as<char>()) { + case 'g': par.fPdfV = 0; break; + case 'u': par.fPdfV = 1; break; + default: par.fPdfV = -1; break; + } + par.fDt = node["dt"]["value"].as<double>(); + switch (node["dt"]["pdf"].as<char>()) { + case 'g': par.fPdfT = 0; break; + case 'u': par.fPdfT = 1; break; + default: par.fPdfT = -1; break; + } + switch (mode) { + case 1: + par.fMode = 1; + par.fbSmear = false; + break; + case 2: + par.fMode = 1; + par.fbSmear = true; + break; + case 3: + par.fMode = 2; + par.fbSmear = false; + break; + case 4: + par.fMode = 2; + par.fbSmear = true; + break; + } + } + } + } + catch (const YAML::BadFile& err) { + std::stringstream msg; + msg << "YAML configuration file " << fsConfigName << " does not exist"; + throw std::runtime_error(msg.str()); + } + catch (const YAML::ParserException& err) { + std::stringstream msg; + msg << "YAML configuration file " << fsConfigName << " is formatted improperly"; + throw std::runtime_error(msg.str()); + } + } + // ------------------------------------------------------------------------------------------------------------------- // template<L1DetectorID DetID> @@ -393,6 +455,18 @@ namespace cbm::ca return std::nullopt; } + // ------------------------------------------------------------------------------------------------------------------- + // + template<L1DetectorID DetID> + void IdealHitProducerDet<DetID>::SmearValue(double& value, double sigma, int opt) + { + switch (opt) { + case 0: value += fRandom.BoundedGaus<double>(0., sigma, kHitWSize); break; + case 1: value += fRandom.Uniform<double>(0., sigma); break; + default: LOG(fatal) << "IdealHitProducerDet::SmearValue: illegal option: opt = " << opt; + } + } + // ------------------------------------------------------------------------------------------------------------------- // template<L1DetectorID DetID> @@ -426,7 +500,7 @@ namespace cbm::ca // Get setting int iSt = fpDetInterface->GetTrackingStationIndex(pHit); - const auto& setting = fmStationPars.at(iSt); + const auto& setting = fvStationPars[iSt]; // Skip hits from stations, where new hits are to be created from points if (setting.fMode == 2) { continue; } @@ -462,17 +536,18 @@ namespace cbm::ca double t = pPoint->GetTime() + fpMCEventList->GetEventTime(link); if (setting.fbSmear) { - auto dt = pHit->GetTimeError(); - auto du = pHit->GetDx(); - auto dv = pHit->GetDy(); + double dt = pHit->GetTimeError(); + double du = pHit->GetDx(); + double dv = pHit->GetDy(); if constexpr (L1DetectorID::kSts == DetID) { du = pHit->GetDu(); dv = pHit->GetDv(); } auto [u, v] = fpDetInterface->ConvertXYtoUV(iSt, x, y); - u += fRandom.BoundedGaus<double>(0., du, kHitWSize); - v += fRandom.BoundedGaus<double>(0., dv, kHitWSize); - t += fRandom.BoundedGaus<double>(0., dt, kHitWSize); + this->SmearValue(u, du, setting.fPdfU); + this->SmearValue(v, dv, setting.fPdfV); + this->SmearValue(t, dt, setting.fPdfT); + std::tie(x, y) = fpDetInterface->ConvertUVtoXY(iSt, u, v); } pHit->SetX(x); @@ -505,7 +580,7 @@ namespace cbm::ca for (int iP = 0; iP < nPoints; ++iP) { auto* pPoint = static_cast<Point_t*>(fpBrPoints->Get(fileId, eventId, iP)); int iSt = fpDetInterface->GetTrackingStationIndex(pPoint->GetDetectorID()); - const auto& setting = fmStationPars.at(iSt); + const auto& setting = fvStationPars[iSt]; if (setting.fMode != 2) { continue; } double du = setting.fDu; double dv = setting.fDv; @@ -534,9 +609,9 @@ namespace cbm::ca if (setting.fbSmear) { auto [u, v] = fpDetInterface->ConvertXYtoUV(iSt, x, y); // TODO: Provide more realistic profiles for TRD - u += fRandom.BoundedGaus<double>(0., du, kHitWSize); - v += fRandom.BoundedGaus<double>(0., dv, kHitWSize); - t += fRandom.BoundedGaus<double>(0., dt, kHitWSize); + this->SmearValue(u, du, setting.fPdfU); + this->SmearValue(v, dv, setting.fPdfV); + this->SmearValue(t, dt, setting.fPdfT); std::tie(x, y) = fpDetInterface->ConvertUVtoXY(iSt, u, v); } pos.SetX(x); -- GitLab