From 89dece604a2a697eb333355fd3220605e727075e Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 20 May 2025 00:29:55 +0800 Subject: [PATCH 01/74] feat(DetSimAna): add ChronoAnaElemTool for simulation time analysis - Add new ChronoAnaElemTool class to track simulation time per subdetector and particle type - Implement ntuple recording for time metrics - Include initialization of subdetector names and logging - Update CMakeLists.txt to include new source file --- Simulation/DetSimAna/CMakeLists.txt | 1 + .../DetSimAna/src/ChronoAnaElemTool.cpp | 112 ++++++++++++++++++ Simulation/DetSimAna/src/ChronoAnaElemTool.h | 72 +++++++++++ 3 files changed, 185 insertions(+) create mode 100644 Simulation/DetSimAna/src/ChronoAnaElemTool.cpp create mode 100644 Simulation/DetSimAna/src/ChronoAnaElemTool.h diff --git a/Simulation/DetSimAna/CMakeLists.txt b/Simulation/DetSimAna/CMakeLists.txt index f3daa7f6..c41361dd 100644 --- a/Simulation/DetSimAna/CMakeLists.txt +++ b/Simulation/DetSimAna/CMakeLists.txt @@ -2,6 +2,7 @@ gaudi_add_module(DetSimAna SOURCES src/Edm4hepWriterAnaElemTool.cpp src/ExampleAnaDoseElemTool.cpp + src/ChronoAnaElemTool.cpp LINK DetSimInterface DetSimSDLib ${DD4hep_COMPONENT_LIBRARIES} diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp new file mode 100644 index 00000000..1eb99371 --- /dev/null +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -0,0 +1,112 @@ +#include "ChronoAnaElemTool.h" + +#include "G4Event.hh" +#include "G4Step.hh" +#include "G4String.hh" +#include "GaudiKernel/IChronoSvc.h" +#include "GaudiKernel/INTupleSvc.h" + +#include "DDG4/Geant4Data.h" +#include "G4TransportationManager.hh" +#include "GaudiKernel/ChronoEntity.h" +#include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/NTuple.h" +#include <array> +#include <cassert> +#include <cerrno> +#include <cstddef> +#include <string> + +#include "GaudiAlg/GaudiAlgorithm.h" +#include "GaudiKernel/NTuple.h" + +DECLARE_COMPONENT(ChronoAnaElemTool) + +StatusCode ChronoAnaElemTool::initNtuple() { + bool success = true; + { // Subdet array + NTuplePtr nt(m_ntupleSvc, "ChronoMetrics/SimulationTime/SubDet"); + if (!nt) { + nt = m_ntupleSvc->book("ChronoMetrics/SimulationTime/SubDet", + CLID_ColumnWiseTuple, "SimTime per Subdetector"); + if (!nt) { + return StatusCode::FAILURE; + } + success &= nt->addItem("EventNumber", m_eventNumber); + success &= nt->addItem("TimePerSubdet", m_subdetNames.size(), + m_timePerSubdet, 0.0, 1e6); + } + m_subdetTuple = nt; + } + + { // Particle array + NTuplePtr nt(m_ntupleSvc, "ChronoMetrics/SimulationTime/PdgIdTypes"); + if (!nt) { + nt = m_ntupleSvc->book("ChronoMetrics/SimulationTime/PdgIdTypes", + CLID_ColumnWiseTuple, "SimTime per Particle ID"); + if (!nt) { + return StatusCode::FAILURE; + } + success &= nt->addItem("EventNumber", m_eventNumber); + // record the number of different PDG ID + success &= nt->addItem("NumPdgIdTypes", m_nPdgTypes, 0U, MAX_PDG_TYPES); + // record the PDG ID and time spend on each type of particle + success &= nt->addIndexedItem("PdgIdTypes", m_nPdgTypes, m_pdgIds); + success &= + nt->addIndexedItem("TimePerPdgIdType", m_nPdgTypes, m_timePerPdgType); + } + m_pidTuple = nt; + } + if (!m_subdetTuple || !m_pidTuple || !success) { + return StatusCode::FAILURE; + } else { + return StatusCode::SUCCESS; + } +} + +StatusCode ChronoAnaElemTool::initSubdetNames() { + + // prepare to write out subdet names + m_logFileStream.open(m_writeLogFileName.value(), + std::ios::out | std::ios::trunc); + if (m_logFileStream.fail()) { + error() << "Failed to open output file: " << m_writeLogFileName.value() + << endmsg; + return StatusCode::FAILURE; + } + + const auto &children = m_geomSvc->getDD4HepGeo().children(); + size_t index = 0; + for (const auto &[name, subdet] : children) { + if (subdet.id() < 0) { + continue; + } + m_subdetNames.push_back(name); + m_logFileStream << "# " << index << " " << name << '\n'; + ++index; + } + + m_logFileStream.close(); + return StatusCode::SUCCESS; +} + +StatusCode ChronoAnaElemTool::initialize() { + StatusCode sc; + + // Get services + m_chronoStatSvc = service<IChronoStatSvc>("ChronoStatSvc"); + m_ntupleSvc = service<INTupleSvc>("NTupleSvc"); + m_geomSvc = service<IGeomSvc>("GeomSvc"); + if (!m_chronoStatSvc || !m_ntupleSvc || !m_geomSvc) { + return StatusCode::FAILURE; + } + + // init subdet names and number + sc = initSubdetNames(); + if (sc.isFailure()) { + return sc; + } + // init ntuple for record sim time over subdet and pid + sc = initNtuple(); + return sc; +} diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h new file mode 100644 index 00000000..dce1928b --- /dev/null +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -0,0 +1,72 @@ +#ifndef ChronoAnaElemTool_h +#define ChronoAnaElemTool_h + +#include <array> +#include <chrono> +#include <cstddef> +#include <ratio> +#include <string> +#include <vector> + +#include "DetInterface/IGeomSvc.h" +#include "DetSimInterface/IAnaElemTool.h" +#include "G4VTouchable.hh" +#include "GaudiKernel/AlgTool.h" +#include "GaudiKernel/IChronoStatSvc.h" +#include "GaudiKernel/INTupleSvc.h" +#include "GaudiKernel/NTuple.h" + +class ChronoAnaElemTool : public extends<AlgTool, IAnaElemTool> { + +public: + using extends::extends; + + // Run + virtual void BeginOfRunAction(const G4Run *) override; + + // Event + virtual void BeginOfEventAction(const G4Event *) override; + virtual void EndOfEventAction(const G4Event *) override; + + // Stepping + virtual void UserSteppingAction(const G4Step *) override; + + /// Overriding initialize and finalize + StatusCode initialize() override; + +private: + // methods + StatusCode initNtuple(); + StatusCode initSubdetNames(); + + // variables + SmartIF<IChronoStatSvc> m_chronoStatSvc; + SmartIF<INTupleSvc> m_ntupleSvc; + SmartIF<IGeomSvc> m_geomSvc; + + Gaudi::Property<std::string> m_writeNtupleFileName{ + this, "WriteNtupleFileName", "chrono_stat.root"}; + Gaudi::Property<std::string> m_writeLogFileName{this, "WriteLogFileName", + "chrono_stat.log"}; + std::ofstream m_logFileStream; + + NTuple::Tuple *m_subdetTuple{nullptr}; + NTuple::Tuple *m_pidTuple{nullptr}; + + std::chrono::duration<double, std::micro> m_overhead_time_counter = + std::chrono::duration<double, std::micro>::zero(); + + static const unsigned MAX_PDG_TYPES = 256; + std::vector<std::string> m_subdetNames; + + NTuple::Item<long> m_eventNumber; + NTuple::Array<double> m_timePerSubdet; + // type number of different PDG ID + NTuple::Item<unsigned> m_nPdgTypes; + // array of pdg ids + NTuple::Array<int> m_pdgIds; + // time spend on each type of particle + NTuple::Array<double> m_timePerPdgType; +}; + +#endif -- GitLab From 464e98d663d7bfc01b046b99b0dccd5280ba5110 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 20 May 2025 16:40:59 +0800 Subject: [PATCH 02/74] feat(ChronoAnaElemTool): add event timing tracking and overhead measurement - Add tracking of event simulation time and overhead time in ntuples - Implement per-PDGID and per-subdetector timing measurements - Include overhead time measurement for subdetector name lookup - Remove unused includes and clean up header file --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 143 ++++++++++++++++++ Simulation/DetSimAna/src/ChronoAnaElemTool.h | 17 ++- 2 files changed, 154 insertions(+), 6 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 1eb99371..6ff34ef8 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -11,6 +11,7 @@ #include "GaudiKernel/ChronoEntity.h" #include "GaudiKernel/MsgStream.h" #include "GaudiKernel/NTuple.h" +#include <G4Track.hh> #include <array> #include <cassert> #include <cerrno> @@ -33,6 +34,9 @@ StatusCode ChronoAnaElemTool::initNtuple() { return StatusCode::FAILURE; } success &= nt->addItem("EventNumber", m_eventNumber); + success &= nt->addItem("EventSimTime", m_eventSimTime); // microseconds + success &= + nt->addItem("EventOverheadTime", m_eventOverheadTime); // microseconds success &= nt->addItem("TimePerSubdet", m_subdetNames.size(), m_timePerSubdet, 0.0, 1e6); } @@ -48,6 +52,8 @@ StatusCode ChronoAnaElemTool::initNtuple() { return StatusCode::FAILURE; } success &= nt->addItem("EventNumber", m_eventNumber); + success &= nt->addItem("EventSimTime", m_eventSimTime); + success &= nt->addItem("EventOverheadTime", m_eventOverheadTime); // record the number of different PDG ID success &= nt->addItem("NumPdgIdTypes", m_nPdgTypes, 0U, MAX_PDG_TYPES); // record the PDG ID and time spend on each type of particle @@ -110,3 +116,140 @@ StatusCode ChronoAnaElemTool::initialize() { sc = initNtuple(); return sc; } + +void ChronoAnaElemTool::BeginOfEventAction(const G4Event *) { + // start total simulation timing + m_subdetTuple->reset(); + m_pidTuple->reset(); + m_overhead_time_counter = std::chrono::duration<double, std::micro>::zero(); + m_chronoStatSvc->chronoStart("Simulation"); +} + +void ChronoAnaElemTool::EndOfEventAction(const G4Event *event) { + m_chronoStatSvc->chronoStop("SubDet/" + + m_subdetNames[m_currentSubdetNameIdx]); + m_chronoStatSvc->chronoStop("PDGID/" + std::to_string(m_currentPdgId)); + m_chronoStatSvc->chronoStop("Simulation"); + + // save ntuple for record sim time over subdet and pid + m_eventNumber = event->GetEventID(); + m_eventSimTime = m_chronoStatSvc->chronoDelta("Simulation", IChronoSvc::USER); + m_eventOverheadTime = m_overhead_time_counter.count(); + + // fill ntuple for record sim time over subdet + for (unsigned i = 0; i < m_subdetNames.size(); ++i) { + auto s = m_chronoStatSvc->chrono("SubDet/" + m_subdetNames[i]); + m_timePerSubdet[i] = s->uTotalTime(); + } + + // fill ntuple for record sim time over pid + for (unsigned i = 0; i < m_nPdgTypes; ++i) { + auto s = m_chronoStatSvc->chrono("PDGID/" + std::to_string(m_pdgIds[i])); + m_timePerPdgType[i] = s->uTotalTime(); + } + + // write ntuple to file + StatusCode sc = m_subdetTuple->writeRecord(); + if (sc.isFailure()) { + error() << "Failed to write m_subdetTuple record for event " + << m_eventNumber << endmsg; + } + sc = m_pidTuple->writeRecord(); + if (sc.isFailure()) { + error() << "Failed to write m_pidTuple record for event " << m_eventNumber + << endmsg; + } +} + +inline void ChronoAnaElemTool::recordTimePerPdgIdType(const G4Step *aStep) { + auto track = aStep->GetTrack(); + if (track->GetCurrentStepNumber() != 1) { + // not the first step, skip + return; + } + // Process Particle ID Timer + int pdg = track->GetParticleDefinition()->GetPDGEncoding(); + if (pdg == m_currentPdgId) { + // pdgid not changed, skip + return; + } + + // If there was a previous PDG timer, stop it + if (m_currentPdgId != 0) { + debug() << "Stopping PDG[" << m_currentPdgId << "] timer -> Starting PDG[" + << pdg << "]" << endmsg; + m_chronoStatSvc->chronoStop("PDGID/" + std::to_string(m_currentPdgId)); + } + + // Find if this PDG is already recorded + if (std::find(m_pdgIds.begin(), m_pdgIds.end(), pdg) == m_pdgIds.end()) { + // new PDG, record it and start timer + m_pdgIds[m_nPdgTypes] = pdg; + ++m_nPdgTypes; + } + + // Update current PDG and start new PDG timer + m_currentPdgId = pdg; + m_chronoStatSvc->chronoStart("PDGID/" + std::to_string(m_currentPdgId)); +} + +inline void ChronoAnaElemTool::recordTimePerSubdet(const G4Step *aStep) { + if (!aStep->IsFirstStepInVolume()) { + return; + } + // Enter the first step in a new volume + // calculate the time spent in get subdet name + auto start = std::chrono::high_resolution_clock::now(); + const auto newNameIdx = getSubdetNameIdx(aStep->GetTrack()->GetTouchable()); + auto end = std::chrono::high_resolution_clock::now(); + m_overhead_time_counter += + std::chrono::duration<double, std::micro>(end - start); + + if (newNameIdx == m_currentSubdetNameIdx) { + // same subdet, skip this step + return; + } + // If we had a previous subdet, stop its timer + if (m_currentSubdetNameIdx != -1) { + debug() << "Exiting " << m_subdetNames[m_currentSubdetNameIdx] + << " -> Entering " << m_subdetNames[newNameIdx] << endmsg; + m_chronoStatSvc->chronoStop("SubDet/" + + m_subdetNames[m_currentSubdetNameIdx]); + } + + // Update state and start the new timer + m_currentSubdetNameIdx = newNameIdx; + m_chronoStatSvc->chronoStart("SubDet/" + + m_subdetNames[m_currentSubdetNameIdx]); +} + +void ChronoAnaElemTool::UserSteppingAction(const G4Step *aStep) { + recordTimePerPdgIdType(aStep); + recordTimePerSubdet(aStep); +} + +inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touchable) { + auto historyDepthNum = touchable->GetHistoryDepth(); + for (int depth = 0; depth <= historyDepthNum; depth++) { + auto vol = touchable->GetVolume(depth); + if (!vol) { + error() << "Volume is nullptr during finding " << depth << " in " + << historyDepthNum << endmsg; + return -1; + } + auto volName = vol->GetName(); + + // Check if the volume name contains the subdetector name + auto it = std::find_if(m_subdetNames.begin(), m_subdetNames.end(), + [&volName](const std::string &s) { + return volName.find(s) != std::string::npos; + }); + // If the volume name contains the subdetector name, return its index + if (it != m_subdetNames.end()) { + return static_cast<int>(std::distance(m_subdetNames.begin(), it)); + } + } + error() << "Volume is nullptr after find history " << historyDepthNum + << endmsg; + return -1; +} \ No newline at end of file diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index dce1928b..5d337f48 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -1,9 +1,7 @@ #ifndef ChronoAnaElemTool_h #define ChronoAnaElemTool_h -#include <array> #include <chrono> -#include <cstddef> #include <ratio> #include <string> #include <vector> @@ -21,9 +19,6 @@ class ChronoAnaElemTool : public extends<AlgTool, IAnaElemTool> { public: using extends::extends; - // Run - virtual void BeginOfRunAction(const G4Run *) override; - // Event virtual void BeginOfEventAction(const G4Event *) override; virtual void EndOfEventAction(const G4Event *) override; @@ -38,6 +33,9 @@ private: // methods StatusCode initNtuple(); StatusCode initSubdetNames(); + inline void recordTimePerPdgIdType(const G4Step *aStep); + inline void recordTimePerSubdet(const G4Step *aStep); + inline int getSubdetNameIdx(const G4VTouchable *touchable); // variables SmartIF<IChronoStatSvc> m_chronoStatSvc; @@ -48,7 +46,7 @@ private: this, "WriteNtupleFileName", "chrono_stat.root"}; Gaudi::Property<std::string> m_writeLogFileName{this, "WriteLogFileName", "chrono_stat.log"}; - std::ofstream m_logFileStream; + std::ofstream m_logFileStream; NTuple::Tuple *m_subdetTuple{nullptr}; NTuple::Tuple *m_pidTuple{nullptr}; @@ -58,9 +56,16 @@ private: static const unsigned MAX_PDG_TYPES = 256; std::vector<std::string> m_subdetNames; + int m_currentSubdetNameIdx = -1; + int m_currentPdgId = 0; NTuple::Item<long> m_eventNumber; + // User space sim time + NTuple::Item<double> m_eventOverheadTime; + NTuple::Item<double> m_eventSimTime; + NTuple::Array<double> m_timePerSubdet; + // type number of different PDG ID NTuple::Item<unsigned> m_nPdgTypes; // array of pdg ids -- GitLab From 2c0cdad6751098f7d97d27e75bc1afd65b18f514 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 20 May 2025 17:15:19 +0800 Subject: [PATCH 03/74] chore: sort import --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 24 +++++++++---------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 3 +-- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 6ff34ef8..038f4d02 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -1,25 +1,23 @@ +#include <array> +#include <cassert> +#include <cerrno> +#include <cstddef> +#include <string> + #include "ChronoAnaElemTool.h" +#include "DDG4/Geant4Data.h" #include "G4Event.hh" #include "G4Step.hh" #include "G4String.hh" -#include "GaudiKernel/IChronoSvc.h" -#include "GaudiKernel/INTupleSvc.h" - -#include "DDG4/Geant4Data.h" +#include "G4Track.hh" #include "G4TransportationManager.hh" +#include "GaudiAlg/GaudiAlgorithm.h" #include "GaudiKernel/ChronoEntity.h" +#include "GaudiKernel/IChronoSvc.h" +#include "GaudiKernel/INTupleSvc.h" #include "GaudiKernel/MsgStream.h" #include "GaudiKernel/NTuple.h" -#include <G4Track.hh> -#include <array> -#include <cassert> -#include <cerrno> -#include <cstddef> -#include <string> - -#include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/NTuple.h" DECLARE_COMPONENT(ChronoAnaElemTool) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 5d337f48..c2f24be5 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -8,6 +8,7 @@ #include "DetInterface/IGeomSvc.h" #include "DetSimInterface/IAnaElemTool.h" + #include "G4VTouchable.hh" #include "GaudiKernel/AlgTool.h" #include "GaudiKernel/IChronoStatSvc.h" @@ -42,8 +43,6 @@ private: SmartIF<INTupleSvc> m_ntupleSvc; SmartIF<IGeomSvc> m_geomSvc; - Gaudi::Property<std::string> m_writeNtupleFileName{ - this, "WriteNtupleFileName", "chrono_stat.root"}; Gaudi::Property<std::string> m_writeLogFileName{this, "WriteLogFileName", "chrono_stat.log"}; std::ofstream m_logFileStream; -- GitLab From 64f8f8873a6cf6063ff5809c35a2bd0ce9b884fa Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 20 May 2025 17:33:13 +0800 Subject: [PATCH 04/74] fix: add skip first n event --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 17 ++++++++++++++--- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 2 ++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 038f4d02..6e770441 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -115,22 +115,30 @@ StatusCode ChronoAnaElemTool::initialize() { return sc; } -void ChronoAnaElemTool::BeginOfEventAction(const G4Event *) { +void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { + m_eventNumber = event->GetEventID(); + if (m_eventNumber < m_skipFirstNEvents) { + return; + } // start total simulation timing m_subdetTuple->reset(); m_pidTuple->reset(); + // set eventNumber so we can use in userstepping + m_eventNumber = event->GetEventID(); m_overhead_time_counter = std::chrono::duration<double, std::micro>::zero(); m_chronoStatSvc->chronoStart("Simulation"); } -void ChronoAnaElemTool::EndOfEventAction(const G4Event *event) { +void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { + if (m_eventNumber < m_skipFirstNEvents) { + return; + } m_chronoStatSvc->chronoStop("SubDet/" + m_subdetNames[m_currentSubdetNameIdx]); m_chronoStatSvc->chronoStop("PDGID/" + std::to_string(m_currentPdgId)); m_chronoStatSvc->chronoStop("Simulation"); // save ntuple for record sim time over subdet and pid - m_eventNumber = event->GetEventID(); m_eventSimTime = m_chronoStatSvc->chronoDelta("Simulation", IChronoSvc::USER); m_eventOverheadTime = m_overhead_time_counter.count(); @@ -222,6 +230,9 @@ inline void ChronoAnaElemTool::recordTimePerSubdet(const G4Step *aStep) { } void ChronoAnaElemTool::UserSteppingAction(const G4Step *aStep) { + if (m_eventNumber < m_skipFirstNEvents) { + return; + } recordTimePerPdgIdType(aStep); recordTimePerSubdet(aStep); } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index c2f24be5..41f93681 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -45,6 +45,8 @@ private: Gaudi::Property<std::string> m_writeLogFileName{this, "WriteLogFileName", "chrono_stat.log"}; + Gaudi::Property<int> m_skipFirstNEvents{this, "SkipFirstNEvents", + 5}; std::ofstream m_logFileStream; NTuple::Tuple *m_subdetTuple{nullptr}; -- GitLab From c6b92b8207da54ea1f52808380997f6003ef22f0 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 20 May 2025 17:39:16 +0800 Subject: [PATCH 05/74] fix: add pWorld --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 6e770441..026b9d98 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -79,8 +79,13 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { return StatusCode::FAILURE; } + // add pWorld + m_subdetNames.push_back("pWorld"); + size_t index = 1; + m_logFileStream << "# " << index << " " << "pWorld" << '\n'; + + // add subdets const auto &children = m_geomSvc->getDD4HepGeo().children(); - size_t index = 0; for (const auto &[name, subdet] : children) { if (subdet.id() < 0) { continue; -- GitLab From 7da0aec0bf68a4c9c46413617332a9ed6ea7779c Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 20 May 2025 19:55:01 +0800 Subject: [PATCH 06/74] fix: index start from 0; avoid crash when not triggered --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 026b9d98..6dce41c9 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -81,8 +81,9 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { // add pWorld m_subdetNames.push_back("pWorld"); - size_t index = 1; + size_t index = 0; m_logFileStream << "# " << index << " " << "pWorld" << '\n'; + ++index; // add subdets const auto &children = m_geomSvc->getDD4HepGeo().children(); @@ -150,13 +151,21 @@ void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { // fill ntuple for record sim time over subdet for (unsigned i = 0; i < m_subdetNames.size(); ++i) { auto s = m_chronoStatSvc->chrono("SubDet/" + m_subdetNames[i]); - m_timePerSubdet[i] = s->uTotalTime(); + if (s != nullptr) { + m_timePerSubdet[i] = s->uTotalTime(); + } else { + info() << "SubDet/" << m_subdetNames[i] << " not triggered" << endmsg; + } } // fill ntuple for record sim time over pid for (unsigned i = 0; i < m_nPdgTypes; ++i) { auto s = m_chronoStatSvc->chrono("PDGID/" + std::to_string(m_pdgIds[i])); - m_timePerPdgType[i] = s->uTotalTime(); + if (s != nullptr) { + m_timePerPdgType[i] = s->uTotalTime(); + } else { + info() << "PDGID/" << std::to_string(m_pdgIds[i]) << " not triggered" << endmsg; + } } // write ntuple to file -- GitLab From 17d436a58df3dde782894e4c7ccda4d2f01964a5 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Wed, 21 May 2025 18:02:23 +0800 Subject: [PATCH 07/74] fix: remove ntuple write out --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 126 ++---------------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 25 +--- 2 files changed, 10 insertions(+), 141 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 6dce41c9..fe3b25c3 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -1,7 +1,7 @@ +#include <GaudiKernel/StatusCode.h> #include <array> #include <cassert> #include <cerrno> -#include <cstddef> #include <string> #include "ChronoAnaElemTool.h" @@ -13,77 +13,16 @@ #include "G4Track.hh" #include "G4TransportationManager.hh" #include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/ChronoEntity.h" #include "GaudiKernel/IChronoSvc.h" #include "GaudiKernel/INTupleSvc.h" #include "GaudiKernel/MsgStream.h" -#include "GaudiKernel/NTuple.h" DECLARE_COMPONENT(ChronoAnaElemTool) -StatusCode ChronoAnaElemTool::initNtuple() { - bool success = true; - { // Subdet array - NTuplePtr nt(m_ntupleSvc, "ChronoMetrics/SimulationTime/SubDet"); - if (!nt) { - nt = m_ntupleSvc->book("ChronoMetrics/SimulationTime/SubDet", - CLID_ColumnWiseTuple, "SimTime per Subdetector"); - if (!nt) { - return StatusCode::FAILURE; - } - success &= nt->addItem("EventNumber", m_eventNumber); - success &= nt->addItem("EventSimTime", m_eventSimTime); // microseconds - success &= - nt->addItem("EventOverheadTime", m_eventOverheadTime); // microseconds - success &= nt->addItem("TimePerSubdet", m_subdetNames.size(), - m_timePerSubdet, 0.0, 1e6); - } - m_subdetTuple = nt; - } - - { // Particle array - NTuplePtr nt(m_ntupleSvc, "ChronoMetrics/SimulationTime/PdgIdTypes"); - if (!nt) { - nt = m_ntupleSvc->book("ChronoMetrics/SimulationTime/PdgIdTypes", - CLID_ColumnWiseTuple, "SimTime per Particle ID"); - if (!nt) { - return StatusCode::FAILURE; - } - success &= nt->addItem("EventNumber", m_eventNumber); - success &= nt->addItem("EventSimTime", m_eventSimTime); - success &= nt->addItem("EventOverheadTime", m_eventOverheadTime); - // record the number of different PDG ID - success &= nt->addItem("NumPdgIdTypes", m_nPdgTypes, 0U, MAX_PDG_TYPES); - // record the PDG ID and time spend on each type of particle - success &= nt->addIndexedItem("PdgIdTypes", m_nPdgTypes, m_pdgIds); - success &= - nt->addIndexedItem("TimePerPdgIdType", m_nPdgTypes, m_timePerPdgType); - } - m_pidTuple = nt; - } - if (!m_subdetTuple || !m_pidTuple || !success) { - return StatusCode::FAILURE; - } else { - return StatusCode::SUCCESS; - } -} - StatusCode ChronoAnaElemTool::initSubdetNames() { - // prepare to write out subdet names - m_logFileStream.open(m_writeLogFileName.value(), - std::ios::out | std::ios::trunc); - if (m_logFileStream.fail()) { - error() << "Failed to open output file: " << m_writeLogFileName.value() - << endmsg; - return StatusCode::FAILURE; - } - // add pWorld m_subdetNames.push_back("pWorld"); - size_t index = 0; - m_logFileStream << "# " << index << " " << "pWorld" << '\n'; - ++index; // add subdets const auto &children = m_geomSvc->getDD4HepGeo().children(); @@ -92,11 +31,8 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { continue; } m_subdetNames.push_back(name); - m_logFileStream << "# " << index << " " << name << '\n'; - ++index; } - m_logFileStream.close(); return StatusCode::SUCCESS; } @@ -113,11 +49,6 @@ StatusCode ChronoAnaElemTool::initialize() { // init subdet names and number sc = initSubdetNames(); - if (sc.isFailure()) { - return sc; - } - // init ntuple for record sim time over subdet and pid - sc = initNtuple(); return sc; } @@ -126,12 +57,7 @@ void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { if (m_eventNumber < m_skipFirstNEvents) { return; } - // start total simulation timing - m_subdetTuple->reset(); - m_pidTuple->reset(); // set eventNumber so we can use in userstepping - m_eventNumber = event->GetEventID(); - m_overhead_time_counter = std::chrono::duration<double, std::micro>::zero(); m_chronoStatSvc->chronoStart("Simulation"); } @@ -143,42 +69,6 @@ void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { m_subdetNames[m_currentSubdetNameIdx]); m_chronoStatSvc->chronoStop("PDGID/" + std::to_string(m_currentPdgId)); m_chronoStatSvc->chronoStop("Simulation"); - - // save ntuple for record sim time over subdet and pid - m_eventSimTime = m_chronoStatSvc->chronoDelta("Simulation", IChronoSvc::USER); - m_eventOverheadTime = m_overhead_time_counter.count(); - - // fill ntuple for record sim time over subdet - for (unsigned i = 0; i < m_subdetNames.size(); ++i) { - auto s = m_chronoStatSvc->chrono("SubDet/" + m_subdetNames[i]); - if (s != nullptr) { - m_timePerSubdet[i] = s->uTotalTime(); - } else { - info() << "SubDet/" << m_subdetNames[i] << " not triggered" << endmsg; - } - } - - // fill ntuple for record sim time over pid - for (unsigned i = 0; i < m_nPdgTypes; ++i) { - auto s = m_chronoStatSvc->chrono("PDGID/" + std::to_string(m_pdgIds[i])); - if (s != nullptr) { - m_timePerPdgType[i] = s->uTotalTime(); - } else { - info() << "PDGID/" << std::to_string(m_pdgIds[i]) << " not triggered" << endmsg; - } - } - - // write ntuple to file - StatusCode sc = m_subdetTuple->writeRecord(); - if (sc.isFailure()) { - error() << "Failed to write m_subdetTuple record for event " - << m_eventNumber << endmsg; - } - sc = m_pidTuple->writeRecord(); - if (sc.isFailure()) { - error() << "Failed to write m_pidTuple record for event " << m_eventNumber - << endmsg; - } } inline void ChronoAnaElemTool::recordTimePerPdgIdType(const G4Step *aStep) { @@ -201,13 +91,6 @@ inline void ChronoAnaElemTool::recordTimePerPdgIdType(const G4Step *aStep) { m_chronoStatSvc->chronoStop("PDGID/" + std::to_string(m_currentPdgId)); } - // Find if this PDG is already recorded - if (std::find(m_pdgIds.begin(), m_pdgIds.end(), pdg) == m_pdgIds.end()) { - // new PDG, record it and start timer - m_pdgIds[m_nPdgTypes] = pdg; - ++m_nPdgTypes; - } - // Update current PDG and start new PDG timer m_currentPdgId = pdg; m_chronoStatSvc->chronoStart("PDGID/" + std::to_string(m_currentPdgId)); @@ -275,4 +158,11 @@ inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touchable) { error() << "Volume is nullptr after find history " << historyDepthNum << endmsg; return -1; +} + +StatusCode ChronoAnaElemTool::finalize() { + info() << "Finalizing ChronoAnaElemTool" << endmsg; + info() << "Overhead Time in total: " << m_overhead_time_counter.count() + << " ms" << endmsg; + return StatusCode::SUCCESS; } \ No newline at end of file diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 41f93681..2873d5e3 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -13,7 +13,6 @@ #include "GaudiKernel/AlgTool.h" #include "GaudiKernel/IChronoStatSvc.h" #include "GaudiKernel/INTupleSvc.h" -#include "GaudiKernel/NTuple.h" class ChronoAnaElemTool : public extends<AlgTool, IAnaElemTool> { @@ -29,10 +28,10 @@ public: /// Overriding initialize and finalize StatusCode initialize() override; + StatusCode finalize() override; private: // methods - StatusCode initNtuple(); StatusCode initSubdetNames(); inline void recordTimePerPdgIdType(const G4Step *aStep); inline void recordTimePerSubdet(const G4Step *aStep); @@ -43,36 +42,16 @@ private: SmartIF<INTupleSvc> m_ntupleSvc; SmartIF<IGeomSvc> m_geomSvc; - Gaudi::Property<std::string> m_writeLogFileName{this, "WriteLogFileName", - "chrono_stat.log"}; Gaudi::Property<int> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; - std::ofstream m_logFileStream; - - NTuple::Tuple *m_subdetTuple{nullptr}; - NTuple::Tuple *m_pidTuple{nullptr}; std::chrono::duration<double, std::micro> m_overhead_time_counter = std::chrono::duration<double, std::micro>::zero(); - static const unsigned MAX_PDG_TYPES = 256; std::vector<std::string> m_subdetNames; int m_currentSubdetNameIdx = -1; int m_currentPdgId = 0; - - NTuple::Item<long> m_eventNumber; - // User space sim time - NTuple::Item<double> m_eventOverheadTime; - NTuple::Item<double> m_eventSimTime; - - NTuple::Array<double> m_timePerSubdet; - - // type number of different PDG ID - NTuple::Item<unsigned> m_nPdgTypes; - // array of pdg ids - NTuple::Array<int> m_pdgIds; - // time spend on each type of particle - NTuple::Array<double> m_timePerPdgType; + int m_eventNumber = 0; }; #endif -- GitLab From a83b5d8fcab479c8c57f0b149c3c4929e77baaeb Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Wed, 21 May 2025 22:58:37 +0800 Subject: [PATCH 08/74] fix: calculate more overhead --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index fe3b25c3..e1c56745 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -102,11 +102,7 @@ inline void ChronoAnaElemTool::recordTimePerSubdet(const G4Step *aStep) { } // Enter the first step in a new volume // calculate the time spent in get subdet name - auto start = std::chrono::high_resolution_clock::now(); const auto newNameIdx = getSubdetNameIdx(aStep->GetTrack()->GetTouchable()); - auto end = std::chrono::high_resolution_clock::now(); - m_overhead_time_counter += - std::chrono::duration<double, std::micro>(end - start); if (newNameIdx == m_currentSubdetNameIdx) { // same subdet, skip this step @@ -130,8 +126,12 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *aStep) { if (m_eventNumber < m_skipFirstNEvents) { return; } + auto start = std::chrono::high_resolution_clock::now(); recordTimePerPdgIdType(aStep); recordTimePerSubdet(aStep); + auto end = std::chrono::high_resolution_clock::now(); + m_overhead_time_counter += + std::chrono::duration<double, std::micro>(end - start); } inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touchable) { @@ -163,6 +163,6 @@ inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touchable) { StatusCode ChronoAnaElemTool::finalize() { info() << "Finalizing ChronoAnaElemTool" << endmsg; info() << "Overhead Time in total: " << m_overhead_time_counter.count() - << " ms" << endmsg; + << " microseconds" << endmsg; return StatusCode::SUCCESS; } \ No newline at end of file -- GitLab From 7b182768b73edc0273676412857b82baedf42094 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sat, 24 May 2025 08:57:29 +0800 Subject: [PATCH 09/74] fix: refactor header; reformat initSubdetNames --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 28 +++++++--- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 56 +++++++++++++------ 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index e1c56745..c488a1d5 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -13,24 +13,32 @@ #include "G4Track.hh" #include "G4TransportationManager.hh" #include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/IChronoSvc.h" #include "GaudiKernel/INTupleSvc.h" #include "GaudiKernel/MsgStream.h" DECLARE_COMPONENT(ChronoAnaElemTool) StatusCode ChronoAnaElemTool::initSubdetNames() { + const auto &children = m_geomSvc->getDD4HepGeo().children(); + m_subdetNames.clear(); + m_subdetNames.reserve(children.size() + 1); // add pWorld - m_subdetNames.push_back("pWorld"); + m_subdetNames.emplace_back("pWorld"); // add subdets - const auto &children = m_geomSvc->getDD4HepGeo().children(); for (const auto &[name, subdet] : children) { - if (subdet.id() < 0) { + if (subdet.id() < 0) continue; - } - m_subdetNames.push_back(name); + m_subdetNames.emplace_back(name); + } + + // print subdets to log file + + info() << "=== Subdetector Names List (" << m_subdetNames.size() + << ") ===" << endmsg; + for (size_t i = 0; i < m_subdetNames.size(); ++i) { + info() << "[" << std::setw(2) << i << "] " << m_subdetNames[i] << endmsg; } return StatusCode::SUCCESS; @@ -40,13 +48,15 @@ StatusCode ChronoAnaElemTool::initialize() { StatusCode sc; // Get services - m_chronoStatSvc = service<IChronoStatSvc>("ChronoStatSvc"); m_ntupleSvc = service<INTupleSvc>("NTupleSvc"); m_geomSvc = service<IGeomSvc>("GeomSvc"); - if (!m_chronoStatSvc || !m_ntupleSvc || !m_geomSvc) { + if (!m_ntupleSvc || !m_geomSvc) { return StatusCode::FAILURE; } + // calibrate the clock before starting the simulation + NanoClock::calibrate(); + // init subdet names and number sc = initSubdetNames(); return sc; @@ -69,6 +79,8 @@ void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { m_subdetNames[m_currentSubdetNameIdx]); m_chronoStatSvc->chronoStop("PDGID/" + std::to_string(m_currentPdgId)); m_chronoStatSvc->chronoStop("Simulation"); + + // record time to NTuple } inline void ChronoAnaElemTool::recordTimePerPdgIdType(const G4Step *aStep) { diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 2873d5e3..10f23655 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -2,27 +2,31 @@ #define ChronoAnaElemTool_h #include <chrono> -#include <ratio> #include <string> #include <vector> #include "DetInterface/IGeomSvc.h" #include "DetSimInterface/IAnaElemTool.h" -#include "G4VTouchable.hh" #include "GaudiKernel/AlgTool.h" -#include "GaudiKernel/IChronoStatSvc.h" #include "GaudiKernel/INTupleSvc.h" +#include "GaudiKernel/NTuple.h" +#include <Gaudi/Timers/RdtscClock.h> class ChronoAnaElemTool : public extends<AlgTool, IAnaElemTool> { public: using extends::extends; + using NanoClock = Gaudi::Timers::RdtscClock<std::chrono::nanoseconds>; // Event virtual void BeginOfEventAction(const G4Event *) override; virtual void EndOfEventAction(const G4Event *) override; + // Tracking + virtual void PreUserTrackingAction(const G4Track *) override; + virtual void PostUserTrackingAction(const G4Track *) override; + // Stepping virtual void UserSteppingAction(const G4Step *) override; @@ -31,27 +35,47 @@ public: StatusCode finalize() override; private: - // methods - StatusCode initSubdetNames(); - inline void recordTimePerPdgIdType(const G4Step *aStep); - inline void recordTimePerSubdet(const G4Step *aStep); - inline int getSubdetNameIdx(const G4VTouchable *touchable); - - // variables - SmartIF<IChronoStatSvc> m_chronoStatSvc; + // common SmartIF<INTupleSvc> m_ntupleSvc; SmartIF<IGeomSvc> m_geomSvc; - Gaudi::Property<int> m_skipFirstNEvents{this, "SkipFirstNEvents", - 5}; + Gaudi::Property<int> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; + + NTuple::Item<long> m_eventNumber; + NTuple::Item<double> m_eventTotSimTime; + StatusCode initNtuple(); - std::chrono::duration<double, std::micro> m_overhead_time_counter = - std::chrono::duration<double, std::micro>::zero(); + // simtime over subdet + inline void recordTimePerSubdet(const G4Step *aStep); + inline int getSubdetNameIdx(const G4Step *aStep); + StatusCode initSubdetNames(); std::vector<std::string> m_subdetNames; int m_currentSubdetNameIdx = -1; + + NTuple::Tuple *m_subdetTuple{nullptr}; + NTuple::Array<double> m_timePerSubdet; + + // simtime over PDGID + inline void recordTimePerPdgIdType(const G4Step *aStep); int m_currentPdgId = 0; - int m_eventNumber = 0; + static const unsigned MAX_PDG_TYPES = 1024; + + NTuple::Tuple *m_pidTuple{nullptr}; + // type number of different PDG ID + NTuple::Item<unsigned> m_nPdgTypes; + // array of pdg ids + NTuple::Array<int> m_pdgIds; + // time spend on each type of particle + NTuple::Array<double> m_timePerPdgType; + + // simtime over Track + Gaudi::Property<bool> m_doTrackSimTime{this, "DoTrackSimTime", false}; + static const unsigned MAX_TRACK_TYPES = 1024; + NTuple::Item<int> m_trackTypes; + NTuple::Array<double> m_trackLengths; + NTuple::Array<double> m_trackTimes; + NTuple::Array<double> m_trackLengthsOverTime; // track length over time }; #endif -- GitLab From 003db483fddb7ab15c1194ddfcff0992adb82fb0 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sat, 24 May 2025 10:02:14 +0800 Subject: [PATCH 10/74] feat(ChronoAnaElemTool): add N-tuple tracking for track lengths and times - Implement `bookNtuple` helper method for NTuple booking - Add `initNtuple` to initialize track-related NTuple items - Update service initialization order and dependencies - Remove unused MAX_PDG_TYPES and MAX_TRACK_TYPES constants - Switch to NTuplePtr for tuple management --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 178 +++++------------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 14 +- 2 files changed, 56 insertions(+), 136 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index c488a1d5..5d96b849 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -2,19 +2,16 @@ #include <array> #include <cassert> #include <cerrno> -#include <string> #include "ChronoAnaElemTool.h" -#include "DDG4/Geant4Data.h" -#include "G4Event.hh" -#include "G4Step.hh" -#include "G4String.hh" -#include "G4Track.hh" -#include "G4TransportationManager.hh" #include "GaudiAlg/GaudiAlgorithm.h" -#include "GaudiKernel/INTupleSvc.h" +#include "GaudiKernel/ClassID.h" #include "GaudiKernel/MsgStream.h" +#include "GaudiKernel/NTuple.h" +#include "GaudiKernel/SmartIF.h" + +#include "DetInterface/IGeomSvc.h" DECLARE_COMPONENT(ChronoAnaElemTool) @@ -44,13 +41,50 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { return StatusCode::SUCCESS; } +StatusCode ChronoAnaElemTool::bookNtuple(NTuplePtr &t, std::string_view path, + std::string_view title) { + if (NTuplePtr tmp = NTuplePtr(m_ntupleSvc, std::string(path)); !tmp) { + tmp = m_ntupleSvc->book(std::string(path), CLID_ColumnWiseTuple, + std::string(title)); + if (!tmp) { + error() << "Cannot book N-tuple: " << path << endmsg; + return StatusCode::FAILURE; + } + } else { + t = tmp; + } + return StatusCode::SUCCESS; +} + +StatusCode ChronoAnaElemTool::initNtuple() { + bool suc = true; + + // Book the N-tuple for track length + suc &= bookNtuple(m_trackTuple, "ChronoMetrics/TrackLength", + "SimTime over Track length") + .isSuccess(); + suc &= + m_trackTuple->addItem("trackNum", m_trackNum, 0U, UINT_MAX).isSuccess(); + suc &= + m_trackTuple->addIndexedItem("trackLengths", m_trackNum, m_trackLengths) + .isSuccess(); + suc &= m_trackTuple->addIndexedItem("trackTimes", m_trackNum, m_trackTimes) + .isSuccess(); + suc &= m_trackTuple + ->addIndexedItem("trackLengthsOverTime", m_trackNum, + m_trackLengthsOverTime) + .isSuccess(); + + return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; +} + StatusCode ChronoAnaElemTool::initialize() { - StatusCode sc; + bool suc = true; // Get services - m_ntupleSvc = service<INTupleSvc>("NTupleSvc"); m_geomSvc = service<IGeomSvc>("GeomSvc"); - if (!m_ntupleSvc || !m_geomSvc) { + m_ntupleSvc = service<INTupleSvc>("NTupleSvc"); + if (!m_geomSvc || !m_ntupleSvc) { return StatusCode::FAILURE; } @@ -58,123 +92,7 @@ StatusCode ChronoAnaElemTool::initialize() { NanoClock::calibrate(); // init subdet names and number - sc = initSubdetNames(); - return sc; + suc &= initSubdetNames().isSuccess(); + suc &= initNtuple().isSuccess(); + return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } - -void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { - m_eventNumber = event->GetEventID(); - if (m_eventNumber < m_skipFirstNEvents) { - return; - } - // set eventNumber so we can use in userstepping - m_chronoStatSvc->chronoStart("Simulation"); -} - -void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { - if (m_eventNumber < m_skipFirstNEvents) { - return; - } - m_chronoStatSvc->chronoStop("SubDet/" + - m_subdetNames[m_currentSubdetNameIdx]); - m_chronoStatSvc->chronoStop("PDGID/" + std::to_string(m_currentPdgId)); - m_chronoStatSvc->chronoStop("Simulation"); - - // record time to NTuple -} - -inline void ChronoAnaElemTool::recordTimePerPdgIdType(const G4Step *aStep) { - auto track = aStep->GetTrack(); - if (track->GetCurrentStepNumber() != 1) { - // not the first step, skip - return; - } - // Process Particle ID Timer - int pdg = track->GetParticleDefinition()->GetPDGEncoding(); - if (pdg == m_currentPdgId) { - // pdgid not changed, skip - return; - } - - // If there was a previous PDG timer, stop it - if (m_currentPdgId != 0) { - debug() << "Stopping PDG[" << m_currentPdgId << "] timer -> Starting PDG[" - << pdg << "]" << endmsg; - m_chronoStatSvc->chronoStop("PDGID/" + std::to_string(m_currentPdgId)); - } - - // Update current PDG and start new PDG timer - m_currentPdgId = pdg; - m_chronoStatSvc->chronoStart("PDGID/" + std::to_string(m_currentPdgId)); -} - -inline void ChronoAnaElemTool::recordTimePerSubdet(const G4Step *aStep) { - if (!aStep->IsFirstStepInVolume()) { - return; - } - // Enter the first step in a new volume - // calculate the time spent in get subdet name - const auto newNameIdx = getSubdetNameIdx(aStep->GetTrack()->GetTouchable()); - - if (newNameIdx == m_currentSubdetNameIdx) { - // same subdet, skip this step - return; - } - // If we had a previous subdet, stop its timer - if (m_currentSubdetNameIdx != -1) { - debug() << "Exiting " << m_subdetNames[m_currentSubdetNameIdx] - << " -> Entering " << m_subdetNames[newNameIdx] << endmsg; - m_chronoStatSvc->chronoStop("SubDet/" + - m_subdetNames[m_currentSubdetNameIdx]); - } - - // Update state and start the new timer - m_currentSubdetNameIdx = newNameIdx; - m_chronoStatSvc->chronoStart("SubDet/" + - m_subdetNames[m_currentSubdetNameIdx]); -} - -void ChronoAnaElemTool::UserSteppingAction(const G4Step *aStep) { - if (m_eventNumber < m_skipFirstNEvents) { - return; - } - auto start = std::chrono::high_resolution_clock::now(); - recordTimePerPdgIdType(aStep); - recordTimePerSubdet(aStep); - auto end = std::chrono::high_resolution_clock::now(); - m_overhead_time_counter += - std::chrono::duration<double, std::micro>(end - start); -} - -inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touchable) { - auto historyDepthNum = touchable->GetHistoryDepth(); - for (int depth = 0; depth <= historyDepthNum; depth++) { - auto vol = touchable->GetVolume(depth); - if (!vol) { - error() << "Volume is nullptr during finding " << depth << " in " - << historyDepthNum << endmsg; - return -1; - } - auto volName = vol->GetName(); - - // Check if the volume name contains the subdetector name - auto it = std::find_if(m_subdetNames.begin(), m_subdetNames.end(), - [&volName](const std::string &s) { - return volName.find(s) != std::string::npos; - }); - // If the volume name contains the subdetector name, return its index - if (it != m_subdetNames.end()) { - return static_cast<int>(std::distance(m_subdetNames.begin(), it)); - } - } - error() << "Volume is nullptr after find history " << historyDepthNum - << endmsg; - return -1; -} - -StatusCode ChronoAnaElemTool::finalize() { - info() << "Finalizing ChronoAnaElemTool" << endmsg; - info() << "Overhead Time in total: " << m_overhead_time_counter.count() - << " microseconds" << endmsg; - return StatusCode::SUCCESS; -} \ No newline at end of file diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 10f23655..4ee608d2 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -11,6 +11,7 @@ #include "GaudiKernel/AlgTool.h" #include "GaudiKernel/INTupleSvc.h" #include "GaudiKernel/NTuple.h" +#include "GaudiKernel/SmartIF.h" #include <Gaudi/Timers/RdtscClock.h> class ChronoAnaElemTool : public extends<AlgTool, IAnaElemTool> { @@ -36,14 +37,16 @@ public: private: // common - SmartIF<INTupleSvc> m_ntupleSvc; SmartIF<IGeomSvc> m_geomSvc; + SmartIF<INTupleSvc> m_ntupleSvc; Gaudi::Property<int> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; NTuple::Item<long> m_eventNumber; NTuple::Item<double> m_eventTotSimTime; StatusCode initNtuple(); + StatusCode bookNtuple(NTuplePtr &t, std::string_view path, + std::string_view title); // simtime over subdet inline void recordTimePerSubdet(const G4Step *aStep); @@ -53,15 +56,14 @@ private: std::vector<std::string> m_subdetNames; int m_currentSubdetNameIdx = -1; - NTuple::Tuple *m_subdetTuple{nullptr}; + NTuplePtr m_subdetTuple; NTuple::Array<double> m_timePerSubdet; // simtime over PDGID inline void recordTimePerPdgIdType(const G4Step *aStep); int m_currentPdgId = 0; - static const unsigned MAX_PDG_TYPES = 1024; - NTuple::Tuple *m_pidTuple{nullptr}; + NTuplePtr m_pidTuple; // type number of different PDG ID NTuple::Item<unsigned> m_nPdgTypes; // array of pdg ids @@ -71,8 +73,8 @@ private: // simtime over Track Gaudi::Property<bool> m_doTrackSimTime{this, "DoTrackSimTime", false}; - static const unsigned MAX_TRACK_TYPES = 1024; - NTuple::Item<int> m_trackTypes; + NTuplePtr m_trackTuple; + NTuple::Item<unsigned> m_trackNum; NTuple::Array<double> m_trackLengths; NTuple::Array<double> m_trackTimes; NTuple::Array<double> m_trackLengthsOverTime; // track length over time -- GitLab From 0af89ffa6d8dd213601161e72e83e7be962a0f05 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sat, 24 May 2025 12:34:04 +0800 Subject: [PATCH 11/74] feat: simtime metrics on track done; --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 51 +++++++++++++++++-- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 12 +++-- 2 files changed, 56 insertions(+), 7 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 5d96b849..27d05f5c 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -5,6 +5,9 @@ #include "ChronoAnaElemTool.h" +#include "G4Event.hh" +#include "G4Step.hh" +#include "G4Track.hh" #include "GaudiAlg/GaudiAlgorithm.h" #include "GaudiKernel/ClassID.h" #include "GaudiKernel/MsgStream.h" @@ -56,13 +59,15 @@ StatusCode ChronoAnaElemTool::bookNtuple(NTuplePtr &t, std::string_view path, return StatusCode::SUCCESS; } -StatusCode ChronoAnaElemTool::initNtuple() { +StatusCode ChronoAnaElemTool::initTrackNtuple() { bool suc = true; // Book the N-tuple for track length suc &= bookNtuple(m_trackTuple, "ChronoMetrics/TrackLength", "SimTime over Track length") .isSuccess(); + suc &= m_trackTuple->addItem("eventNumber", m_eventNumber, 0U, UINT_MAX) + .isSuccess(); suc &= m_trackTuple->addItem("trackNum", m_trackNum, 0U, UINT_MAX).isSuccess(); suc &= @@ -92,7 +97,47 @@ StatusCode ChronoAnaElemTool::initialize() { NanoClock::calibrate(); // init subdet names and number - suc &= initSubdetNames().isSuccess(); - suc &= initNtuple().isSuccess(); + if (m_enableSubdetSimTimeRecording.value()) { + suc &= initSubdetNames().isSuccess(); + } + + if (m_enableTrackSimTimeRecording.value()) { + suc &= initTrackNtuple().isSuccess(); + } + return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } + +void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *) { + if (!m_enableTrackSimTimeRecording.value()) { + return; + } + m_track_start = NanoClock::now(); +} + +void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { + if (!m_enableTrackSimTimeRecording.value()) { + return; + } + NanoClock::time_point track_stop = NanoClock::now(); + m_trackLengths[m_trackNum] = track->GetTrackLength(); + m_trackTimes[m_trackNum] = + NanoClock::duration(track_stop - m_track_start).count(); + m_trackLengthsOverTime[m_trackNum] = + m_trackLengths[m_trackNum] / m_trackTimes[m_trackNum]; + ++m_trackNum; +} + +void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { + if (m_enableTrackSimTimeRecording.value()) { + if (m_trackTuple->write().isFailure()) { + error() << "Error write track tuple at event " << m_eventNumber << endmsg; + } else { + m_trackTuple->reset(); + } + } +} + +void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { + m_eventNumber = event->GetEventID(); +} \ No newline at end of file diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 4ee608d2..792bd98e 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -40,15 +40,14 @@ private: SmartIF<IGeomSvc> m_geomSvc; SmartIF<INTupleSvc> m_ntupleSvc; - Gaudi::Property<int> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; - NTuple::Item<long> m_eventNumber; NTuple::Item<double> m_eventTotSimTime; - StatusCode initNtuple(); StatusCode bookNtuple(NTuplePtr &t, std::string_view path, std::string_view title); // simtime over subdet + Gaudi::Property<bool> m_enableSubdetSimTimeRecording{ + this, "EnableSubdetSimTimeRecording", false}; inline void recordTimePerSubdet(const G4Step *aStep); inline int getSubdetNameIdx(const G4Step *aStep); @@ -60,6 +59,8 @@ private: NTuple::Array<double> m_timePerSubdet; // simtime over PDGID + Gaudi::Property<bool> m_enablePDGIDSimTimeRecording{ + this, "EnablePDGIDSimTimeRecording", false}; inline void recordTimePerPdgIdType(const G4Step *aStep); int m_currentPdgId = 0; @@ -72,7 +73,10 @@ private: NTuple::Array<double> m_timePerPdgType; // simtime over Track - Gaudi::Property<bool> m_doTrackSimTime{this, "DoTrackSimTime", false}; + NanoClock::time_point m_track_start; + StatusCode initTrackNtuple(); + Gaudi::Property<bool> m_enableTrackSimTimeRecording{ + this, "EnableTrackSimTimeRecording", false}; NTuplePtr m_trackTuple; NTuple::Item<unsigned> m_trackNum; NTuple::Array<double> m_trackLengths; -- GitLab From e3a1e90dfbb60ebba11efc9b87e038b98c229110 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sat, 24 May 2025 14:09:48 +0800 Subject: [PATCH 12/74] feat(ChronoAnaElemTool): refactor ntuple handling and add tracking metrics --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 115 +++++++++++++----- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 40 +++--- 2 files changed, 97 insertions(+), 58 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 27d05f5c..3f194411 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -44,41 +44,39 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { return StatusCode::SUCCESS; } -StatusCode ChronoAnaElemTool::bookNtuple(NTuplePtr &t, std::string_view path, - std::string_view title) { - if (NTuplePtr tmp = NTuplePtr(m_ntupleSvc, std::string(path)); !tmp) { - tmp = m_ntupleSvc->book(std::string(path), CLID_ColumnWiseTuple, - std::string(title)); - if (!tmp) { - error() << "Cannot book N-tuple: " << path << endmsg; +StatusCode ChronoAnaElemTool::initNtuple() { + bool suc = true; + + // Book the N-tuple + if (NTuplePtr nt = NTuplePtr(m_ntupleSvc, std::string("ChronoMetrics")); + !nt) { + nt = m_ntupleSvc->book(std::string("ChronoMetrics/events"), + CLID_ColumnWiseTuple, + std::string("ChronoMetrics/events")); + if (!nt) { + error() << "Cannot book N-tuple: ChronoMetrics" << endmsg; return StatusCode::FAILURE; } } else { - t = tmp; + m_ntuple = nt; } - return StatusCode::SUCCESS; -} -StatusCode ChronoAnaElemTool::initTrackNtuple() { - bool suc = true; - - // Book the N-tuple for track length - suc &= bookNtuple(m_trackTuple, "ChronoMetrics/TrackLength", - "SimTime over Track length") - .isSuccess(); - suc &= m_trackTuple->addItem("eventNumber", m_eventNumber, 0U, UINT_MAX) - .isSuccess(); suc &= - m_trackTuple->addItem("trackNum", m_trackNum, 0U, UINT_MAX).isSuccess(); + m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX).isSuccess(); + suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, UINT_MAX).isSuccess(); suc &= - m_trackTuple->addIndexedItem("trackLengths", m_trackNum, m_trackLengths) + m_ntuple->addItem("TimePerSubdet", m_subdetNames.size(), m_timePerSubdet) .isSuccess(); - suc &= m_trackTuple->addIndexedItem("trackTimes", m_trackNum, m_trackTimes) + suc &= m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) .isSuccess(); - suc &= m_trackTuple - ->addIndexedItem("trackLengthsOverTime", m_trackNum, + suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTimes) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackLengthsOverTime", m_trackNum, m_trackLengthsOverTime) .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGIds) + .isSuccess(); return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } @@ -102,16 +100,18 @@ StatusCode ChronoAnaElemTool::initialize() { } if (m_enableTrackSimTimeRecording.value()) { - suc &= initTrackNtuple().isSuccess(); + suc &= initNtuple().isSuccess(); } return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } -void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *) { +void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { if (!m_enableTrackSimTimeRecording.value()) { return; } + + m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); m_track_start = NanoClock::now(); } @@ -125,19 +125,70 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { NanoClock::duration(track_stop - m_track_start).count(); m_trackLengthsOverTime[m_trackNum] = m_trackLengths[m_trackNum] / m_trackTimes[m_trackNum]; + m_trackPDGIds[m_trackNum] = track->GetParticleDefinition()->GetPDGEncoding(); + m_trackEndSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); ++m_trackNum; } void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { - if (m_enableTrackSimTimeRecording.value()) { - if (m_trackTuple->write().isFailure()) { - error() << "Error write track tuple at event " << m_eventNumber << endmsg; - } else { - m_trackTuple->reset(); - } + NanoClock::time_point event_stop = NanoClock::now(); + m_eventTotSimTime = NanoClock::duration(event_stop - m_event_start).count(); + if (m_ntuple->write().isFailure()) { + error() << "Error write track tuple at event " << m_eventNumber << endmsg; } } void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { + m_ntuple->reset(); m_eventNumber = event->GetEventID(); + + m_event_start = NanoClock::now(); +} + +void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { + if (!m_enableSubdetSimTimeRecording.value()) + return; + if (step->IsLastStepInVolume()) { + auto subdet_stop = NanoClock::now(); + m_timePerSubdet[getSubdetNameIdx(step->GetTrack()->GetTouchable())] += + NanoClock::duration(subdet_stop - m_subdet_enter).count(); + } else if (step->IsFirstStepInVolume()) { + m_subdet_enter = NanoClock::now(); + } +} + +inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { + auto historyDepthNum = touch->GetHistoryDepth(); + for (int depth = 0; depth <= historyDepthNum; depth++) { + auto vol = touch->GetVolume(depth); + if (!vol) { + error() << "Volume is nullptr during finding " << depth << " in " + << historyDepthNum << endmsg; + return -1; + } + auto volName = vol->GetName(); + + // Check how many subdetector names are contained in the volume name + int foundCount = 0; + int foundIndex = -1; + + for (size_t i = 0; i < m_subdetNames.size(); ++i) { + if (volName.find(m_subdetNames[i]) != std::string::npos) { + foundCount++; + foundIndex = static_cast<int>(i); + } + } + + // Return index if exactly one match found, otherwise -1 + return (foundCount == 1) ? foundIndex : -1; + } + error() << "Volume is nullptr after find history " << historyDepthNum + << endmsg; + return -1; +} + +StatusCode ChronoAnaElemTool::finalize() { + StatusCode sc; + + return sc; } \ No newline at end of file diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 792bd98e..ddebd7ca 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -1,6 +1,7 @@ #ifndef ChronoAnaElemTool_h #define ChronoAnaElemTool_h +#include <G4VTouchable.hh> #include <chrono> #include <string> #include <vector> @@ -39,49 +40,36 @@ private: // common SmartIF<IGeomSvc> m_geomSvc; SmartIF<INTupleSvc> m_ntupleSvc; + NTuple::Tuple *m_ntuple; + StatusCode initNtuple(); NTuple::Item<long> m_eventNumber; NTuple::Item<double> m_eventTotSimTime; - StatusCode bookNtuple(NTuplePtr &t, std::string_view path, - std::string_view title); + NanoClock::time_point m_event_start; // simtime over subdet - Gaudi::Property<bool> m_enableSubdetSimTimeRecording{ - this, "EnableSubdetSimTimeRecording", false}; - inline void recordTimePerSubdet(const G4Step *aStep); - inline int getSubdetNameIdx(const G4Step *aStep); - StatusCode initSubdetNames(); std::vector<std::string> m_subdetNames; - int m_currentSubdetNameIdx = -1; - - NTuplePtr m_subdetTuple; - NTuple::Array<double> m_timePerSubdet; + inline int getSubdetNameIdx(const G4VTouchable *); - // simtime over PDGID - Gaudi::Property<bool> m_enablePDGIDSimTimeRecording{ - this, "EnablePDGIDSimTimeRecording", false}; - inline void recordTimePerPdgIdType(const G4Step *aStep); - int m_currentPdgId = 0; + NanoClock::time_point m_subdet_enter; + Gaudi::Property<bool> m_enableSubdetSimTimeRecording{ + this, "EnableSubdetSimTimeRecording", false}; - NTuplePtr m_pidTuple; - // type number of different PDG ID - NTuple::Item<unsigned> m_nPdgTypes; - // array of pdg ids - NTuple::Array<int> m_pdgIds; - // time spend on each type of particle - NTuple::Array<double> m_timePerPdgType; + NTuple::Array<double> m_timePerSubdet; // simtime over Track NanoClock::time_point m_track_start; - StatusCode initTrackNtuple(); Gaudi::Property<bool> m_enableTrackSimTimeRecording{ this, "EnableTrackSimTimeRecording", false}; - NTuplePtr m_trackTuple; + NTuple::Item<unsigned> m_trackNum; NTuple::Array<double> m_trackLengths; NTuple::Array<double> m_trackTimes; - NTuple::Array<double> m_trackLengthsOverTime; // track length over time + NTuple::Array<double> m_trackLengthsOverTime; + NTuple::Array<int> m_trackPDGIds; + NTuple::Array<int> m_trackStartSubdet; + NTuple::Array<int> m_trackEndSubdet; }; #endif -- GitLab From 45d02fcf5ad372805ad93217b0838d39479e3df6 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sat, 24 May 2025 14:42:03 +0800 Subject: [PATCH 13/74] refactor: remove redundant ntuple item additions --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 56 ++++++++++--------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 3f194411..01469b24 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -48,36 +48,40 @@ StatusCode ChronoAnaElemTool::initNtuple() { bool suc = true; // Book the N-tuple - if (NTuplePtr nt = NTuplePtr(m_ntupleSvc, std::string("ChronoMetrics")); - !nt) { - nt = m_ntupleSvc->book(std::string("ChronoMetrics/events"), - CLID_ColumnWiseTuple, - std::string("ChronoMetrics/events")); - if (!nt) { - error() << "Cannot book N-tuple: ChronoMetrics" << endmsg; + NTuplePtr nt(m_ntupleSvc, "ChronoMetrics/Sim"); + if (nt) { + info() << "Get Ntuple Success" << endmsg; + m_ntuple = nt; + } else { + m_ntuple = m_ntupleSvc->book("ChronoMetrics/Sim", CLID_ColumnWiseTuple, + "Simulation ChronoMetrics"); + if (m_ntuple) { + info() << "Create Ntuple Success" << endmsg; + suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX) + .isSuccess(); + suc &= + m_ntuple->addItem("TrackNum", m_trackNum, 0U, UINT_MAX).isSuccess(); + suc &= + m_ntuple + ->addItem("TimePerSubdet", m_subdetNames.size(), m_timePerSubdet) + .isSuccess(); + suc &= + m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTimes) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackLengthsOverTime", m_trackNum, + m_trackLengthsOverTime) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGIds) + .isSuccess(); + } else { + error() << "Cannot book N-tuple:" << long(m_ntuple) << endmsg; return StatusCode::FAILURE; } - } else { - m_ntuple = nt; } - suc &= - m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX).isSuccess(); - suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, UINT_MAX).isSuccess(); - suc &= - m_ntuple->addItem("TimePerSubdet", m_subdetNames.size(), m_timePerSubdet) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTimes) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackLengthsOverTime", m_trackNum, - m_trackLengthsOverTime) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGIds) - .isSuccess(); - return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } -- GitLab From ae2128643d1c3d0ece69531832c3e15e8cd46275 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sat, 24 May 2025 14:44:05 +0800 Subject: [PATCH 14/74] fix: init ntuple anyway --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 01469b24..b16c2757 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -102,11 +102,7 @@ StatusCode ChronoAnaElemTool::initialize() { if (m_enableSubdetSimTimeRecording.value()) { suc &= initSubdetNames().isSuccess(); } - - if (m_enableTrackSimTimeRecording.value()) { - suc &= initNtuple().isSuccess(); - } - + suc &= initNtuple().isSuccess(); return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } @@ -143,6 +139,7 @@ void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { } void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { + info() << m_ntuple << endmsg; m_ntuple->reset(); m_eventNumber = event->GetEventID(); -- GitLab From 649176483bf2c8ac0382d7466122c0e34fc982de Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sat, 24 May 2025 15:22:58 +0800 Subject: [PATCH 15/74] feat(ChronoAnaElemTool): add skip events option and track time improvements --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 22 ++++++++++++++----- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 3 +++ 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index b16c2757..7558854c 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -59,8 +59,9 @@ StatusCode ChronoAnaElemTool::initNtuple() { info() << "Create Ntuple Success" << endmsg; suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX) .isSuccess(); - suc &= - m_ntuple->addItem("TrackNum", m_trackNum, 0U, UINT_MAX).isSuccess(); + suc &= m_ntuple->addItem("TotSimTime", m_eventTotSimTime).isSuccess(); + suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, MAX_TRACK_NUM) + .isSuccess(); suc &= m_ntuple ->addItem("TimePerSubdet", m_subdetNames.size(), m_timePerSubdet) @@ -110,13 +111,17 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { if (!m_enableTrackSimTimeRecording.value()) { return; } + if (m_eventNumber < m_skipFirstNEvents) { + return; + } m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); m_track_start = NanoClock::now(); } void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { - if (!m_enableTrackSimTimeRecording.value()) { + if (!m_enableTrackSimTimeRecording.value() || + m_eventNumber < m_skipFirstNEvents) { return; } NanoClock::time_point track_stop = NanoClock::now(); @@ -131,6 +136,9 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { } void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { + if (m_eventNumber < m_skipFirstNEvents) { + return; + } NanoClock::time_point event_stop = NanoClock::now(); m_eventTotSimTime = NanoClock::duration(event_stop - m_event_start).count(); if (m_ntuple->write().isFailure()) { @@ -139,16 +147,20 @@ void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { } void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { - info() << m_ntuple << endmsg; m_ntuple->reset(); m_eventNumber = event->GetEventID(); + if (m_eventNumber < m_skipFirstNEvents) { + return; + } m_event_start = NanoClock::now(); } void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { - if (!m_enableSubdetSimTimeRecording.value()) + if (!m_enableSubdetSimTimeRecording.value() || + m_eventNumber < m_skipFirstNEvents) { return; + } if (step->IsLastStepInVolume()) { auto subdet_stop = NanoClock::now(); m_timePerSubdet[getSubdetNameIdx(step->GetTrack()->GetTouchable())] += diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index ddebd7ca..07407219 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -47,6 +47,8 @@ private: NTuple::Item<double> m_eventTotSimTime; NanoClock::time_point m_event_start; + Gaudi::Property<int> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; + // simtime over subdet StatusCode initSubdetNames(); std::vector<std::string> m_subdetNames; @@ -59,6 +61,7 @@ private: NTuple::Array<double> m_timePerSubdet; // simtime over Track + static const unsigned MAX_TRACK_NUM = 25565; NanoClock::time_point m_track_start; Gaudi::Property<bool> m_enableTrackSimTimeRecording{ this, "EnableTrackSimTimeRecording", false}; -- GitLab From fb6b9613e1bace1e0d7d4970789a9d118a7167b2 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 11:37:48 +0800 Subject: [PATCH 16/74] fix: data type; getSubdetNameIdx --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 98 ++++++++++--------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 11 +-- 2 files changed, 58 insertions(+), 51 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 7558854c..73c8cd13 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -1,7 +1,7 @@ #include <GaudiKernel/StatusCode.h> -#include <array> #include <cassert> #include <cerrno> +#include <climits> #include "ChronoAnaElemTool.h" @@ -28,8 +28,6 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { // add subdets for (const auto &[name, subdet] : children) { - if (subdet.id() < 0) - continue; m_subdetNames.emplace_back(name); } @@ -57,26 +55,34 @@ StatusCode ChronoAnaElemTool::initNtuple() { "Simulation ChronoMetrics"); if (m_ntuple) { info() << "Create Ntuple Success" << endmsg; - suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX) + suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0L, LONG_MAX) .isSuccess(); suc &= m_ntuple->addItem("TotSimTime", m_eventTotSimTime).isSuccess(); - suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, MAX_TRACK_NUM) - .isSuccess(); - suc &= - m_ntuple - ->addItem("TimePerSubdet", m_subdetNames.size(), m_timePerSubdet) - .isSuccess(); - suc &= - m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTimes) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackLengthsOverTime", m_trackNum, - m_trackLengthsOverTime) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGIds) - .isSuccess(); + if (m_enableTrackSimTimeRecording.value()) { + suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0L, MAX_TRACK_NUM) + .isSuccess(); + suc &= + m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTimes) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGIds) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackStartSubdet", m_trackNum, + m_trackStartSubdet) + .isSuccess(); + suc &= + m_ntuple + ->addIndexedItem("TrackEndSubdet", m_trackNum, m_trackEndSubdet) + .isSuccess(); + } + if (m_enableSubdetSimTimeRecording.value()) { + suc &= m_ntuple + ->addItem("TimePerSubdet", m_subdetNames.size(), + m_timePerSubdet) + .isSuccess(); + } } else { error() << "Cannot book N-tuple:" << long(m_ntuple) << endmsg; return StatusCode::FAILURE; @@ -87,7 +93,7 @@ StatusCode ChronoAnaElemTool::initNtuple() { } StatusCode ChronoAnaElemTool::initialize() { - bool suc = true; + bool suc = AlgTool::initialize().isSuccess(); // Get services m_geomSvc = service<IGeomSvc>("GeomSvc"); @@ -108,13 +114,11 @@ StatusCode ChronoAnaElemTool::initialize() { } void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { - if (!m_enableTrackSimTimeRecording.value()) { - return; - } - if (m_eventNumber < m_skipFirstNEvents) { + if (!m_enableTrackSimTimeRecording.value() || + m_eventNumber < m_skipFirstNEvents) { return; } - + // info() << "Start Recording Track Num " << m_trackNum << endmsg; m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); m_track_start = NanoClock::now(); } @@ -128,8 +132,6 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { m_trackLengths[m_trackNum] = track->GetTrackLength(); m_trackTimes[m_trackNum] = NanoClock::duration(track_stop - m_track_start).count(); - m_trackLengthsOverTime[m_trackNum] = - m_trackLengths[m_trackNum] / m_trackTimes[m_trackNum]; m_trackPDGIds[m_trackNum] = track->GetParticleDefinition()->GetPDGEncoding(); m_trackEndSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); ++m_trackNum; @@ -163,7 +165,8 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { } if (step->IsLastStepInVolume()) { auto subdet_stop = NanoClock::now(); - m_timePerSubdet[getSubdetNameIdx(step->GetTrack()->GetTouchable())] += + auto subDetNameIdx = getSubdetNameIdx(step->GetTrack()->GetTouchable()); + m_timePerSubdet[subDetNameIdx] += NanoClock::duration(subdet_stop - m_subdet_enter).count(); } else if (step->IsFirstStepInVolume()) { m_subdet_enter = NanoClock::now(); @@ -172,36 +175,41 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { auto historyDepthNum = touch->GetHistoryDepth(); - for (int depth = 0; depth <= historyDepthNum; depth++) { + for (int depth = 0; depth <= historyDepthNum; ++depth) { auto vol = touch->GetVolume(depth); if (!vol) { - error() << "Volume is nullptr during finding " << depth << " in " - << historyDepthNum << endmsg; - return -1; + error() << "Volume is nullptr at depth " << depth << endmsg; + continue; } - auto volName = vol->GetName(); + std::string_view volName{vol->GetName()}; - // Check how many subdetector names are contained in the volume name - int foundCount = 0; int foundIndex = -1; - for (size_t i = 0; i < m_subdetNames.size(); ++i) { if (volName.find(m_subdetNames[i]) != std::string::npos) { - foundCount++; + if (foundIndex != -1) { + // Found more than one match, report an error and return -1 + error() << "Multiple matching subdetector names found in volume: " + << volName << " depth: " << depth << endmsg; + return -1; + } foundIndex = static_cast<int>(i); } } - // Return index if exactly one match found, otherwise -1 - return (foundCount == 1) ? foundIndex : -1; + // Found exactly one match, return the index + if (foundIndex != -1) { + // info() << "Found exactly one matching subdetector name in volume: " + // << volName << " depth: " << depth << endmsg; + return foundIndex; + } } - error() << "Volume is nullptr after find history " << historyDepthNum - << endmsg; + + error() << "No matching subdetector name found" << endmsg; return -1; } StatusCode ChronoAnaElemTool::finalize() { - StatusCode sc; + m_ntuple->reset(); - return sc; + return AlgTool::finalize(); } \ No newline at end of file diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 07407219..85e8ddf3 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -44,7 +44,7 @@ private: StatusCode initNtuple(); NTuple::Item<long> m_eventNumber; - NTuple::Item<double> m_eventTotSimTime; + NTuple::Item<long> m_eventTotSimTime; NanoClock::time_point m_event_start; Gaudi::Property<int> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; @@ -58,18 +58,17 @@ private: Gaudi::Property<bool> m_enableSubdetSimTimeRecording{ this, "EnableSubdetSimTimeRecording", false}; - NTuple::Array<double> m_timePerSubdet; + NTuple::Array<long> m_timePerSubdet; // simtime over Track - static const unsigned MAX_TRACK_NUM = 25565; + static const long MAX_TRACK_NUM = 100'000'000; // 0.1B NanoClock::time_point m_track_start; Gaudi::Property<bool> m_enableTrackSimTimeRecording{ this, "EnableTrackSimTimeRecording", false}; - NTuple::Item<unsigned> m_trackNum; + NTuple::Item<long> m_trackNum; NTuple::Array<double> m_trackLengths; - NTuple::Array<double> m_trackTimes; - NTuple::Array<double> m_trackLengthsOverTime; + NTuple::Array<long> m_trackTimes; NTuple::Array<int> m_trackPDGIds; NTuple::Array<int> m_trackStartSubdet; NTuple::Array<int> m_trackEndSubdet; -- GitLab From 7c37a0e403f0d30fd4abd889a885f2135d028287 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 12:06:24 +0800 Subject: [PATCH 17/74] fix: allow multiple matching subdetector names --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 73c8cd13..a4db8d2a 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -188,9 +188,10 @@ inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { if (volName.find(m_subdetNames[i]) != std::string::npos) { if (foundIndex != -1) { // Found more than one match, report an error and return -1 - error() << "Multiple matching subdetector names found in volume: " - << volName << " depth: " << depth << endmsg; - return -1; + info() << "Multiple matching subdetector names found in volume: " + << volName << " depth: " << depth + << " ,return first found index: " << foundIndex << endmsg; + return foundIndex; } foundIndex = static_cast<int>(i); } -- GitLab From cfe8aff182a8566b38f8b5c85b3d0a692799d815 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 12:08:03 +0800 Subject: [PATCH 18/74] fix: disallow multiple match --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index a4db8d2a..21f2ca43 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -183,26 +183,12 @@ inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { } std::string_view volName{vol->GetName()}; - int foundIndex = -1; for (size_t i = 0; i < m_subdetNames.size(); ++i) { if (volName.find(m_subdetNames[i]) != std::string::npos) { - if (foundIndex != -1) { - // Found more than one match, report an error and return -1 - info() << "Multiple matching subdetector names found in volume: " - << volName << " depth: " << depth - << " ,return first found index: " << foundIndex << endmsg; - return foundIndex; - } - foundIndex = static_cast<int>(i); + // Found a or more match, return the index + return static_cast<int>(i); } } - - // Found exactly one match, return the index - if (foundIndex != -1) { - // info() << "Found exactly one matching subdetector name in volume: " - // << volName << " depth: " << depth << endmsg; - return foundIndex; - } } error() << "No matching subdetector name found" << endmsg; -- GitLab From cfdd50fe4854cca4ca19c8834fd6ab620d80114f Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 12:11:54 +0800 Subject: [PATCH 19/74] fix: use error to print subdet names --- .vscode | 1 + Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) create mode 160000 .vscode diff --git a/.vscode b/.vscode new file mode 160000 index 00000000..51256046 --- /dev/null +++ b/.vscode @@ -0,0 +1 @@ +Subproject commit 51256046f3df0e7c007be8bf892d69c1e9bd523b diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 21f2ca43..a1e30788 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -31,12 +31,11 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { m_subdetNames.emplace_back(name); } - // print subdets to log file - - info() << "=== Subdetector Names List (" << m_subdetNames.size() + // print subdets to log file, use ERROR level for performance reasons + error() << "=== Subdetector Names List (" << m_subdetNames.size() << ") ===" << endmsg; for (size_t i = 0; i < m_subdetNames.size(); ++i) { - info() << "[" << std::setw(2) << i << "] " << m_subdetNames[i] << endmsg; + error() << "[" << std::setw(2) << i << "] " << m_subdetNames[i] << endmsg; } return StatusCode::SUCCESS; -- GitLab From ae6496831352fbf63c950d01bc3f987a2b2072c7 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 13:40:29 +0800 Subject: [PATCH 20/74] fix: add unknown subdet --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 11 ++++++++--- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index a1e30788..86b33fd6 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -21,9 +21,10 @@ DECLARE_COMPONENT(ChronoAnaElemTool) StatusCode ChronoAnaElemTool::initSubdetNames() { const auto &children = m_geomSvc->getDD4HepGeo().children(); m_subdetNames.clear(); - m_subdetNames.reserve(children.size() + 1); + m_subdetNames.reserve(children.size() + 2); // add pWorld and Unknown subdet // add pWorld + m_subdetNames.emplace_back("Unknown"); m_subdetNames.emplace_back("pWorld"); // add subdets @@ -33,7 +34,7 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { // print subdets to log file, use ERROR level for performance reasons error() << "=== Subdetector Names List (" << m_subdetNames.size() - << ") ===" << endmsg; + << ") ===" << endmsg; for (size_t i = 0; i < m_subdetNames.size(); ++i) { error() << "[" << std::setw(2) << i << "] " << m_subdetNames[i] << endmsg; } @@ -191,7 +192,11 @@ inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { } error() << "No matching subdetector name found" << endmsg; - return -1; + for (int depth = 0; depth <= historyDepthNum; ++depth) { + auto vol = touch->GetVolume(depth); + error() << "Volume at depth " << depth << ": " << vol->GetName() << endmsg; + } + return UNKNOWN_SUBDET; } StatusCode ChronoAnaElemTool::finalize() { diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 85e8ddf3..a804011a 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -51,6 +51,7 @@ private: // simtime over subdet StatusCode initSubdetNames(); + static const int UNKNOWN_SUBDET = 0; std::vector<std::string> m_subdetNames; inline int getSubdetNameIdx(const G4VTouchable *); -- GitLab From ffb0773664104fca50c09623b99b47e3e73252f9 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 13:46:41 +0800 Subject: [PATCH 21/74] fix: search exclude unknown --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 86b33fd6..81baa18d 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -183,7 +183,9 @@ inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { } std::string_view volName{vol->GetName()}; - for (size_t i = 0; i < m_subdetNames.size(); ++i) { + // start from the second subdetector name, as the first one is always + // Unknown + for (size_t i = 1; i < m_subdetNames.size(); ++i) { if (volName.find(m_subdetNames[i]) != std::string::npos) { // Found a or more match, return the index return static_cast<int>(i); -- GitLab From 3fca1c731ff1b77d91015f787e2447a2e4bcdcbb Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 13:56:44 +0800 Subject: [PATCH 22/74] fix: replace int with size_t --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 21 ++++++++++--------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 17 ++++++++------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 81baa18d..e921b4ad 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -2,6 +2,7 @@ #include <cassert> #include <cerrno> #include <climits> +#include <cstddef> #include "ChronoAnaElemTool.h" @@ -55,11 +56,11 @@ StatusCode ChronoAnaElemTool::initNtuple() { "Simulation ChronoMetrics"); if (m_ntuple) { info() << "Create Ntuple Success" << endmsg; - suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0L, LONG_MAX) + suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0UL, ULONG_MAX) .isSuccess(); suc &= m_ntuple->addItem("TotSimTime", m_eventTotSimTime).isSuccess(); if (m_enableTrackSimTimeRecording.value()) { - suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0L, MAX_TRACK_NUM) + suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0UL, MAX_TRACK_NUM) .isSuccess(); suc &= m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) @@ -115,7 +116,7 @@ StatusCode ChronoAnaElemTool::initialize() { void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { if (!m_enableTrackSimTimeRecording.value() || - m_eventNumber < m_skipFirstNEvents) { + m_eventNumber < m_skipFirstNEvents.value()) { return; } // info() << "Start Recording Track Num " << m_trackNum << endmsg; @@ -125,7 +126,7 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { if (!m_enableTrackSimTimeRecording.value() || - m_eventNumber < m_skipFirstNEvents) { + m_eventNumber < m_skipFirstNEvents.value()) { return; } NanoClock::time_point track_stop = NanoClock::now(); @@ -138,7 +139,7 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { } void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { - if (m_eventNumber < m_skipFirstNEvents) { + if (m_eventNumber < m_skipFirstNEvents.value()) { return; } NanoClock::time_point event_stop = NanoClock::now(); @@ -150,8 +151,8 @@ void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { m_ntuple->reset(); - m_eventNumber = event->GetEventID(); - if (m_eventNumber < m_skipFirstNEvents) { + m_eventNumber = static_cast<size_t>(event->GetEventID()); + if (m_eventNumber < m_skipFirstNEvents.value()) { return; } @@ -160,7 +161,7 @@ void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { if (!m_enableSubdetSimTimeRecording.value() || - m_eventNumber < m_skipFirstNEvents) { + m_eventNumber < m_skipFirstNEvents.value()) { return; } if (step->IsLastStepInVolume()) { @@ -173,7 +174,7 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { } } -inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { +inline size_t ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { auto historyDepthNum = touch->GetHistoryDepth(); for (int depth = 0; depth <= historyDepthNum; ++depth) { auto vol = touch->GetVolume(depth); @@ -188,7 +189,7 @@ inline int ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { for (size_t i = 1; i < m_subdetNames.size(); ++i) { if (volName.find(m_subdetNames[i]) != std::string::npos) { // Found a or more match, return the index - return static_cast<int>(i); + return i; } } } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index a804011a..a29178ea 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -3,6 +3,7 @@ #include <G4VTouchable.hh> #include <chrono> +#include <cstddef> #include <string> #include <vector> @@ -43,17 +44,17 @@ private: NTuple::Tuple *m_ntuple; StatusCode initNtuple(); - NTuple::Item<long> m_eventNumber; + NTuple::Item<size_t> m_eventNumber; NTuple::Item<long> m_eventTotSimTime; NanoClock::time_point m_event_start; - Gaudi::Property<int> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; + Gaudi::Property<size_t> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; // simtime over subdet StatusCode initSubdetNames(); - static const int UNKNOWN_SUBDET = 0; + static const size_t UNKNOWN_SUBDET = 0; std::vector<std::string> m_subdetNames; - inline int getSubdetNameIdx(const G4VTouchable *); + inline size_t getSubdetNameIdx(const G4VTouchable *); NanoClock::time_point m_subdet_enter; Gaudi::Property<bool> m_enableSubdetSimTimeRecording{ @@ -62,17 +63,17 @@ private: NTuple::Array<long> m_timePerSubdet; // simtime over Track - static const long MAX_TRACK_NUM = 100'000'000; // 0.1B + static const size_t MAX_TRACK_NUM = 100'000'000; // 0.1B NanoClock::time_point m_track_start; Gaudi::Property<bool> m_enableTrackSimTimeRecording{ this, "EnableTrackSimTimeRecording", false}; - NTuple::Item<long> m_trackNum; + NTuple::Item<size_t> m_trackNum; NTuple::Array<double> m_trackLengths; NTuple::Array<long> m_trackTimes; NTuple::Array<int> m_trackPDGIds; - NTuple::Array<int> m_trackStartSubdet; - NTuple::Array<int> m_trackEndSubdet; + NTuple::Array<size_t> m_trackStartSubdet; + NTuple::Array<size_t> m_trackEndSubdet; }; #endif -- GitLab From 77a8dd7c3647e5adb6554611fe78a202c8801222 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 14:14:58 +0800 Subject: [PATCH 23/74] fix: manage index uniformly --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 10 +++++----- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 6 ++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index e921b4ad..810dd094 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -22,7 +22,7 @@ DECLARE_COMPONENT(ChronoAnaElemTool) StatusCode ChronoAnaElemTool::initSubdetNames() { const auto &children = m_geomSvc->getDD4HepGeo().children(); m_subdetNames.clear(); - m_subdetNames.reserve(children.size() + 2); // add pWorld and Unknown subdet + m_subdetNames.reserve(children.size() + SpecialCount); // add pWorld and Unknown subdet // add pWorld m_subdetNames.emplace_back("Unknown"); @@ -37,7 +37,7 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { error() << "=== Subdetector Names List (" << m_subdetNames.size() << ") ===" << endmsg; for (size_t i = 0; i < m_subdetNames.size(); ++i) { - error() << "[" << std::setw(2) << i << "] " << m_subdetNames[i] << endmsg; + error() << "[" << i << "] " << m_subdetNames[i] << endmsg; } return StatusCode::SUCCESS; @@ -184,9 +184,9 @@ inline size_t ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { } std::string_view volName{vol->GetName()}; - // start from the second subdetector name, as the first one is always + // start from the PWorldIndex subdetector name, as the first one is always // Unknown - for (size_t i = 1; i < m_subdetNames.size(); ++i) { + for (size_t i = PWorldIndex; i < m_subdetNames.size(); ++i) { if (volName.find(m_subdetNames[i]) != std::string::npos) { // Found a or more match, return the index return i; @@ -199,7 +199,7 @@ inline size_t ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { auto vol = touch->GetVolume(depth); error() << "Volume at depth " << depth << ": " << vol->GetName() << endmsg; } - return UNKNOWN_SUBDET; + return UnknownIndex; } StatusCode ChronoAnaElemTool::finalize() { diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index a29178ea..2d58eeae 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -52,7 +52,9 @@ private: // simtime over subdet StatusCode initSubdetNames(); - static const size_t UNKNOWN_SUBDET = 0; + static constexpr size_t UnknownIndex = 0; + static constexpr size_t PWorldIndex = 1; + static constexpr size_t SpecialCount = 2; std::vector<std::string> m_subdetNames; inline size_t getSubdetNameIdx(const G4VTouchable *); @@ -63,7 +65,7 @@ private: NTuple::Array<long> m_timePerSubdet; // simtime over Track - static const size_t MAX_TRACK_NUM = 100'000'000; // 0.1B + static constexpr size_t MAX_TRACK_NUM = 100'000'000; // 0.1B NanoClock::time_point m_track_start; Gaudi::Property<bool> m_enableTrackSimTimeRecording{ this, "EnableTrackSimTimeRecording", false}; -- GitLab From 0cc5af9608ef2684dc80d5fb3acd6757bdc84b99 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 14:20:20 +0800 Subject: [PATCH 24/74] fix: init subdet names anyway --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 810dd094..e9dbc3dd 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -107,9 +107,7 @@ StatusCode ChronoAnaElemTool::initialize() { NanoClock::calibrate(); // init subdet names and number - if (m_enableSubdetSimTimeRecording.value()) { - suc &= initSubdetNames().isSuccess(); - } + suc &= initSubdetNames().isSuccess(); suc &= initNtuple().isSuccess(); return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } -- GitLab From 92a9791608fae8e2b313d5e35c8dacd005295581 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 15:07:10 +0800 Subject: [PATCH 25/74] fix: track num limit --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index e9dbc3dd..bccf8016 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -22,7 +22,8 @@ DECLARE_COMPONENT(ChronoAnaElemTool) StatusCode ChronoAnaElemTool::initSubdetNames() { const auto &children = m_geomSvc->getDD4HepGeo().children(); m_subdetNames.clear(); - m_subdetNames.reserve(children.size() + SpecialCount); // add pWorld and Unknown subdet + m_subdetNames.reserve(children.size() + + SpecialCount); // add pWorld and Unknown subdet // add pWorld m_subdetNames.emplace_back("Unknown"); @@ -117,7 +118,10 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_eventNumber < m_skipFirstNEvents.value()) { return; } - // info() << "Start Recording Track Num " << m_trackNum << endmsg; + if (m_trackNum >= MAX_TRACK_NUM) { + error() << "Exceeded MAX_TRACK_NUM at event " << m_eventNumber << endmsg; + return; + } m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); m_track_start = NanoClock::now(); } -- GitLab From a109d4f3f5223f15f68b526cff576726045506ce Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 15:08:29 +0800 Subject: [PATCH 26/74] fix: remove meaningless output --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index bccf8016..df3f3334 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -86,7 +86,7 @@ StatusCode ChronoAnaElemTool::initNtuple() { .isSuccess(); } } else { - error() << "Cannot book N-tuple:" << long(m_ntuple) << endmsg; + error() << "Cannot book N-tuple." << endmsg; return StatusCode::FAILURE; } } -- GitLab From c9616be10bc786047cb58975fc317f3a7f28a816 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sun, 25 May 2025 16:49:29 +0800 Subject: [PATCH 27/74] fix: throw error when exceed --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index df3f3334..25c55d63 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -3,6 +3,8 @@ #include <cerrno> #include <climits> #include <cstddef> +#include <cstdlib> +#include <string> #include "ChronoAnaElemTool.h" @@ -11,6 +13,7 @@ #include "G4Track.hh" #include "GaudiAlg/GaudiAlgorithm.h" #include "GaudiKernel/ClassID.h" +#include "GaudiKernel/GaudiException.h" #include "GaudiKernel/MsgStream.h" #include "GaudiKernel/NTuple.h" #include "GaudiKernel/SmartIF.h" @@ -120,7 +123,9 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { } if (m_trackNum >= MAX_TRACK_NUM) { error() << "Exceeded MAX_TRACK_NUM at event " << m_eventNumber << endmsg; - return; + throw GaudiException("Exceeded MAX_TRACK_NUM at event " + + std::to_string(m_eventNumber), + "ChronoAnaElemTool", StatusCode::FAILURE); } m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); m_track_start = NanoClock::now(); -- GitLab From 2a6aa455a28ccdf0e7f16cfeb016d93560c15e30 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 26 May 2025 12:13:42 +0800 Subject: [PATCH 28/74] fix: make time to int64 --- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 2d58eeae..6b5887c5 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -45,7 +45,7 @@ private: StatusCode initNtuple(); NTuple::Item<size_t> m_eventNumber; - NTuple::Item<long> m_eventTotSimTime; + NTuple::Item<long long> m_eventTotSimTime; NanoClock::time_point m_event_start; Gaudi::Property<size_t> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; @@ -62,7 +62,7 @@ private: Gaudi::Property<bool> m_enableSubdetSimTimeRecording{ this, "EnableSubdetSimTimeRecording", false}; - NTuple::Array<long> m_timePerSubdet; + NTuple::Array<long long> m_timePerSubdet; // simtime over Track static constexpr size_t MAX_TRACK_NUM = 100'000'000; // 0.1B @@ -72,7 +72,7 @@ private: NTuple::Item<size_t> m_trackNum; NTuple::Array<double> m_trackLengths; - NTuple::Array<long> m_trackTimes; + NTuple::Array<long long> m_trackTimes; NTuple::Array<int> m_trackPDGIds; NTuple::Array<size_t> m_trackStartSubdet; NTuple::Array<size_t> m_trackEndSubdet; -- GitLab From efbfa48f438a4498dbfb2ab2607a2d986742626b Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 26 May 2025 12:24:10 +0800 Subject: [PATCH 29/74] fix: make size clear --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 8 ++++---- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 9 +++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 25c55d63..bb18c34f 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -2,7 +2,6 @@ #include <cassert> #include <cerrno> #include <climits> -#include <cstddef> #include <cstdlib> #include <string> @@ -60,11 +59,11 @@ StatusCode ChronoAnaElemTool::initNtuple() { "Simulation ChronoMetrics"); if (m_ntuple) { info() << "Create Ntuple Success" << endmsg; - suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0UL, ULONG_MAX) + suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX) .isSuccess(); suc &= m_ntuple->addItem("TotSimTime", m_eventTotSimTime).isSuccess(); if (m_enableTrackSimTimeRecording.value()) { - suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0UL, MAX_TRACK_NUM) + suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, MAX_TRACK_NUM) .isSuccess(); suc &= m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) @@ -181,7 +180,8 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { } } -inline size_t ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { +inline ChronoAnaElemTool::size_t +ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { auto historyDepthNum = touch->GetHistoryDepth(); for (int depth = 0; depth <= historyDepthNum; ++depth) { auto vol = touch->GetVolume(depth); diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 6b5887c5..974cad3f 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -3,7 +3,6 @@ #include <G4VTouchable.hh> #include <chrono> -#include <cstddef> #include <string> #include <vector> @@ -21,6 +20,8 @@ class ChronoAnaElemTool : public extends<AlgTool, IAnaElemTool> { public: using extends::extends; using NanoClock = Gaudi::Timers::RdtscClock<std::chrono::nanoseconds>; + typedef unsigned long long time_t; + typedef unsigned int size_t; // Event virtual void BeginOfEventAction(const G4Event *) override; @@ -45,7 +46,7 @@ private: StatusCode initNtuple(); NTuple::Item<size_t> m_eventNumber; - NTuple::Item<long long> m_eventTotSimTime; + NTuple::Item<time_t> m_eventTotSimTime; NanoClock::time_point m_event_start; Gaudi::Property<size_t> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; @@ -62,7 +63,7 @@ private: Gaudi::Property<bool> m_enableSubdetSimTimeRecording{ this, "EnableSubdetSimTimeRecording", false}; - NTuple::Array<long long> m_timePerSubdet; + NTuple::Array<time_t> m_timePerSubdet; // simtime over Track static constexpr size_t MAX_TRACK_NUM = 100'000'000; // 0.1B @@ -72,7 +73,7 @@ private: NTuple::Item<size_t> m_trackNum; NTuple::Array<double> m_trackLengths; - NTuple::Array<long long> m_trackTimes; + NTuple::Array<time_t> m_trackTimes; NTuple::Array<int> m_trackPDGIds; NTuple::Array<size_t> m_trackStartSubdet; NTuple::Array<size_t> m_trackEndSubdet; -- GitLab From 014b5d84565f79d8e351141d9386995a4aebdd44 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 27 May 2025 11:36:03 +0800 Subject: [PATCH 30/74] fix: add debug to log out subdets --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index bb18c34f..bc22fb19 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -196,6 +196,8 @@ ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { for (size_t i = PWorldIndex; i < m_subdetNames.size(); ++i) { if (volName.find(m_subdetNames[i]) != std::string::npos) { // Found a or more match, return the index + // info() << "Found subdetector name: " << m_subdetNames[i] << " at depth " + // << depth << " with volName: " << volName << endmsg; return i; } } -- GitLab From 408004fb82d2094a3e142255873e9934e71accf2 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 27 May 2025 14:47:09 +0800 Subject: [PATCH 31/74] fix: subdet alg renewed --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 15 +++++++++------ Simulation/DetSimAna/src/ChronoAnaElemTool.h | 3 +++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index bc22fb19..7268d2c1 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -170,12 +170,14 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { m_eventNumber < m_skipFirstNEvents.value()) { return; } - if (step->IsLastStepInVolume()) { - auto subdet_stop = NanoClock::now(); + if (step->IsFirstStepInVolume()) { + if (m_currentSubdetIndex != UninitializedIndex) { + auto subdet_stop = NanoClock::now(); + m_timePerSubdet[m_currentSubdetIndex] += + NanoClock::duration(subdet_stop - m_subdet_enter).count(); + } auto subDetNameIdx = getSubdetNameIdx(step->GetTrack()->GetTouchable()); - m_timePerSubdet[subDetNameIdx] += - NanoClock::duration(subdet_stop - m_subdet_enter).count(); - } else if (step->IsFirstStepInVolume()) { + m_currentSubdetIndex = subDetNameIdx; m_subdet_enter = NanoClock::now(); } } @@ -196,7 +198,8 @@ ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { for (size_t i = PWorldIndex; i < m_subdetNames.size(); ++i) { if (volName.find(m_subdetNames[i]) != std::string::npos) { // Found a or more match, return the index - // info() << "Found subdetector name: " << m_subdetNames[i] << " at depth " + // info() << "Found subdetector name: " << m_subdetNames[i] << " at + // depth " // << depth << " with volName: " << volName << endmsg; return i; } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 974cad3f..3eadcabd 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -3,6 +3,7 @@ #include <G4VTouchable.hh> #include <chrono> +#include <climits> #include <string> #include <vector> @@ -56,8 +57,10 @@ private: static constexpr size_t UnknownIndex = 0; static constexpr size_t PWorldIndex = 1; static constexpr size_t SpecialCount = 2; + static constexpr size_t UninitializedIndex = UINT_MAX; std::vector<std::string> m_subdetNames; inline size_t getSubdetNameIdx(const G4VTouchable *); + size_t m_currentSubdetIndex = UninitializedIndex; NanoClock::time_point m_subdet_enter; Gaudi::Property<bool> m_enableSubdetSimTimeRecording{ -- GitLab From a6318b45e53adcbbc880174f84198e7497076458 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 27 May 2025 16:23:35 +0800 Subject: [PATCH 32/74] fix: add event number --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 7268d2c1..1638d002 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -158,6 +158,7 @@ void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { m_ntuple->reset(); m_eventNumber = static_cast<size_t>(event->GetEventID()); + always() << "ChronoAnaElemTool: Event number: " << m_eventNumber << endmsg; if (m_eventNumber < m_skipFirstNEvents.value()) { return; } -- GitLab From a1c6a20968c8c85e85be4711981cbd8733a26efb Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Wed, 28 May 2025 10:34:37 +0800 Subject: [PATCH 33/74] fix: add track step num --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 4 ++++ Simulation/DetSimAna/src/ChronoAnaElemTool.h | 1 + 2 files changed, 5 insertions(+) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 1638d002..c071dddc 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -80,6 +80,9 @@ StatusCode ChronoAnaElemTool::initNtuple() { m_ntuple ->addIndexedItem("TrackEndSubdet", m_trackNum, m_trackEndSubdet) .isSuccess(); + suc &= + m_ntuple->addIndexedItem("TrackStepNum", m_trackNum, m_trackStepNum) + .isSuccess(); } if (m_enableSubdetSimTimeRecording.value()) { suc &= m_ntuple @@ -139,6 +142,7 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { m_trackLengths[m_trackNum] = track->GetTrackLength(); m_trackTimes[m_trackNum] = NanoClock::duration(track_stop - m_track_start).count(); + m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); m_trackPDGIds[m_trackNum] = track->GetParticleDefinition()->GetPDGEncoding(); m_trackEndSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); ++m_trackNum; diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 3eadcabd..f5d01e9a 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -77,6 +77,7 @@ private: NTuple::Item<size_t> m_trackNum; NTuple::Array<double> m_trackLengths; NTuple::Array<time_t> m_trackTimes; + NTuple::Array<int> m_trackStepNum; NTuple::Array<int> m_trackPDGIds; NTuple::Array<size_t> m_trackStartSubdet; NTuple::Array<size_t> m_trackEndSubdet; -- GitLab From 880baa65beed4582c1a7474f4670a7698860be4c Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Wed, 28 May 2025 16:33:00 +0800 Subject: [PATCH 34/74] fix: add per subdet time to track --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 88 ++++++++++--------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 13 ++- 2 files changed, 52 insertions(+), 49 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index c071dddc..4abdb318 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -1,3 +1,4 @@ +#include <G4StepStatus.hh> #include <GaudiKernel/StatusCode.h> #include <cassert> #include <cerrno> @@ -43,6 +44,11 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { error() << "[" << i << "] " << m_subdetNames[i] << endmsg; } + if (m_subdetNames.size() > MAX_SUBDET_NUM) { + throw GaudiException("m_subdetNames size exceeded MAX_SUBDET_NUM", + "ChronoAnaElemTool", StatusCode::FAILURE); + } + return StatusCode::SUCCESS; } @@ -62,34 +68,34 @@ StatusCode ChronoAnaElemTool::initNtuple() { suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX) .isSuccess(); suc &= m_ntuple->addItem("TotSimTime", m_eventTotSimTime).isSuccess(); - if (m_enableTrackSimTimeRecording.value()) { - suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, MAX_TRACK_NUM) - .isSuccess(); - suc &= - m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTimes) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGIds) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackStartSubdet", m_trackNum, - m_trackStartSubdet) - .isSuccess(); - suc &= - m_ntuple - ->addIndexedItem("TrackEndSubdet", m_trackNum, m_trackEndSubdet) - .isSuccess(); - suc &= - m_ntuple->addIndexedItem("TrackStepNum", m_trackNum, m_trackStepNum) - .isSuccess(); - } - if (m_enableSubdetSimTimeRecording.value()) { - suc &= m_ntuple - ->addItem("TimePerSubdet", m_subdetNames.size(), - m_timePerSubdet) - .isSuccess(); - } + suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, MAX_TRACK_NUM) + .isSuccess(); + suc &= + m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTimes) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackTimeOverhead", m_trackNum, + m_trackTimeOverhead) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGIds) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackStartSubdet", m_trackNum, + m_trackStartSubdet) + .isSuccess(); + suc &= + m_ntuple + ->addIndexedItem("TrackEndSubdet", m_trackNum, m_trackEndSubdet) + .isSuccess(); + suc &= + m_ntuple->addIndexedItem("TrackStepNum", m_trackNum, m_trackStepNum) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackTimePerSubdet", m_trackNum, + MAX_SUBDET_NUM, m_trackTimePerSubdet) + .isSuccess(); } else { error() << "Cannot book N-tuple." << endmsg; return StatusCode::FAILURE; @@ -119,8 +125,7 @@ StatusCode ChronoAnaElemTool::initialize() { } void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { - if (!m_enableTrackSimTimeRecording.value() || - m_eventNumber < m_skipFirstNEvents.value()) { + if (m_eventNumber < m_skipFirstNEvents.value()) { return; } if (m_trackNum >= MAX_TRACK_NUM) { @@ -129,13 +134,14 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { std::to_string(m_eventNumber), "ChronoAnaElemTool", StatusCode::FAILURE); } - m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); - m_track_start = NanoClock::now(); + m_currentSubdetIndex = getSubdetNameIdx(track->GetTouchable()); + m_trackStartSubdet[m_trackNum] = m_currentSubdetIndex; + m_step_overhead = m_step_overhead.zero(); + m_track_start = m_subdet_enter = NanoClock::now(); } void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { - if (!m_enableTrackSimTimeRecording.value() || - m_eventNumber < m_skipFirstNEvents.value()) { + if (m_eventNumber < m_skipFirstNEvents.value()) { return; } NanoClock::time_point track_stop = NanoClock::now(); @@ -145,6 +151,8 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); m_trackPDGIds[m_trackNum] = track->GetParticleDefinition()->GetPDGEncoding(); m_trackEndSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); + m_trackTimeOverhead[m_trackNum] = + NanoClock::duration(m_step_overhead).count(); ++m_trackNum; } @@ -171,19 +179,17 @@ void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { } void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { - if (!m_enableSubdetSimTimeRecording.value() || - m_eventNumber < m_skipFirstNEvents.value()) { + if (m_eventNumber < m_skipFirstNEvents.value()) { return; } if (step->IsFirstStepInVolume()) { - if (m_currentSubdetIndex != UninitializedIndex) { - auto subdet_stop = NanoClock::now(); - m_timePerSubdet[m_currentSubdetIndex] += - NanoClock::duration(subdet_stop - m_subdet_enter).count(); - } + auto subdet_stop = NanoClock::now(); + m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += + NanoClock::duration(subdet_stop - m_subdet_enter).count(); auto subDetNameIdx = getSubdetNameIdx(step->GetTrack()->GetTouchable()); m_currentSubdetIndex = subDetNameIdx; m_subdet_enter = NanoClock::now(); + m_step_overhead += (m_subdet_enter - subdet_stop); } } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index f5d01e9a..968a13f4 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -62,21 +62,18 @@ private: inline size_t getSubdetNameIdx(const G4VTouchable *); size_t m_currentSubdetIndex = UninitializedIndex; - NanoClock::time_point m_subdet_enter; - Gaudi::Property<bool> m_enableSubdetSimTimeRecording{ - this, "EnableSubdetSimTimeRecording", false}; - - NTuple::Array<time_t> m_timePerSubdet; - // simtime over Track static constexpr size_t MAX_TRACK_NUM = 100'000'000; // 0.1B + static constexpr size_t MAX_SUBDET_NUM = 30; NanoClock::time_point m_track_start; - Gaudi::Property<bool> m_enableTrackSimTimeRecording{ - this, "EnableTrackSimTimeRecording", false}; + NanoClock::time_point m_subdet_enter; + NanoClock::duration m_step_overhead{0}; NTuple::Item<size_t> m_trackNum; NTuple::Array<double> m_trackLengths; NTuple::Array<time_t> m_trackTimes; + NTuple::Array<time_t> m_trackTimeOverhead; + NTuple::Matrix<time_t> m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx NTuple::Array<int> m_trackStepNum; NTuple::Array<int> m_trackPDGIds; NTuple::Array<size_t> m_trackStartSubdet; -- GitLab From e17efeab0f11bae7beb262321bf24ad7e3a5dca6 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Wed, 28 May 2025 16:54:40 +0800 Subject: [PATCH 35/74] fix: add charge --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 3 +++ Simulation/DetSimAna/src/ChronoAnaElemTool.h | 1 + 2 files changed, 4 insertions(+) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 4abdb318..67976d0e 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -89,6 +89,8 @@ StatusCode ChronoAnaElemTool::initNtuple() { m_ntuple ->addIndexedItem("TrackEndSubdet", m_trackNum, m_trackEndSubdet) .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackCharge", m_trackNum, m_trackCharge) + .isSuccess(); suc &= m_ntuple->addIndexedItem("TrackStepNum", m_trackNum, m_trackStepNum) .isSuccess(); @@ -149,6 +151,7 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { m_trackTimes[m_trackNum] = NanoClock::duration(track_stop - m_track_start).count(); m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); + m_trackCharge[m_trackNum] = track->GetParticleDefinition()->GetPDGCharge(); m_trackPDGIds[m_trackNum] = track->GetParticleDefinition()->GetPDGEncoding(); m_trackEndSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); m_trackTimeOverhead[m_trackNum] = diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 968a13f4..78061c09 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -71,6 +71,7 @@ private: NTuple::Item<size_t> m_trackNum; NTuple::Array<double> m_trackLengths; + NTuple::Array<double> m_trackCharge; NTuple::Array<time_t> m_trackTimes; NTuple::Array<time_t> m_trackTimeOverhead; NTuple::Matrix<time_t> m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx -- GitLab From 3e2706aa3592200a6a5508a3b64716b35c2bc0a5 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Wed, 28 May 2025 17:44:53 +0800 Subject: [PATCH 36/74] fix: add track id momentum energy; reduce MAX_TRACK_NUM --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 29 ++++++++++++++++++- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 10 +++++-- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 67976d0e..31c8fac2 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -8,6 +8,7 @@ #include "ChronoAnaElemTool.h" +#include "CLHEP/Units/SystemOfUnits.h" #include "G4Event.hh" #include "G4Step.hh" #include "G4Track.hh" @@ -70,6 +71,12 @@ StatusCode ChronoAnaElemTool::initNtuple() { suc &= m_ntuple->addItem("TotSimTime", m_eventTotSimTime).isSuccess(); suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, MAX_TRACK_NUM) .isSuccess(); + suc &= m_ntuple->addItem("TrackPx", m_trackNum, m_px); + suc &= m_ntuple->addItem("TrackPy", m_trackNum, m_py); + suc &= m_ntuple->addItem("TrackPz", m_trackNum, m_pz); + suc &= m_ntuple->addItem("TrackX", m_trackNum, m_x); + suc &= m_ntuple->addItem("TrackY", m_trackNum, m_y); + suc &= m_ntuple->addItem("TrackZ", m_trackNum, m_z); suc &= m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) .isSuccess(); @@ -94,6 +101,15 @@ StatusCode ChronoAnaElemTool::initNtuple() { suc &= m_ntuple->addIndexedItem("TrackStepNum", m_trackNum, m_trackStepNum) .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackID", m_trackNum, m_trackID) + .isSuccess(); + suc &= + m_ntuple->addIndexedItem("TrackParentID", m_trackNum, m_trackParentID) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackKineticEnergy", m_trackNum, + m_trackKineticEnergy) + .isSuccess(); suc &= m_ntuple ->addIndexedItem("TrackTimePerSubdet", m_trackNum, MAX_SUBDET_NUM, m_trackTimePerSubdet) @@ -139,6 +155,17 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_currentSubdetIndex = getSubdetNameIdx(track->GetTouchable()); m_trackStartSubdet[m_trackNum] = m_currentSubdetIndex; m_step_overhead = m_step_overhead.zero(); + m_trackID[m_trackNum] = track->GetTrackID(); + m_trackParentID[m_trackNum] = track->GetParentID(); + m_trackKineticEnergy[m_trackNum] = track->GetKineticEnergy() / CLHEP::GeV; + auto mom = track->GetMomentum(); + auto pos = track->GetPosition(); + m_px[m_trackNum] = mom.x() / CLHEP::GeV; + m_py[m_trackNum] = mom.y() / CLHEP::GeV; + m_pz[m_trackNum] = mom.z() / CLHEP::GeV; + m_x[m_trackNum] = pos.x() / CLHEP::mm; + m_y[m_trackNum] = pos.y() / CLHEP::mm; + m_z[m_trackNum] = pos.z() / CLHEP::mm; m_track_start = m_subdet_enter = NanoClock::now(); } @@ -147,7 +174,7 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { return; } NanoClock::time_point track_stop = NanoClock::now(); - m_trackLengths[m_trackNum] = track->GetTrackLength(); + m_trackLengths[m_trackNum] = track->GetTrackLength() / CLHEP::mm; m_trackTimes[m_trackNum] = NanoClock::duration(track_stop - m_track_start).count(); m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 78061c09..241f2ea3 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -63,18 +63,24 @@ private: size_t m_currentSubdetIndex = UninitializedIndex; // simtime over Track - static constexpr size_t MAX_TRACK_NUM = 100'000'000; // 0.1B + static constexpr size_t MAX_TRACK_NUM = 10'000'000; // 10M static constexpr size_t MAX_SUBDET_NUM = 30; NanoClock::time_point m_track_start; NanoClock::time_point m_subdet_enter; NanoClock::duration m_step_overhead{0}; NTuple::Item<size_t> m_trackNum; + NTuple::Array<int> m_trackID; + NTuple::Array<int> m_trackParentID; + NTuple::Array<double> m_trackKineticEnergy; + NTuple::Array<double> m_px, m_py, m_pz; + NTuple::Array<double> m_x, m_y, m_z; NTuple::Array<double> m_trackLengths; NTuple::Array<double> m_trackCharge; NTuple::Array<time_t> m_trackTimes; NTuple::Array<time_t> m_trackTimeOverhead; - NTuple::Matrix<time_t> m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx + NTuple::Matrix<time_t> + m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx NTuple::Array<int> m_trackStepNum; NTuple::Array<int> m_trackPDGIds; NTuple::Array<size_t> m_trackStartSubdet; -- GitLab From 2ef282a978251545ceb867bbd90311ba256631ec Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 29 May 2025 11:30:00 +0800 Subject: [PATCH 37/74] feat: add metric to see if frequently call causeing waste --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 18 ++++++++++++++++-- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 3 +++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 31c8fac2..f614de10 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -114,6 +114,14 @@ StatusCode ChronoAnaElemTool::initNtuple() { ->addIndexedItem("TrackTimePerSubdet", m_trackNum, MAX_SUBDET_NUM, m_trackTimePerSubdet) .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackStepsPerSubdet", m_trackNum, + MAX_SUBDET_NUM, m_trackStepsPerSubdet) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackStepsPerSubdet", m_trackNum, + MAX_SUBDET_NUM, m_trackTriggerCountPerSubdet) + .isSuccess(); } else { error() << "Cannot book N-tuple." << endmsg; return StatusCode::FAILURE; @@ -166,6 +174,7 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_x[m_trackNum] = pos.x() / CLHEP::mm; m_y[m_trackNum] = pos.y() / CLHEP::mm; m_z[m_trackNum] = pos.z() / CLHEP::mm; + m_currentStepNum = track->GetCurrentStepNumber(); m_track_start = m_subdet_enter = NanoClock::now(); } @@ -214,10 +223,15 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { } if (step->IsFirstStepInVolume()) { auto subdet_stop = NanoClock::now(); + auto newStepNum = step->GetTrack()->GetCurrentStepNumber(); + auto newSubDetNameIdx = getSubdetNameIdx(step->GetTrack()->GetTouchable()); m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += NanoClock::duration(subdet_stop - m_subdet_enter).count(); - auto subDetNameIdx = getSubdetNameIdx(step->GetTrack()->GetTouchable()); - m_currentSubdetIndex = subDetNameIdx; + m_trackStepsPerSubdet[m_trackNum][m_currentSubdetIndex] += + (newStepNum - m_currentStepNum); + m_trackTriggerCountPerSubdet[m_trackNum][m_currentSubdetIndex] += 1; + m_currentSubdetIndex = newSubDetNameIdx; + m_currentStepNum = newStepNum; m_subdet_enter = NanoClock::now(); m_step_overhead += (m_subdet_enter - subdet_stop); } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 241f2ea3..2ec9f870 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -68,6 +68,7 @@ private: NanoClock::time_point m_track_start; NanoClock::time_point m_subdet_enter; NanoClock::duration m_step_overhead{0}; + size_t m_currentStepNum = 0; NTuple::Item<size_t> m_trackNum; NTuple::Array<int> m_trackID; @@ -81,6 +82,8 @@ private: NTuple::Array<time_t> m_trackTimeOverhead; NTuple::Matrix<time_t> m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx + NTuple::Matrix<time_t> m_trackStepsPerSubdet; + NTuple::Matrix<time_t> m_trackTriggerCountPerSubdet; NTuple::Array<int> m_trackStepNum; NTuple::Array<int> m_trackPDGIds; NTuple::Array<size_t> m_trackStartSubdet; -- GitLab From f6060e64f6ed8a02b139acf460e13e4406650e25 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 29 May 2025 11:31:06 +0800 Subject: [PATCH 38/74] fix: name dup --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index f614de10..cccf59c7 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -119,7 +119,7 @@ StatusCode ChronoAnaElemTool::initNtuple() { MAX_SUBDET_NUM, m_trackStepsPerSubdet) .isSuccess(); suc &= m_ntuple - ->addIndexedItem("TrackStepsPerSubdet", m_trackNum, + ->addIndexedItem("TrackTriggerCountPerSubdet", m_trackNum, MAX_SUBDET_NUM, m_trackTriggerCountPerSubdet) .isSuccess(); } else { -- GitLab From 3ee9b1fc39e7db6d2e7ee88e1562a50a23f1fdc2 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 29 May 2025 14:06:16 +0800 Subject: [PATCH 39/74] fix: rm track and update subdet --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 177 +++--------------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 40 +--- 2 files changed, 35 insertions(+), 182 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index cccf59c7..a4b5015d 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -8,13 +8,11 @@ #include "ChronoAnaElemTool.h" -#include "CLHEP/Units/SystemOfUnits.h" #include "G4Event.hh" #include "G4Step.hh" #include "G4Track.hh" #include "GaudiAlg/GaudiAlgorithm.h" #include "GaudiKernel/ClassID.h" -#include "GaudiKernel/GaudiException.h" #include "GaudiKernel/MsgStream.h" #include "GaudiKernel/NTuple.h" #include "GaudiKernel/SmartIF.h" @@ -26,8 +24,7 @@ DECLARE_COMPONENT(ChronoAnaElemTool) StatusCode ChronoAnaElemTool::initSubdetNames() { const auto &children = m_geomSvc->getDD4HepGeo().children(); m_subdetNames.clear(); - m_subdetNames.reserve(children.size() + - SpecialCount); // add pWorld and Unknown subdet + m_subdetNames.reserve(MAX_SUBDET_NUM); // add pWorld and Unknown subdet // add pWorld m_subdetNames.emplace_back("Unknown"); @@ -45,11 +42,6 @@ StatusCode ChronoAnaElemTool::initSubdetNames() { error() << "[" << i << "] " << m_subdetNames[i] << endmsg; } - if (m_subdetNames.size() > MAX_SUBDET_NUM) { - throw GaudiException("m_subdetNames size exceeded MAX_SUBDET_NUM", - "ChronoAnaElemTool", StatusCode::FAILURE); - } - return StatusCode::SUCCESS; } @@ -69,58 +61,7 @@ StatusCode ChronoAnaElemTool::initNtuple() { suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX) .isSuccess(); suc &= m_ntuple->addItem("TotSimTime", m_eventTotSimTime).isSuccess(); - suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, MAX_TRACK_NUM) - .isSuccess(); - suc &= m_ntuple->addItem("TrackPx", m_trackNum, m_px); - suc &= m_ntuple->addItem("TrackPy", m_trackNum, m_py); - suc &= m_ntuple->addItem("TrackPz", m_trackNum, m_pz); - suc &= m_ntuple->addItem("TrackX", m_trackNum, m_x); - suc &= m_ntuple->addItem("TrackY", m_trackNum, m_y); - suc &= m_ntuple->addItem("TrackZ", m_trackNum, m_z); - suc &= - m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLengths) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTimes) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackTimeOverhead", m_trackNum, - m_trackTimeOverhead) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGIds) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackStartSubdet", m_trackNum, - m_trackStartSubdet) - .isSuccess(); - suc &= - m_ntuple - ->addIndexedItem("TrackEndSubdet", m_trackNum, m_trackEndSubdet) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackCharge", m_trackNum, m_trackCharge) - .isSuccess(); - suc &= - m_ntuple->addIndexedItem("TrackStepNum", m_trackNum, m_trackStepNum) - .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackID", m_trackNum, m_trackID) - .isSuccess(); - suc &= - m_ntuple->addIndexedItem("TrackParentID", m_trackNum, m_trackParentID) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackKineticEnergy", m_trackNum, - m_trackKineticEnergy) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackTimePerSubdet", m_trackNum, - MAX_SUBDET_NUM, m_trackTimePerSubdet) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackStepsPerSubdet", m_trackNum, - MAX_SUBDET_NUM, m_trackStepsPerSubdet) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackTriggerCountPerSubdet", m_trackNum, - MAX_SUBDET_NUM, m_trackTriggerCountPerSubdet) + suc &= m_ntuple->addItem("TimePerSubdet", MAX_SUBDET_NUM, m_timePerSubdet) .isSuccess(); } else { error() << "Cannot book N-tuple." << endmsg; @@ -150,51 +91,6 @@ StatusCode ChronoAnaElemTool::initialize() { return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } -void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { - if (m_eventNumber < m_skipFirstNEvents.value()) { - return; - } - if (m_trackNum >= MAX_TRACK_NUM) { - error() << "Exceeded MAX_TRACK_NUM at event " << m_eventNumber << endmsg; - throw GaudiException("Exceeded MAX_TRACK_NUM at event " + - std::to_string(m_eventNumber), - "ChronoAnaElemTool", StatusCode::FAILURE); - } - m_currentSubdetIndex = getSubdetNameIdx(track->GetTouchable()); - m_trackStartSubdet[m_trackNum] = m_currentSubdetIndex; - m_step_overhead = m_step_overhead.zero(); - m_trackID[m_trackNum] = track->GetTrackID(); - m_trackParentID[m_trackNum] = track->GetParentID(); - m_trackKineticEnergy[m_trackNum] = track->GetKineticEnergy() / CLHEP::GeV; - auto mom = track->GetMomentum(); - auto pos = track->GetPosition(); - m_px[m_trackNum] = mom.x() / CLHEP::GeV; - m_py[m_trackNum] = mom.y() / CLHEP::GeV; - m_pz[m_trackNum] = mom.z() / CLHEP::GeV; - m_x[m_trackNum] = pos.x() / CLHEP::mm; - m_y[m_trackNum] = pos.y() / CLHEP::mm; - m_z[m_trackNum] = pos.z() / CLHEP::mm; - m_currentStepNum = track->GetCurrentStepNumber(); - m_track_start = m_subdet_enter = NanoClock::now(); -} - -void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { - if (m_eventNumber < m_skipFirstNEvents.value()) { - return; - } - NanoClock::time_point track_stop = NanoClock::now(); - m_trackLengths[m_trackNum] = track->GetTrackLength() / CLHEP::mm; - m_trackTimes[m_trackNum] = - NanoClock::duration(track_stop - m_track_start).count(); - m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); - m_trackCharge[m_trackNum] = track->GetParticleDefinition()->GetPDGCharge(); - m_trackPDGIds[m_trackNum] = track->GetParticleDefinition()->GetPDGEncoding(); - m_trackEndSubdet[m_trackNum] = getSubdetNameIdx(track->GetTouchable()); - m_trackTimeOverhead[m_trackNum] = - NanoClock::duration(m_step_overhead).count(); - ++m_trackNum; -} - void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { if (m_eventNumber < m_skipFirstNEvents.value()) { return; @@ -214,7 +110,24 @@ void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { return; } - m_event_start = NanoClock::now(); + m_subdet_enter = m_event_start = NanoClock::now(); +} + +inline ChronoAnaElemTool::size_t +ChronoAnaElemTool::getSubdetNameIdx(const G4Step *step) { + const auto &pos = step->GetPreStepPoint()->GetPosition(); + const double r = pos.r(); + const double z = std::abs(pos.z()); + + if ((r >= 600 && r <= 1800) && (z <= 2900)) { + return TPC; + } else if ((r >= 1830 && r <= 2130) && (z <= 2900)) { + return ECAL_BARREL; + } else if ((r >= 350 && r <= 2130) && (2930 <= z && z <= 2930 + 300)) { + return ECAL_ENDCAP; + } else { + return Other; + } } void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { @@ -222,51 +135,15 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { return; } if (step->IsFirstStepInVolume()) { - auto subdet_stop = NanoClock::now(); - auto newStepNum = step->GetTrack()->GetCurrentStepNumber(); - auto newSubDetNameIdx = getSubdetNameIdx(step->GetTrack()->GetTouchable()); - m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += - NanoClock::duration(subdet_stop - m_subdet_enter).count(); - m_trackStepsPerSubdet[m_trackNum][m_currentSubdetIndex] += - (newStepNum - m_currentStepNum); - m_trackTriggerCountPerSubdet[m_trackNum][m_currentSubdetIndex] += 1; - m_currentSubdetIndex = newSubDetNameIdx; - m_currentStepNum = newStepNum; - m_subdet_enter = NanoClock::now(); - m_step_overhead += (m_subdet_enter - subdet_stop); - } -} - -inline ChronoAnaElemTool::size_t -ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touch) { - auto historyDepthNum = touch->GetHistoryDepth(); - for (int depth = 0; depth <= historyDepthNum; ++depth) { - auto vol = touch->GetVolume(depth); - if (!vol) { - error() << "Volume is nullptr at depth " << depth << endmsg; - continue; + auto newSubdet = getSubdetNameIdx(step); + if (newSubdet != m_currentSubdetIndex) { + auto stop = NanoClock::now(); + m_timePerSubdet[m_currentSubdetIndex] += + NanoClock::duration(stop - m_subdet_enter).count(); + m_subdet_enter = stop; + m_currentSubdetIndex = newSubdet; } - std::string_view volName{vol->GetName()}; - - // start from the PWorldIndex subdetector name, as the first one is always - // Unknown - for (size_t i = PWorldIndex; i < m_subdetNames.size(); ++i) { - if (volName.find(m_subdetNames[i]) != std::string::npos) { - // Found a or more match, return the index - // info() << "Found subdetector name: " << m_subdetNames[i] << " at - // depth " - // << depth << " with volName: " << volName << endmsg; - return i; - } - } - } - - error() << "No matching subdetector name found" << endmsg; - for (int depth = 0; depth <= historyDepthNum; ++depth) { - auto vol = touch->GetVolume(depth); - error() << "Volume at depth " << depth << ": " << vol->GetName() << endmsg; } - return UnknownIndex; } StatusCode ChronoAnaElemTool::finalize() { diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 2ec9f870..ce68ef83 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -28,10 +28,6 @@ public: virtual void BeginOfEventAction(const G4Event *) override; virtual void EndOfEventAction(const G4Event *) override; - // Tracking - virtual void PreUserTrackingAction(const G4Track *) override; - virtual void PostUserTrackingAction(const G4Track *) override; - // Stepping virtual void UserSteppingAction(const G4Step *) override; @@ -56,38 +52,18 @@ private: StatusCode initSubdetNames(); static constexpr size_t UnknownIndex = 0; static constexpr size_t PWorldIndex = 1; - static constexpr size_t SpecialCount = 2; - static constexpr size_t UninitializedIndex = UINT_MAX; + static constexpr size_t MAX_SUBDET_NUM = 30; std::vector<std::string> m_subdetNames; - inline size_t getSubdetNameIdx(const G4VTouchable *); - size_t m_currentSubdetIndex = UninitializedIndex; + inline size_t getSubdetNameIdx(const G4Step *step); + NTuple::Array<time_t> m_timePerSubdet; + static constexpr size_t Other = 27; + static constexpr size_t TPC = 25; + static constexpr size_t ECAL_BARREL = 13; + static constexpr size_t ECAL_ENDCAP = 14; + size_t m_currentSubdetIndex = Other; // simtime over Track - static constexpr size_t MAX_TRACK_NUM = 10'000'000; // 10M - static constexpr size_t MAX_SUBDET_NUM = 30; - NanoClock::time_point m_track_start; NanoClock::time_point m_subdet_enter; - NanoClock::duration m_step_overhead{0}; - size_t m_currentStepNum = 0; - - NTuple::Item<size_t> m_trackNum; - NTuple::Array<int> m_trackID; - NTuple::Array<int> m_trackParentID; - NTuple::Array<double> m_trackKineticEnergy; - NTuple::Array<double> m_px, m_py, m_pz; - NTuple::Array<double> m_x, m_y, m_z; - NTuple::Array<double> m_trackLengths; - NTuple::Array<double> m_trackCharge; - NTuple::Array<time_t> m_trackTimes; - NTuple::Array<time_t> m_trackTimeOverhead; - NTuple::Matrix<time_t> - m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx - NTuple::Matrix<time_t> m_trackStepsPerSubdet; - NTuple::Matrix<time_t> m_trackTriggerCountPerSubdet; - NTuple::Array<int> m_trackStepNum; - NTuple::Array<int> m_trackPDGIds; - NTuple::Array<size_t> m_trackStartSubdet; - NTuple::Array<size_t> m_trackEndSubdet; }; #endif -- GitLab From 6a5074259ce670c6a4908e60e5beda8891bad44f Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 29 May 2025 16:51:43 +0800 Subject: [PATCH 40/74] fix: use map to find subdet names --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 75 +++++++++++++++---- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 15 ++-- 2 files changed, 65 insertions(+), 25 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index a4b5015d..8709f3c3 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -11,6 +11,7 @@ #include "G4Event.hh" #include "G4Step.hh" #include "G4Track.hh" +#include "G4TransportationManager.hh" #include "GaudiAlg/GaudiAlgorithm.h" #include "GaudiKernel/ClassID.h" #include "GaudiKernel/MsgStream.h" @@ -21,10 +22,46 @@ DECLARE_COMPONENT(ChronoAnaElemTool) +StatusCode ChronoAnaElemTool::initSubdetVolumes() { + // Code to get all the volume Names + auto world_vol = G4TransportationManager::GetTransportationManager() + ->GetNavigatorForTracking() + ->GetWorldVolume(); + auto num_dau = world_vol->GetLogicalVolume()->GetNoDaughters(); + debug() << "World Physical Volume - Name: " << world_vol->GetName() + << " Pointer: " << world_vol << " World Logical Volume - Name: " + << world_vol->GetLogicalVolume()->GetName() + << " Pointer: " << world_vol->GetLogicalVolume() << endmsg; + m_logicalVolumePtrToSubdetIdx[world_vol->GetLogicalVolume()] = PWorldIndex; + debug() << "Set m_logicalVolumePtrToSubdetIdx[" + << world_vol->GetLogicalVolume() << "] to subdet index " + << PWorldIndex << endmsg; + for (size_t _dau = 0; _dau < num_dau; ++_dau) { + auto dau_vol = world_vol->GetLogicalVolume()->GetDaughter(_dau); + debug() << "Daughter Physical Volume - Name: " << dau_vol->GetName() + << " Pointer: " << dau_vol << " Daughter Logical Volume - Name: " + << dau_vol->GetLogicalVolume()->GetName() + << " Pointer: " << dau_vol->GetLogicalVolume() << endmsg; + auto dau_name = dau_vol->GetName(); + for (size_t _subdet = PWorldIndex; _subdet < m_subdetNames.size(); + ++_subdet) { + if (dau_name.find(m_subdetNames[_subdet]) != std::string::npos) { + m_logicalVolumePtrToSubdetIdx[dau_vol->GetLogicalVolume()] = _subdet; + debug() << "Set m_logicalVolumePtrToSubdetIdx[" + << dau_vol->GetLogicalVolume() << "] to subdet index " + << _subdet << endmsg; + continue; + } + } + } + return StatusCode::SUCCESS; +} + StatusCode ChronoAnaElemTool::initSubdetNames() { const auto &children = m_geomSvc->getDD4HepGeo().children(); m_subdetNames.clear(); - m_subdetNames.reserve(MAX_SUBDET_NUM); // add pWorld and Unknown subdet + m_subdetNames.reserve(m_subdetNames.size() + + 2); // add pWorld and Unknown subdet // add pWorld m_subdetNames.emplace_back("Unknown"); @@ -61,8 +98,10 @@ StatusCode ChronoAnaElemTool::initNtuple() { suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX) .isSuccess(); suc &= m_ntuple->addItem("TotSimTime", m_eventTotSimTime).isSuccess(); - suc &= m_ntuple->addItem("TimePerSubdet", MAX_SUBDET_NUM, m_timePerSubdet) - .isSuccess(); + suc &= + m_ntuple + ->addItem("TimePerSubdet", m_subdetNames.size(), m_timePerSubdet) + .isSuccess(); } else { error() << "Cannot book N-tuple." << endmsg; return StatusCode::FAILURE; @@ -87,6 +126,7 @@ StatusCode ChronoAnaElemTool::initialize() { // init subdet names and number suc &= initSubdetNames().isSuccess(); + suc &= initSubdetVolumes().isSuccess(); suc &= initNtuple().isSuccess(); return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } @@ -114,19 +154,22 @@ void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { } inline ChronoAnaElemTool::size_t -ChronoAnaElemTool::getSubdetNameIdx(const G4Step *step) { - const auto &pos = step->GetPreStepPoint()->GetPosition(); - const double r = pos.r(); - const double z = std::abs(pos.z()); - - if ((r >= 600 && r <= 1800) && (z <= 2900)) { - return TPC; - } else if ((r >= 1830 && r <= 2130) && (z <= 2900)) { - return ECAL_BARREL; - } else if ((r >= 350 && r <= 2130) && (2930 <= z && z <= 2930 + 300)) { - return ECAL_ENDCAP; +ChronoAnaElemTool::getSubdetNameIdx(const G4Track *track) { + auto historyDepthNum = track->GetTouchable()->GetHistoryDepth(); + if (historyDepthNum == 0) { + return PWorldIndex; } else { - return Other; + auto lastVolume = track->GetTouchable() + ->GetVolume(historyDepthNum - 1) + ->GetLogicalVolume(); + auto it = m_logicalVolumePtrToSubdetIdx.find(lastVolume); + if (it != m_logicalVolumePtrToSubdetIdx.end()) { + return it->second; + } else { + // error() << "Error find " << lastVolume->GetName() + // << " ptr: " << lastVolume << endmsg; + return UnknownIndex; + } } } @@ -135,7 +178,7 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { return; } if (step->IsFirstStepInVolume()) { - auto newSubdet = getSubdetNameIdx(step); + auto newSubdet = getSubdetNameIdx(step->GetTrack()); if (newSubdet != m_currentSubdetIndex) { auto stop = NanoClock::now(); m_timePerSubdet[m_currentSubdetIndex] += diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index ce68ef83..4a39d88b 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -5,6 +5,7 @@ #include <chrono> #include <climits> #include <string> +#include <unordered_map> #include <vector> #include "DetInterface/IGeomSvc.h" @@ -50,20 +51,16 @@ private: // simtime over subdet StatusCode initSubdetNames(); + StatusCode initSubdetVolumes(); static constexpr size_t UnknownIndex = 0; static constexpr size_t PWorldIndex = 1; - static constexpr size_t MAX_SUBDET_NUM = 30; std::vector<std::string> m_subdetNames; - inline size_t getSubdetNameIdx(const G4Step *step); - NTuple::Array<time_t> m_timePerSubdet; - static constexpr size_t Other = 27; - static constexpr size_t TPC = 25; - static constexpr size_t ECAL_BARREL = 13; - static constexpr size_t ECAL_ENDCAP = 14; - size_t m_currentSubdetIndex = Other; + std::unordered_map<G4LogicalVolume *, size_t> m_logicalVolumePtrToSubdetIdx; - // simtime over Track + inline size_t getSubdetNameIdx(const G4Track *track); + size_t m_currentSubdetIndex = UnknownIndex; NanoClock::time_point m_subdet_enter; + NTuple::Array<time_t> m_timePerSubdet; }; #endif -- GitLab From 1c91dd39fa395877119935e2a37d89cefa09793e Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 29 May 2025 17:01:58 +0800 Subject: [PATCH 41/74] fix: restrict useage of unknown --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 4 ++-- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 8709f3c3..b1eaa5b3 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -166,8 +166,8 @@ ChronoAnaElemTool::getSubdetNameIdx(const G4Track *track) { if (it != m_logicalVolumePtrToSubdetIdx.end()) { return it->second; } else { - // error() << "Error find " << lastVolume->GetName() - // << " ptr: " << lastVolume << endmsg; + error() << "Error find " << lastVolume->GetName() + << " ptr: " << lastVolume << endmsg; return UnknownIndex; } } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 4a39d88b..498f2c2f 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -58,7 +58,7 @@ private: std::unordered_map<G4LogicalVolume *, size_t> m_logicalVolumePtrToSubdetIdx; inline size_t getSubdetNameIdx(const G4Track *track); - size_t m_currentSubdetIndex = UnknownIndex; + size_t m_currentSubdetIndex = PWorldIndex; NanoClock::time_point m_subdet_enter; NTuple::Array<time_t> m_timePerSubdet; }; -- GitLab From a356f7bcee2c955dee630260d8ad272f977b0de0 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 29 May 2025 19:55:25 +0800 Subject: [PATCH 42/74] fix: add track info --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 103 +++++++++++++++++- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 32 ++++++ 2 files changed, 130 insertions(+), 5 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index b1eaa5b3..f755e141 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -8,6 +8,7 @@ #include "ChronoAnaElemTool.h" +#include "CLHEP/Units/SystemOfUnits.h" #include "G4Event.hh" #include "G4Step.hh" #include "G4Track.hh" @@ -102,6 +103,58 @@ StatusCode ChronoAnaElemTool::initNtuple() { m_ntuple ->addItem("TimePerSubdet", m_subdetNames.size(), m_timePerSubdet) .isSuccess(); + suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, MAX_TRACK_NUM) + .isSuccess(); + suc &= m_ntuple->addItem("TrackPx", m_trackNum, m_trackPx); + suc &= m_ntuple->addItem("TrackPy", m_trackNum, m_trackPy); + suc &= m_ntuple->addItem("TrackPz", m_trackNum, m_trackPz); + suc &= m_ntuple->addItem("TrackX", m_trackNum, m_trackX); + suc &= m_ntuple->addItem("TrackY", m_trackNum, m_trackY); + suc &= m_ntuple->addItem("TrackZ", m_trackNum, m_trackZ); + suc &= m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLength) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTime) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackTimeOverhead", m_trackNum, + m_trackTimeOverhead) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGId) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackStartSubdet", m_trackNum, + m_trackStartSubdet) + .isSuccess(); + suc &= + m_ntuple + ->addIndexedItem("TrackEndSubdet", m_trackNum, m_trackEndSubdet) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackCharge", m_trackNum, m_trackCharge) + .isSuccess(); + suc &= + m_ntuple->addIndexedItem("TrackStepNum", m_trackNum, m_trackStepNum) + .isSuccess(); + suc &= m_ntuple->addIndexedItem("TrackID", m_trackNum, m_trackID) + .isSuccess(); + suc &= + m_ntuple->addIndexedItem("TrackParentID", m_trackNum, m_trackParentID) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackKineticEnergy", m_trackNum, + m_trackKineticEnergy) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackTimePerSubdet", m_trackNum, + MAX_SUBDET_NUM, m_trackTimePerSubdet) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackStepsPerSubdet", m_trackNum, + MAX_SUBDET_NUM, m_trackStepsPerSubdet) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackTriggerCountPerSubdet", m_trackNum, + MAX_SUBDET_NUM, m_trackTriggerCountPerSubdet) + .isSuccess(); } else { error() << "Cannot book N-tuple." << endmsg; return StatusCode::FAILURE; @@ -150,7 +203,39 @@ void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { return; } - m_subdet_enter = m_event_start = NanoClock::now(); + m_event_start = NanoClock::now(); +} + +void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { + + m_trackID[m_trackNum] = track->GetTrackID(); + m_trackParentID[m_trackNum] = track->GetParentID(); + m_trackKineticEnergy[m_trackNum] = track->GetKineticEnergy() / CLHEP::GeV; + auto mom = track->GetMomentum(); + auto pos = track->GetPosition(); + m_trackPx[m_trackNum] = mom.x() / CLHEP::GeV; + m_trackPy[m_trackNum] = mom.y() / CLHEP::GeV; + m_trackPz[m_trackNum] = mom.z() / CLHEP::GeV; + m_trackX[m_trackNum] = pos.x() / CLHEP::mm; + m_trackY[m_trackNum] = pos.y() / CLHEP::mm; + m_trackZ[m_trackNum] = pos.z() / CLHEP::mm; + m_trackCharge[m_trackNum] = track->GetParticleDefinition()->GetPDGCharge(); + m_trackPDGId[m_trackNum] = + track->GetParticleDefinition()->GetParticleDefinitionID(); + m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track); + m_current_step_num = track->GetCurrentStepNumber(); + m_track_overhead = m_track_overhead.zero(); + m_subdet_enter = m_track_start = NanoClock::now(); +} + +void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { + auto stop = NanoClock::now(); + m_trackTime[m_trackNum] = NanoClock::duration(stop - m_track_start).count(); + m_trackLength[m_trackNum] = track->GetTrackLength(); + m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); + m_trackEndSubdet[m_trackNum] = getSubdetNameIdx(track); + m_trackTimeOverhead[m_trackNum] = m_track_overhead.count(); + ++m_trackNum; } inline ChronoAnaElemTool::size_t @@ -178,13 +263,21 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { return; } if (step->IsFirstStepInVolume()) { - auto newSubdet = getSubdetNameIdx(step->GetTrack()); + auto track = step->GetTrack(); + auto newSubdet = getSubdetNameIdx(track); if (newSubdet != m_currentSubdetIndex) { auto stop = NanoClock::now(); - m_timePerSubdet[m_currentSubdetIndex] += - NanoClock::duration(stop - m_subdet_enter).count(); - m_subdet_enter = stop; + auto duration = NanoClock::duration(stop - m_subdet_enter).count(); + auto newStepNum = track->GetCurrentStepNumber(); + m_timePerSubdet[m_currentSubdetIndex] += duration; + m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += duration; + m_trackStepsPerSubdet[m_trackNum][m_currentSubdetIndex] += + newStepNum - m_current_step_num; + m_trackTriggerCountPerSubdet[m_trackNum][m_currentSubdetIndex] += 1; m_currentSubdetIndex = newSubdet; + m_current_step_num = newStepNum; + m_subdet_enter = NanoClock::now(); + m_track_overhead += (m_subdet_enter - stop); } } } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 498f2c2f..c2edc016 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -29,6 +29,10 @@ public: virtual void BeginOfEventAction(const G4Event *) override; virtual void EndOfEventAction(const G4Event *) override; + // Tracking + virtual void PreUserTrackingAction(const G4Track *) override; + virtual void PostUserTrackingAction(const G4Track *) override; + // Stepping virtual void UserSteppingAction(const G4Step *) override; @@ -61,6 +65,34 @@ private: size_t m_currentSubdetIndex = PWorldIndex; NanoClock::time_point m_subdet_enter; NTuple::Array<time_t> m_timePerSubdet; + + // simtime over track + static constexpr size_t MAX_TRACK_NUM = 10'000'000; // 10M + static constexpr size_t MAX_SUBDET_NUM = 30; + NanoClock::time_point m_track_start; + time_t m_current_step_num; + NanoClock::duration m_track_overhead{0}; + + NTuple::Item<size_t> m_trackNum; + NTuple::Array<int> m_trackID; + NTuple::Array<int> m_trackParentID; + NTuple::Array<double> m_trackKineticEnergy; + NTuple::Array<double> m_trackPx, m_trackPy, m_trackPz; + NTuple::Array<double> m_trackX, m_trackY, m_trackZ; + NTuple::Array<double> m_trackLength; + NTuple::Array<double> m_trackCharge; + NTuple::Array<int> m_trackPDGId; + NTuple::Array<int> m_trackStepNum; + NTuple::Array<time_t> m_trackTime; + NTuple::Array<time_t> m_trackTimeOverhead; + NTuple::Array<size_t> m_trackStartSubdet; + NTuple::Array<size_t> m_trackEndSubdet; + + NTuple::Matrix<time_t> + m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx + NTuple::Matrix<time_t> m_trackStepsPerSubdet; + NTuple::Matrix<time_t> m_trackTriggerCountPerSubdet; + }; #endif -- GitLab From 24e57c4af46d8b1cf5f672748adecc9f004e2408 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 29 May 2025 20:07:25 +0800 Subject: [PATCH 43/74] fix: track time remove overhead --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index f755e141..73a09c8d 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -230,7 +230,8 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { auto stop = NanoClock::now(); - m_trackTime[m_trackNum] = NanoClock::duration(stop - m_track_start).count(); + m_trackTime[m_trackNum] = + NanoClock::duration(stop - m_track_start - m_track_overhead).count(); m_trackLength[m_trackNum] = track->GetTrackLength(); m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); m_trackEndSubdet[m_trackNum] = getSubdetNameIdx(track); -- GitLab From 0137e66fb9aecf930939c8822c95b4a1c072ddcb Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 29 May 2025 20:49:17 +0800 Subject: [PATCH 44/74] fix: track may stay in same subdet --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 40 +++++++++---------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 4 +- 2 files changed, 19 insertions(+), 25 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 73a09c8d..0358cee0 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -147,14 +147,6 @@ StatusCode ChronoAnaElemTool::initNtuple() { ->addIndexedItem("TrackTimePerSubdet", m_trackNum, MAX_SUBDET_NUM, m_trackTimePerSubdet) .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackStepsPerSubdet", m_trackNum, - MAX_SUBDET_NUM, m_trackStepsPerSubdet) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackTriggerCountPerSubdet", m_trackNum, - MAX_SUBDET_NUM, m_trackTriggerCountPerSubdet) - .isSuccess(); } else { error() << "Cannot book N-tuple." << endmsg; return StatusCode::FAILURE; @@ -203,7 +195,7 @@ void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { return; } - m_event_start = NanoClock::now(); + m_subdet_enter = m_event_start = NanoClock::now(); } void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { @@ -223,19 +215,26 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_trackPDGId[m_trackNum] = track->GetParticleDefinition()->GetParticleDefinitionID(); m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track); - m_current_step_num = track->GetCurrentStepNumber(); m_track_overhead = m_track_overhead.zero(); - m_subdet_enter = m_track_start = NanoClock::now(); + m_subdet_track_enter = m_track_start = NanoClock::now(); } void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { auto stop = NanoClock::now(); m_trackTime[m_trackNum] = NanoClock::duration(stop - m_track_start - m_track_overhead).count(); + auto track_end_subdet = getSubdetNameIdx(track); m_trackLength[m_trackNum] = track->GetTrackLength(); m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); - m_trackEndSubdet[m_trackNum] = getSubdetNameIdx(track); + m_trackEndSubdet[m_trackNum] = track_end_subdet; m_trackTimeOverhead[m_trackNum] = m_track_overhead.count(); + // track did not change subdet, add time + m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += + NanoClock::duration(stop - m_subdet_track_enter).count(); + if (m_currentSubdetIndex != track_end_subdet) { + error() << "Current Subdet " << m_currentSubdetIndex + << " not equal with track end subdet" << track_end_subdet << endmsg; + } ++m_trackNum; } @@ -268,17 +267,14 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { auto newSubdet = getSubdetNameIdx(track); if (newSubdet != m_currentSubdetIndex) { auto stop = NanoClock::now(); - auto duration = NanoClock::duration(stop - m_subdet_enter).count(); - auto newStepNum = track->GetCurrentStepNumber(); - m_timePerSubdet[m_currentSubdetIndex] += duration; - m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += duration; - m_trackStepsPerSubdet[m_trackNum][m_currentSubdetIndex] += - newStepNum - m_current_step_num; - m_trackTriggerCountPerSubdet[m_trackNum][m_currentSubdetIndex] += 1; + auto event_duration = NanoClock::duration(stop - m_subdet_enter).count(); + auto track_duration = + NanoClock::duration(stop - m_subdet_track_enter).count(); + m_timePerSubdet[m_currentSubdetIndex] += event_duration; + m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += track_duration; m_currentSubdetIndex = newSubdet; - m_current_step_num = newStepNum; - m_subdet_enter = NanoClock::now(); - m_track_overhead += (m_subdet_enter - stop); + m_subdet_track_enter = m_subdet_enter = NanoClock::now(); + m_track_overhead += (m_subdet_track_enter - stop); } } } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index c2edc016..fd1cf30e 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -70,8 +70,8 @@ private: static constexpr size_t MAX_TRACK_NUM = 10'000'000; // 10M static constexpr size_t MAX_SUBDET_NUM = 30; NanoClock::time_point m_track_start; - time_t m_current_step_num; NanoClock::duration m_track_overhead{0}; + NanoClock::time_point m_subdet_track_enter; NTuple::Item<size_t> m_trackNum; NTuple::Array<int> m_trackID; @@ -90,8 +90,6 @@ private: NTuple::Matrix<time_t> m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx - NTuple::Matrix<time_t> m_trackStepsPerSubdet; - NTuple::Matrix<time_t> m_trackTriggerCountPerSubdet; }; -- GitLab From 020fbd8518fc63a2b70aa37daf80dfa9daa789b6 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 29 May 2025 21:03:54 +0800 Subject: [PATCH 45/74] fix: skip first n events --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 0358cee0..c66c3f9d 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -190,7 +190,7 @@ void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { m_ntuple->reset(); m_eventNumber = static_cast<size_t>(event->GetEventID()); - always() << "ChronoAnaElemTool: Event number: " << m_eventNumber << endmsg; + always() << " ChronoAnaElemTool: Event number: " << m_eventNumber << endmsg; if (m_eventNumber < m_skipFirstNEvents.value()) { return; } @@ -199,7 +199,9 @@ void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { } void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { - + if (m_eventNumber < m_skipFirstNEvents.value()) { + return; + } m_trackID[m_trackNum] = track->GetTrackID(); m_trackParentID[m_trackNum] = track->GetParentID(); m_trackKineticEnergy[m_trackNum] = track->GetKineticEnergy() / CLHEP::GeV; @@ -216,10 +218,14 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { track->GetParticleDefinition()->GetParticleDefinitionID(); m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track); m_track_overhead = m_track_overhead.zero(); + // always() << "track start in " << m_trackStartSubdet[m_trackNum] << endmsg; m_subdet_track_enter = m_track_start = NanoClock::now(); } void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { + if (m_eventNumber < m_skipFirstNEvents.value()) { + return; + } auto stop = NanoClock::now(); m_trackTime[m_trackNum] = NanoClock::duration(stop - m_track_start - m_track_overhead).count(); @@ -233,8 +239,10 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { NanoClock::duration(stop - m_subdet_track_enter).count(); if (m_currentSubdetIndex != track_end_subdet) { error() << "Current Subdet " << m_currentSubdetIndex - << " not equal with track end subdet" << track_end_subdet << endmsg; + << " not equal with track end subdet " << track_end_subdet + << endmsg; } + // always() << "track end in " << track_end_subdet << endmsg; ++m_trackNum; } @@ -272,6 +280,8 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { NanoClock::duration(stop - m_subdet_track_enter).count(); m_timePerSubdet[m_currentSubdetIndex] += event_duration; m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += track_duration; + // always() << "track " << track->GetTrackID() << " entering " << newSubdet + // << " from " << m_currentSubdetIndex << endmsg; m_currentSubdetIndex = newSubdet; m_subdet_track_enter = m_subdet_enter = NanoClock::now(); m_track_overhead += (m_subdet_track_enter - stop); -- GitLab From 21feef49ee1512ba8b1166c6b49822564c3d28cd Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Fri, 30 May 2025 08:43:28 +0800 Subject: [PATCH 46/74] fix: add event end subdet --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index c66c3f9d..7d7a2fa6 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -181,6 +181,8 @@ void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { return; } NanoClock::time_point event_stop = NanoClock::now(); + m_timePerSubdet[m_currentSubdetIndex] += + NanoClock::duration(event_stop - m_subdet_enter).count(); m_eventTotSimTime = NanoClock::duration(event_stop - m_event_start).count(); if (m_ntuple->write().isFailure()) { error() << "Error write track tuple at event " << m_eventNumber << endmsg; @@ -280,7 +282,8 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { NanoClock::duration(stop - m_subdet_track_enter).count(); m_timePerSubdet[m_currentSubdetIndex] += event_duration; m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += track_duration; - // always() << "track " << track->GetTrackID() << " entering " << newSubdet + // always() << "track " << track->GetTrackID() << " entering " << + // newSubdet // << " from " << m_currentSubdetIndex << endmsg; m_currentSubdetIndex = newSubdet; m_subdet_track_enter = m_subdet_enter = NanoClock::now(); -- GitLab From 5b3c684bd72533d4344ca265fb7505ffce6586ca Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Fri, 30 May 2025 09:37:32 +0800 Subject: [PATCH 47/74] fix: change include sequence --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 3 +-- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 7d7a2fa6..c1f5e7e4 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -6,8 +6,6 @@ #include <cstdlib> #include <string> -#include "ChronoAnaElemTool.h" - #include "CLHEP/Units/SystemOfUnits.h" #include "G4Event.hh" #include "G4Step.hh" @@ -19,6 +17,7 @@ #include "GaudiKernel/NTuple.h" #include "GaudiKernel/SmartIF.h" +#include "ChronoAnaElemTool.h" #include "DetInterface/IGeomSvc.h" DECLARE_COMPONENT(ChronoAnaElemTool) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index fd1cf30e..1efecba0 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -1,7 +1,6 @@ #ifndef ChronoAnaElemTool_h #define ChronoAnaElemTool_h -#include <G4VTouchable.hh> #include <chrono> #include <climits> #include <string> @@ -11,6 +10,7 @@ #include "DetInterface/IGeomSvc.h" #include "DetSimInterface/IAnaElemTool.h" +#include "G4LogicalVolume.hh" #include "GaudiKernel/AlgTool.h" #include "GaudiKernel/INTupleSvc.h" #include "GaudiKernel/NTuple.h" @@ -90,7 +90,6 @@ private: NTuple::Matrix<time_t> m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx - }; #endif -- GitLab From 90bc2f30dfc7b2a88a70985cdb84a819c1dd5d64 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Sat, 31 May 2025 20:48:28 +0800 Subject: [PATCH 48/74] fix: remove overhead --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 10 +--------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 4 +--- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index c1f5e7e4..3299c457 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -114,10 +114,6 @@ StatusCode ChronoAnaElemTool::initNtuple() { .isSuccess(); suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTime) .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackTimeOverhead", m_trackNum, - m_trackTimeOverhead) - .isSuccess(); suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGId) .isSuccess(); suc &= m_ntuple @@ -218,7 +214,6 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_trackPDGId[m_trackNum] = track->GetParticleDefinition()->GetParticleDefinitionID(); m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track); - m_track_overhead = m_track_overhead.zero(); // always() << "track start in " << m_trackStartSubdet[m_trackNum] << endmsg; m_subdet_track_enter = m_track_start = NanoClock::now(); } @@ -228,13 +223,11 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { return; } auto stop = NanoClock::now(); - m_trackTime[m_trackNum] = - NanoClock::duration(stop - m_track_start - m_track_overhead).count(); + m_trackTime[m_trackNum] = NanoClock::duration(stop - m_track_start).count(); auto track_end_subdet = getSubdetNameIdx(track); m_trackLength[m_trackNum] = track->GetTrackLength(); m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); m_trackEndSubdet[m_trackNum] = track_end_subdet; - m_trackTimeOverhead[m_trackNum] = m_track_overhead.count(); // track did not change subdet, add time m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += NanoClock::duration(stop - m_subdet_track_enter).count(); @@ -286,7 +279,6 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { // << " from " << m_currentSubdetIndex << endmsg; m_currentSubdetIndex = newSubdet; m_subdet_track_enter = m_subdet_enter = NanoClock::now(); - m_track_overhead += (m_subdet_track_enter - stop); } } } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 1efecba0..1be07656 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -11,11 +11,11 @@ #include "DetSimInterface/IAnaElemTool.h" #include "G4LogicalVolume.hh" +#include "Gaudi/Timers/RdtscClock.h" #include "GaudiKernel/AlgTool.h" #include "GaudiKernel/INTupleSvc.h" #include "GaudiKernel/NTuple.h" #include "GaudiKernel/SmartIF.h" -#include <Gaudi/Timers/RdtscClock.h> class ChronoAnaElemTool : public extends<AlgTool, IAnaElemTool> { @@ -70,7 +70,6 @@ private: static constexpr size_t MAX_TRACK_NUM = 10'000'000; // 10M static constexpr size_t MAX_SUBDET_NUM = 30; NanoClock::time_point m_track_start; - NanoClock::duration m_track_overhead{0}; NanoClock::time_point m_subdet_track_enter; NTuple::Item<size_t> m_trackNum; @@ -84,7 +83,6 @@ private: NTuple::Array<int> m_trackPDGId; NTuple::Array<int> m_trackStepNum; NTuple::Array<time_t> m_trackTime; - NTuple::Array<time_t> m_trackTimeOverhead; NTuple::Array<size_t> m_trackStartSubdet; NTuple::Array<size_t> m_trackEndSubdet; -- GitLab From 87f990c079b637026865ecb5cd7e46abf95b6feb Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 2 Jun 2025 09:54:52 +0800 Subject: [PATCH 49/74] fix: reset start subdet to unknown --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 14 +++++++++----- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 3299c457..4b4e01be 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -192,6 +192,7 @@ void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { return; } + m_currentSubdetIndex = UnknownIndex; m_subdet_enter = m_event_start = NanoClock::now(); } @@ -214,7 +215,8 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_trackPDGId[m_trackNum] = track->GetParticleDefinition()->GetParticleDefinitionID(); m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track); - // always() << "track start in " << m_trackStartSubdet[m_trackNum] << endmsg; + // always() << "track " << m_trackID[m_trackNum] << " start in " + // << m_trackStartSubdet[m_trackNum] << endmsg; m_subdet_track_enter = m_track_start = NanoClock::now(); } @@ -236,7 +238,8 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { << " not equal with track end subdet " << track_end_subdet << endmsg; } - // always() << "track end in " << track_end_subdet << endmsg; + // always() << "track " << m_trackID[m_trackNum] << " end in " + // << track_end_subdet << endmsg; ++m_trackNum; } @@ -274,9 +277,10 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { NanoClock::duration(stop - m_subdet_track_enter).count(); m_timePerSubdet[m_currentSubdetIndex] += event_duration; m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += track_duration; - // always() << "track " << track->GetTrackID() << " entering " << - // newSubdet - // << " from " << m_currentSubdetIndex << endmsg; + // always() << "track " << track->GetTrackID() << " from " + // << m_currentSubdetIndex << " entering " << newSubdet + // << " event time " << event_duration << " track time " + // << track_duration << endmsg; m_currentSubdetIndex = newSubdet; m_subdet_track_enter = m_subdet_enter = NanoClock::now(); } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 1be07656..4893f5ca 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -62,7 +62,7 @@ private: std::unordered_map<G4LogicalVolume *, size_t> m_logicalVolumePtrToSubdetIdx; inline size_t getSubdetNameIdx(const G4Track *track); - size_t m_currentSubdetIndex = PWorldIndex; + size_t m_currentSubdetIndex = UnknownIndex; NanoClock::time_point m_subdet_enter; NTuple::Array<time_t> m_timePerSubdet; -- GitLab From 4144c49cdcee58c30ce50f7461f7cc8ba70fde49 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 3 Jun 2025 09:17:34 +0800 Subject: [PATCH 50/74] fix: process current subdet change in pre track --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 4b4e01be..96441910 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -214,7 +214,14 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_trackCharge[m_trackNum] = track->GetParticleDefinition()->GetPDGCharge(); m_trackPDGId[m_trackNum] = track->GetParticleDefinition()->GetParticleDefinitionID(); - m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track); + auto newSubdet = m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track); + if (newSubdet != m_currentSubdetIndex) { + auto stop = NanoClock::now(); + auto event_duration = NanoClock::duration(stop - m_subdet_enter).count(); + m_timePerSubdet[m_currentSubdetIndex] += event_duration; + m_currentSubdetIndex = newSubdet; + m_subdet_enter = NanoClock::now(); + } // always() << "track " << m_trackID[m_trackNum] << " start in " // << m_trackStartSubdet[m_trackNum] << endmsg; m_subdet_track_enter = m_track_start = NanoClock::now(); -- GitLab From 3730e3a9428211d3ecb8f14d43fc6687a9af922e Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 3 Jun 2025 16:13:38 +0800 Subject: [PATCH 51/74] fix: change Simulation Granularity --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 45 +++++++++++++++---- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 5 +++ 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 96441910..38b8b4ff 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -6,9 +6,11 @@ #include <cstdlib> #include <string> -#include "CLHEP/Units/SystemOfUnits.h" +#include "G4ChordFinder.hh" #include "G4Event.hh" +#include "G4FieldManager.hh" #include "G4Step.hh" +#include "G4SystemOfUnits.hh" #include "G4Track.hh" #include "G4TransportationManager.hh" #include "GaudiAlg/GaudiAlgorithm.h" @@ -161,6 +163,9 @@ StatusCode ChronoAnaElemTool::initialize() { return StatusCode::FAILURE; } + m_fieldManager = + G4TransportationManager::GetTransportationManager()->GetFieldManager(); + // calibrate the clock before starting the simulation NanoClock::calibrate(); @@ -202,15 +207,15 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { } m_trackID[m_trackNum] = track->GetTrackID(); m_trackParentID[m_trackNum] = track->GetParentID(); - m_trackKineticEnergy[m_trackNum] = track->GetKineticEnergy() / CLHEP::GeV; + m_trackKineticEnergy[m_trackNum] = track->GetKineticEnergy() / GeV; auto mom = track->GetMomentum(); auto pos = track->GetPosition(); - m_trackPx[m_trackNum] = mom.x() / CLHEP::GeV; - m_trackPy[m_trackNum] = mom.y() / CLHEP::GeV; - m_trackPz[m_trackNum] = mom.z() / CLHEP::GeV; - m_trackX[m_trackNum] = pos.x() / CLHEP::mm; - m_trackY[m_trackNum] = pos.y() / CLHEP::mm; - m_trackZ[m_trackNum] = pos.z() / CLHEP::mm; + m_trackPx[m_trackNum] = mom.x() / GeV; + m_trackPy[m_trackNum] = mom.y() / GeV; + m_trackPz[m_trackNum] = mom.z() / GeV; + m_trackX[m_trackNum] = pos.x() / mm; + m_trackY[m_trackNum] = pos.y() / mm; + m_trackZ[m_trackNum] = pos.z() / mm; m_trackCharge[m_trackNum] = track->GetParticleDefinition()->GetPDGCharge(); m_trackPDGId[m_trackNum] = track->GetParticleDefinition()->GetParticleDefinitionID(); @@ -219,6 +224,7 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { auto stop = NanoClock::now(); auto event_duration = NanoClock::duration(stop - m_subdet_enter).count(); m_timePerSubdet[m_currentSubdetIndex] += event_duration; + // switchSimulationGranularity(newSubdet, m_currentSubdetIndex); m_currentSubdetIndex = newSubdet; m_subdet_enter = NanoClock::now(); } @@ -288,12 +294,35 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { // << m_currentSubdetIndex << " entering " << newSubdet // << " event time " << event_duration << " track time " // << track_duration << endmsg; + // switchSimulationGranularity(newSubdet, m_currentSubdetIndex); m_currentSubdetIndex = newSubdet; m_subdet_track_enter = m_subdet_enter = NanoClock::now(); } } } +inline void ChronoAnaElemTool::switchSimulationGranularity( + const ChronoAnaElemTool::size_t newsubdet, + const ChronoAnaElemTool::size_t currentSubdet) { + if (newsubdet != currentSubdet) { + if (currentSubdet == TPCIndex) { + // leaving TPC, turn high + m_fieldManager->SetDeltaIntersection(1.0e-5 * mm); + m_fieldManager->SetDeltaOneStep(1.0e-4 * mm); + m_fieldManager->SetMinimumEpsilonStep(5.0e-5 * mm); + m_fieldManager->SetMaximumEpsilonStep(1.0e-3 * mm); + m_fieldManager->GetChordFinder()->SetDeltaChord(0.25 * mm); + } else if (newsubdet == TPCIndex) { + // entering TPC, turn low + m_fieldManager->SetDeltaIntersection(0.001 * mm); + m_fieldManager->SetDeltaOneStep(0.01 * mm); + m_fieldManager->SetMinimumEpsilonStep(5.0e-5 * mm); + m_fieldManager->SetMaximumEpsilonStep(1.0e-3 * mm); + m_fieldManager->GetChordFinder()->SetDeltaChord(25 * mm); + } + } +} + StatusCode ChronoAnaElemTool::finalize() { m_ntuple->reset(); diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 4893f5ca..b889c32d 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -58,6 +58,7 @@ private: StatusCode initSubdetVolumes(); static constexpr size_t UnknownIndex = 0; static constexpr size_t PWorldIndex = 1; + static constexpr size_t TPCIndex = 25; std::vector<std::string> m_subdetNames; std::unordered_map<G4LogicalVolume *, size_t> m_logicalVolumePtrToSubdetIdx; @@ -88,6 +89,10 @@ private: NTuple::Matrix<time_t> m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx + + inline void switchSimulationGranularity(const size_t newsubdet, + const size_t currentSubdet); + G4FieldManager *m_fieldManager; }; #endif -- GitLab From 6b2cd43e8225c71ac07911fd55fac4b3b0867aa3 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Wed, 4 Jun 2025 15:58:44 +0800 Subject: [PATCH 52/74] fix: remove field manager --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 46 +++++++++---------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 6 +-- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 38b8b4ff..e095aa15 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -163,8 +163,8 @@ StatusCode ChronoAnaElemTool::initialize() { return StatusCode::FAILURE; } - m_fieldManager = - G4TransportationManager::GetTransportationManager()->GetFieldManager(); + // m_fieldManager = + // G4TransportationManager::GetTransportationManager()->GetFieldManager(); // calibrate the clock before starting the simulation NanoClock::calibrate(); @@ -301,27 +301,27 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { } } -inline void ChronoAnaElemTool::switchSimulationGranularity( - const ChronoAnaElemTool::size_t newsubdet, - const ChronoAnaElemTool::size_t currentSubdet) { - if (newsubdet != currentSubdet) { - if (currentSubdet == TPCIndex) { - // leaving TPC, turn high - m_fieldManager->SetDeltaIntersection(1.0e-5 * mm); - m_fieldManager->SetDeltaOneStep(1.0e-4 * mm); - m_fieldManager->SetMinimumEpsilonStep(5.0e-5 * mm); - m_fieldManager->SetMaximumEpsilonStep(1.0e-3 * mm); - m_fieldManager->GetChordFinder()->SetDeltaChord(0.25 * mm); - } else if (newsubdet == TPCIndex) { - // entering TPC, turn low - m_fieldManager->SetDeltaIntersection(0.001 * mm); - m_fieldManager->SetDeltaOneStep(0.01 * mm); - m_fieldManager->SetMinimumEpsilonStep(5.0e-5 * mm); - m_fieldManager->SetMaximumEpsilonStep(1.0e-3 * mm); - m_fieldManager->GetChordFinder()->SetDeltaChord(25 * mm); - } - } -} +// inline void ChronoAnaElemTool::switchSimulationGranularity( +// const ChronoAnaElemTool::size_t newsubdet, +// const ChronoAnaElemTool::size_t currentSubdet) { +// if (newsubdet != currentSubdet) { +// if (currentSubdet == TPCIndex) { +// // leaving TPC, turn high +// m_fieldManager->SetDeltaIntersection(1.0e-5 * mm); +// m_fieldManager->SetDeltaOneStep(1.0e-4 * mm); +// m_fieldManager->SetMinimumEpsilonStep(5.0e-5 * mm); +// m_fieldManager->SetMaximumEpsilonStep(1.0e-3 * mm); +// m_fieldManager->GetChordFinder()->SetDeltaChord(0.25 * mm); +// } else if (newsubdet == TPCIndex) { +// // entering TPC, turn low +// m_fieldManager->SetDeltaIntersection(0.001 * mm); +// m_fieldManager->SetDeltaOneStep(0.01 * mm); +// m_fieldManager->SetMinimumEpsilonStep(5.0e-5 * mm); +// m_fieldManager->SetMaximumEpsilonStep(1.0e-3 * mm); +// m_fieldManager->GetChordFinder()->SetDeltaChord(25 * mm); +// } +// } +// } StatusCode ChronoAnaElemTool::finalize() { m_ntuple->reset(); diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index b889c32d..93ff125f 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -90,9 +90,9 @@ private: NTuple::Matrix<time_t> m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx - inline void switchSimulationGranularity(const size_t newsubdet, - const size_t currentSubdet); - G4FieldManager *m_fieldManager; + // inline void switchSimulationGranularity(const size_t newsubdet, + // const size_t currentSubdet); + // G4FieldManager *m_fieldManager; }; #endif -- GitLab From dfed17ef3b06a054708bfd807cae9251247c469e Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Fri, 6 Jun 2025 10:35:24 +0800 Subject: [PATCH 53/74] fix: remove sim grant change --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 25 ------------------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 4 --- 2 files changed, 29 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index e095aa15..0e9fe1a6 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -6,7 +6,6 @@ #include <cstdlib> #include <string> -#include "G4ChordFinder.hh" #include "G4Event.hh" #include "G4FieldManager.hh" #include "G4Step.hh" @@ -224,7 +223,6 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { auto stop = NanoClock::now(); auto event_duration = NanoClock::duration(stop - m_subdet_enter).count(); m_timePerSubdet[m_currentSubdetIndex] += event_duration; - // switchSimulationGranularity(newSubdet, m_currentSubdetIndex); m_currentSubdetIndex = newSubdet; m_subdet_enter = NanoClock::now(); } @@ -294,35 +292,12 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { // << m_currentSubdetIndex << " entering " << newSubdet // << " event time " << event_duration << " track time " // << track_duration << endmsg; - // switchSimulationGranularity(newSubdet, m_currentSubdetIndex); m_currentSubdetIndex = newSubdet; m_subdet_track_enter = m_subdet_enter = NanoClock::now(); } } } -// inline void ChronoAnaElemTool::switchSimulationGranularity( -// const ChronoAnaElemTool::size_t newsubdet, -// const ChronoAnaElemTool::size_t currentSubdet) { -// if (newsubdet != currentSubdet) { -// if (currentSubdet == TPCIndex) { -// // leaving TPC, turn high -// m_fieldManager->SetDeltaIntersection(1.0e-5 * mm); -// m_fieldManager->SetDeltaOneStep(1.0e-4 * mm); -// m_fieldManager->SetMinimumEpsilonStep(5.0e-5 * mm); -// m_fieldManager->SetMaximumEpsilonStep(1.0e-3 * mm); -// m_fieldManager->GetChordFinder()->SetDeltaChord(0.25 * mm); -// } else if (newsubdet == TPCIndex) { -// // entering TPC, turn low -// m_fieldManager->SetDeltaIntersection(0.001 * mm); -// m_fieldManager->SetDeltaOneStep(0.01 * mm); -// m_fieldManager->SetMinimumEpsilonStep(5.0e-5 * mm); -// m_fieldManager->SetMaximumEpsilonStep(1.0e-3 * mm); -// m_fieldManager->GetChordFinder()->SetDeltaChord(25 * mm); -// } -// } -// } - StatusCode ChronoAnaElemTool::finalize() { m_ntuple->reset(); diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 93ff125f..26575e00 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -89,10 +89,6 @@ private: NTuple::Matrix<time_t> m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx - - // inline void switchSimulationGranularity(const size_t newsubdet, - // const size_t currentSubdet); - // G4FieldManager *m_fieldManager; }; #endif -- GitLab From 7862565adbef7232c5ece2349b568ae261e5754f Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 11:23:52 +0800 Subject: [PATCH 54/74] feat: reformat using track user info --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 267 +++++++++--------- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 49 ++-- .../DetSimInterface/CommonUserTrackInfo.hh | 72 ++++- 3 files changed, 226 insertions(+), 162 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 0e9fe1a6..7c193eb5 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -1,15 +1,15 @@ -#include <G4StepStatus.hh> -#include <GaudiKernel/StatusCode.h> #include <cassert> #include <cerrno> #include <climits> +#include <cstddef> +#include <cstdint> #include <cstdlib> #include <string> #include "G4Event.hh" #include "G4FieldManager.hh" #include "G4Step.hh" -#include "G4SystemOfUnits.hh" +#include "G4StepStatus.hh" #include "G4Track.hh" #include "G4TransportationManager.hh" #include "GaudiAlg/GaudiAlgorithm.h" @@ -17,9 +17,11 @@ #include "GaudiKernel/MsgStream.h" #include "GaudiKernel/NTuple.h" #include "GaudiKernel/SmartIF.h" +#include "GaudiKernel/StatusCode.h" #include "ChronoAnaElemTool.h" #include "DetInterface/IGeomSvc.h" +#include "DetSimInterface/CommonUserTrackInfo.hh" DECLARE_COMPONENT(ChronoAnaElemTool) @@ -29,28 +31,28 @@ StatusCode ChronoAnaElemTool::initSubdetVolumes() { ->GetNavigatorForTracking() ->GetWorldVolume(); auto num_dau = world_vol->GetLogicalVolume()->GetNoDaughters(); - debug() << "World Physical Volume - Name: " << world_vol->GetName() - << " Pointer: " << world_vol << " World Logical Volume - Name: " - << world_vol->GetLogicalVolume()->GetName() - << " Pointer: " << world_vol->GetLogicalVolume() << endmsg; + // debug() << "World Physical Volume - Name: " << world_vol->GetName() + // << " Pointer: " << world_vol << " World Logical Volume - Name: " + // << world_vol->GetLogicalVolume()->GetName() + // << " Pointer: " << world_vol->GetLogicalVolume() << endmsg; m_logicalVolumePtrToSubdetIdx[world_vol->GetLogicalVolume()] = PWorldIndex; - debug() << "Set m_logicalVolumePtrToSubdetIdx[" - << world_vol->GetLogicalVolume() << "] to subdet index " - << PWorldIndex << endmsg; + // debug() << "Set m_logicalVolumePtrToSubdetIdx[" + // << world_vol->GetLogicalVolume() << "] to subdet index " + // << PWorldIndex << endmsg; for (size_t _dau = 0; _dau < num_dau; ++_dau) { auto dau_vol = world_vol->GetLogicalVolume()->GetDaughter(_dau); - debug() << "Daughter Physical Volume - Name: " << dau_vol->GetName() - << " Pointer: " << dau_vol << " Daughter Logical Volume - Name: " - << dau_vol->GetLogicalVolume()->GetName() - << " Pointer: " << dau_vol->GetLogicalVolume() << endmsg; + // debug() << "Daughter Physical Volume - Name: " << dau_vol->GetName() + // << " Pointer: " << dau_vol << " Daughter Logical Volume - Name: " + // << dau_vol->GetLogicalVolume()->GetName() + // << " Pointer: " << dau_vol->GetLogicalVolume() << endmsg; auto dau_name = dau_vol->GetName(); - for (size_t _subdet = PWorldIndex; _subdet < m_subdetNames.size(); + for (uint8_t _subdet = PWorldIndex; _subdet < m_subdetNames.size(); ++_subdet) { if (dau_name.find(m_subdetNames[_subdet]) != std::string::npos) { m_logicalVolumePtrToSubdetIdx[dau_vol->GetLogicalVolume()] = _subdet; - debug() << "Set m_logicalVolumePtrToSubdetIdx[" - << dau_vol->GetLogicalVolume() << "] to subdet index " - << _subdet << endmsg; + // debug() << "Set m_logicalVolumePtrToSubdetIdx[" + // << dau_vol->GetLogicalVolume() << "] to subdet index " + // << _subdet << endmsg; continue; } } @@ -98,51 +100,55 @@ StatusCode ChronoAnaElemTool::initNtuple() { info() << "Create Ntuple Success" << endmsg; suc &= m_ntuple->addItem("EventNumber", m_eventNumber, 0U, UINT_MAX) .isSuccess(); - suc &= m_ntuple->addItem("TotSimTime", m_eventTotSimTime).isSuccess(); suc &= - m_ntuple - ->addItem("TimePerSubdet", m_subdetNames.size(), m_timePerSubdet) + m_ntuple->addItem("TotSimTime", m_eventTotSimTime, 0ULL, ULLONG_MAX) .isSuccess(); - suc &= m_ntuple->addItem("TrackNum", m_trackNum, 0U, MAX_TRACK_NUM) + suc &= m_ntuple->addItem("TrackNum", m_trackIdx, 0U, MAX_TRACK_NUM) .isSuccess(); - suc &= m_ntuple->addItem("TrackPx", m_trackNum, m_trackPx); - suc &= m_ntuple->addItem("TrackPy", m_trackNum, m_trackPy); - suc &= m_ntuple->addItem("TrackPz", m_trackNum, m_trackPz); - suc &= m_ntuple->addItem("TrackX", m_trackNum, m_trackX); - suc &= m_ntuple->addItem("TrackY", m_trackNum, m_trackY); - suc &= m_ntuple->addItem("TrackZ", m_trackNum, m_trackZ); - suc &= m_ntuple->addIndexedItem("TrackLengths", m_trackNum, m_trackLength) + suc &= m_ntuple->addItem("TrackPx", m_trackIdx, m_trackPx); + suc &= m_ntuple->addItem("TrackPy", m_trackIdx, m_trackPy); + suc &= m_ntuple->addItem("TrackPz", m_trackIdx, m_trackPz); + suc &= m_ntuple->addItem("TrackX", m_trackIdx, m_trackX); + suc &= m_ntuple->addItem("TrackY", m_trackIdx, m_trackY); + suc &= m_ntuple->addItem("TrackZ", m_trackIdx, m_trackZ); + suc &= m_ntuple->addIndexedItem("TrackLengths", m_trackIdx, m_trackLength) .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackNum, m_trackTime) + suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackIdx, m_trackTime) .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackNum, m_trackPDGId) + suc &= m_ntuple->addIndexedItem("TrackPDGID", m_trackIdx, m_trackPDGId) .isSuccess(); suc &= m_ntuple - ->addIndexedItem("TrackStartSubdet", m_trackNum, + ->addIndexedItem("TrackStartSubdet", m_trackIdx, m_trackStartSubdet) .isSuccess(); suc &= m_ntuple - ->addIndexedItem("TrackEndSubdet", m_trackNum, m_trackEndSubdet) + ->addIndexedItem("TrackEndSubdet", m_trackIdx, m_trackEndSubdet) .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackCharge", m_trackNum, m_trackCharge) - .isSuccess(); suc &= - m_ntuple->addIndexedItem("TrackStepNum", m_trackNum, m_trackStepNum) + m_ntuple->addIndexedItem("TrackStepNum", m_trackIdx, m_trackStepNum) .isSuccess(); - suc &= m_ntuple->addIndexedItem("TrackID", m_trackNum, m_trackID) + suc &= m_ntuple->addIndexedItem("TrackEnergy", m_trackIdx, m_trackE) .isSuccess(); - suc &= - m_ntuple->addIndexedItem("TrackParentID", m_trackNum, m_trackParentID) - .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackKineticEnergy", m_trackNum, - m_trackKineticEnergy) + suc &= m_ntuple->addIndexedItem("TrackDeltaEnergy", m_trackIdx, m_trackdE) .isSuccess(); suc &= m_ntuple - ->addIndexedItem("TrackTimePerSubdet", m_trackNum, + ->addIndexedItem("TrackTimePerSubdet", m_trackIdx, MAX_SUBDET_NUM, m_trackTimePerSubdet) .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackStepPerSubdet", m_trackIdx, + MAX_SUBDET_NUM, m_trackStepPerSubdet) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackNumSubdetSequence", m_trackIdx, + m_trackNumSubdetSequence) + .isSuccess(); + suc &= + m_ntuple + ->addIndexedItem("TrackSubdetSequence", m_trackIdx, + MAX_SUBDET_SEQUENCE_NUM, m_trackSubdetSequence) + .isSuccess(); } else { error() << "Cannot book N-tuple." << endmsg; return StatusCode::FAILURE; @@ -162,9 +168,6 @@ StatusCode ChronoAnaElemTool::initialize() { return StatusCode::FAILURE; } - // m_fieldManager = - // G4TransportationManager::GetTransportationManager()->GetFieldManager(); - // calibrate the clock before starting the simulation NanoClock::calibrate(); @@ -175,94 +178,128 @@ StatusCode ChronoAnaElemTool::initialize() { return suc ? StatusCode::SUCCESS : StatusCode::FAILURE; } +void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { + m_ntuple->reset(); + m_eventNumber = static_cast<uint>(event->GetEventID()); + always() << " ChronoAnaElemTool: Event number: " << m_eventNumber << endmsg; + if (m_eventNumber < m_skipFirstNEvents.value()) { + return; + } + + m_event_start = NanoClock::now(); +} + void ChronoAnaElemTool::EndOfEventAction(const G4Event *) { if (m_eventNumber < m_skipFirstNEvents.value()) { return; } NanoClock::time_point event_stop = NanoClock::now(); - m_timePerSubdet[m_currentSubdetIndex] += - NanoClock::duration(event_stop - m_subdet_enter).count(); m_eventTotSimTime = NanoClock::duration(event_stop - m_event_start).count(); if (m_ntuple->write().isFailure()) { error() << "Error write track tuple at event " << m_eventNumber << endmsg; } } -void ChronoAnaElemTool::BeginOfEventAction(const G4Event *event) { - m_ntuple->reset(); - m_eventNumber = static_cast<size_t>(event->GetEventID()); - always() << " ChronoAnaElemTool: Event number: " << m_eventNumber << endmsg; +void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { if (m_eventNumber < m_skipFirstNEvents.value()) { return; } - m_currentSubdetIndex = UnknownIndex; - m_subdet_enter = m_event_start = NanoClock::now(); + // ensure info exists + auto info = static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); + if (!info) { + info = new CommonUserTrackInfo(); + track->SetUserInformation(info); + } + auto currentSubdet = getSubdetNameIdx(track->GetTouchable()); + // æ ¹æ®å·²æœ‰çš„ chronoTrackIdx åˆ¤æ–æ˜¯æ–° track 还是 resumed + int chronoTrackIdx = info->GetChronoTrackIdx(); + if (chronoTrackIdx < 0) { + // new track + chronoTrackIdx = m_trackIdx++; // first copy then self-add + info->SetChronoTrackIdx(chronoTrackIdx); + const auto &mom = track->GetMomentum(); + const auto &pos = track->GetPosition(); + m_trackPx[chronoTrackIdx] = mom.x(); + m_trackPy[chronoTrackIdx] = mom.y(); + m_trackPz[chronoTrackIdx] = mom.z(); + m_trackX[chronoTrackIdx] = pos.x(); + m_trackY[chronoTrackIdx] = pos.y(); + m_trackZ[chronoTrackIdx] = pos.z(); + m_trackE[chronoTrackIdx] = track->GetTotalEnergy(); + m_trackPDGId[chronoTrackIdx] = + track->GetParticleDefinition()->GetParticleDefinitionID(); + m_trackStartSubdet[chronoTrackIdx] = currentSubdet; + } else { + // resumed track + error() << "resumed track!!! TrackIdx=" << chronoTrackIdx << endmsg; + } + + info->GetStepNumDeltaAndSet(track->GetCurrentStepNumber()); + info->SetCurrentSubdet(currentSubdet); + const auto start = NanoClock::now(); + info->SetTrackStartTime(start); + info->SetTrackSubdetChangeTime(start); } -void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { +void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { if (m_eventNumber < m_skipFirstNEvents.value()) { return; } - m_trackID[m_trackNum] = track->GetTrackID(); - m_trackParentID[m_trackNum] = track->GetParentID(); - m_trackKineticEnergy[m_trackNum] = track->GetKineticEnergy() / GeV; - auto mom = track->GetMomentum(); - auto pos = track->GetPosition(); - m_trackPx[m_trackNum] = mom.x() / GeV; - m_trackPy[m_trackNum] = mom.y() / GeV; - m_trackPz[m_trackNum] = mom.z() / GeV; - m_trackX[m_trackNum] = pos.x() / mm; - m_trackY[m_trackNum] = pos.y() / mm; - m_trackZ[m_trackNum] = pos.z() / mm; - m_trackCharge[m_trackNum] = track->GetParticleDefinition()->GetPDGCharge(); - m_trackPDGId[m_trackNum] = - track->GetParticleDefinition()->GetParticleDefinitionID(); - auto newSubdet = m_trackStartSubdet[m_trackNum] = getSubdetNameIdx(track); - if (newSubdet != m_currentSubdetIndex) { - auto stop = NanoClock::now(); - auto event_duration = NanoClock::duration(stop - m_subdet_enter).count(); - m_timePerSubdet[m_currentSubdetIndex] += event_duration; - m_currentSubdetIndex = newSubdet; - m_subdet_enter = NanoClock::now(); + + auto trackStop = NanoClock::now(); + auto info = static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); + auto chronoTrackIdx = info->GetChronoTrackIdx(); + auto currentStep = track->GetCurrentStepNumber(); + + // record value + m_trackdE[chronoTrackIdx] = + track->GetTotalEnergy() - m_trackE[chronoTrackIdx]; + m_trackTime[chronoTrackIdx] += + NanoClock::duration(trackStop - info->GetTrackStartTime()).count(); + auto track_end_subdet = getSubdetNameIdx(track->GetTouchable()); + m_trackLength[chronoTrackIdx] = track->GetTrackLength(); + m_trackStepNum[chronoTrackIdx] = currentStep; + m_trackEndSubdet[chronoTrackIdx] = track_end_subdet; + // add remained time + info->UpdateTrackInfo(trackStop, currentStep); + const auto trackStepPerSubdet = info->GetTrackStepPerSubdet(); + const auto trackTimePerSubdet = info->GetTrackTimePerSubdet(); + for (size_t i = 0; i < MAX_SUBDET_NUM; i++) { + m_trackTimePerSubdet[chronoTrackIdx][i] = trackTimePerSubdet[i]; + m_trackStepPerSubdet[chronoTrackIdx][i] = trackStepPerSubdet[i]; } - // always() << "track " << m_trackID[m_trackNum] << " start in " - // << m_trackStartSubdet[m_trackNum] << endmsg; - m_subdet_track_enter = m_track_start = NanoClock::now(); } -void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { +void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { if (m_eventNumber < m_skipFirstNEvents.value()) { return; } - auto stop = NanoClock::now(); - m_trackTime[m_trackNum] = NanoClock::duration(stop - m_track_start).count(); - auto track_end_subdet = getSubdetNameIdx(track); - m_trackLength[m_trackNum] = track->GetTrackLength(); - m_trackStepNum[m_trackNum] = track->GetCurrentStepNumber(); - m_trackEndSubdet[m_trackNum] = track_end_subdet; - // track did not change subdet, add time - m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += - NanoClock::duration(stop - m_subdet_track_enter).count(); - if (m_currentSubdetIndex != track_end_subdet) { - error() << "Current Subdet " << m_currentSubdetIndex - << " not equal with track end subdet " << track_end_subdet - << endmsg; + + const auto &stepStatus = step->GetPostStepPoint()->GetStepStatus(); + if (stepStatus == fGeomBoundary || stepStatus == fWorldBoundary) { + // last step in a volume or world + const auto &track = step->GetTrack(); + auto info = static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); + auto newSubdet = getSubdetNameIdx(track->GetNextTouchable()); + if (info->IsSubdetChanged(newSubdet)) { + auto stop = NanoClock::now(); + auto currentStep = track->GetCurrentStepNumber(); + info->UpdateTrackInfo(stop, currentStep); + info->SetCurrentSubdet(newSubdet); + info->SetTrackSubdetChangeTime(stop); + } } - // always() << "track " << m_trackID[m_trackNum] << " end in " - // << track_end_subdet << endmsg; - ++m_trackNum; } -inline ChronoAnaElemTool::size_t -ChronoAnaElemTool::getSubdetNameIdx(const G4Track *track) { - auto historyDepthNum = track->GetTouchable()->GetHistoryDepth(); +inline uint8_t +ChronoAnaElemTool::getSubdetNameIdx(const G4VTouchable *touchable) { + auto historyDepthNum = touchable->GetHistoryDepth(); if (historyDepthNum == 0) { return PWorldIndex; } else { - auto lastVolume = track->GetTouchable() - ->GetVolume(historyDepthNum - 1) - ->GetLogicalVolume(); + auto lastVolume = + touchable->GetVolume(historyDepthNum - 1)->GetLogicalVolume(); auto it = m_logicalVolumePtrToSubdetIdx.find(lastVolume); if (it != m_logicalVolumePtrToSubdetIdx.end()) { return it->second; @@ -274,30 +311,6 @@ ChronoAnaElemTool::getSubdetNameIdx(const G4Track *track) { } } -void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { - if (m_eventNumber < m_skipFirstNEvents.value()) { - return; - } - if (step->IsFirstStepInVolume()) { - auto track = step->GetTrack(); - auto newSubdet = getSubdetNameIdx(track); - if (newSubdet != m_currentSubdetIndex) { - auto stop = NanoClock::now(); - auto event_duration = NanoClock::duration(stop - m_subdet_enter).count(); - auto track_duration = - NanoClock::duration(stop - m_subdet_track_enter).count(); - m_timePerSubdet[m_currentSubdetIndex] += event_duration; - m_trackTimePerSubdet[m_trackNum][m_currentSubdetIndex] += track_duration; - // always() << "track " << track->GetTrackID() << " from " - // << m_currentSubdetIndex << " entering " << newSubdet - // << " event time " << event_duration << " track time " - // << track_duration << endmsg; - m_currentSubdetIndex = newSubdet; - m_subdet_track_enter = m_subdet_enter = NanoClock::now(); - } - } -} - StatusCode ChronoAnaElemTool::finalize() { m_ntuple->reset(); diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 26575e00..463edabb 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -3,6 +3,7 @@ #include <chrono> #include <climits> +#include <cstdint> #include <string> #include <unordered_map> #include <vector> @@ -11,6 +12,7 @@ #include "DetSimInterface/IAnaElemTool.h" #include "G4LogicalVolume.hh" +#include "G4VTouchable.hh" #include "Gaudi/Timers/RdtscClock.h" #include "GaudiKernel/AlgTool.h" #include "GaudiKernel/INTupleSvc.h" @@ -23,7 +25,7 @@ public: using extends::extends; using NanoClock = Gaudi::Timers::RdtscClock<std::chrono::nanoseconds>; typedef unsigned long long time_t; - typedef unsigned int size_t; + typedef unsigned long long uint64_t; // Event virtual void BeginOfEventAction(const G4Event *) override; @@ -47,48 +49,41 @@ private: NTuple::Tuple *m_ntuple; StatusCode initNtuple(); - NTuple::Item<size_t> m_eventNumber; + NTuple::Item<uint> m_eventNumber; NTuple::Item<time_t> m_eventTotSimTime; NanoClock::time_point m_event_start; - Gaudi::Property<size_t> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; + Gaudi::Property<uint> m_skipFirstNEvents{this, "SkipFirstNEvents", 5}; // simtime over subdet StatusCode initSubdetNames(); StatusCode initSubdetVolumes(); - static constexpr size_t UnknownIndex = 0; - static constexpr size_t PWorldIndex = 1; - static constexpr size_t TPCIndex = 25; + static constexpr uint8_t UnknownIndex = 0; + static constexpr uint8_t PWorldIndex = 1; std::vector<std::string> m_subdetNames; - std::unordered_map<G4LogicalVolume *, size_t> m_logicalVolumePtrToSubdetIdx; + std::unordered_map<G4LogicalVolume *, uint8_t> m_logicalVolumePtrToSubdetIdx; - inline size_t getSubdetNameIdx(const G4Track *track); - size_t m_currentSubdetIndex = UnknownIndex; - NanoClock::time_point m_subdet_enter; - NTuple::Array<time_t> m_timePerSubdet; + inline uint8_t getSubdetNameIdx(const G4VTouchable *touchable); // simtime over track - static constexpr size_t MAX_TRACK_NUM = 10'000'000; // 10M - static constexpr size_t MAX_SUBDET_NUM = 30; + static constexpr uint MAX_TRACK_NUM = 1'000'000; // 1M NanoClock::time_point m_track_start; - NanoClock::time_point m_subdet_track_enter; - NTuple::Item<size_t> m_trackNum; - NTuple::Array<int> m_trackID; - NTuple::Array<int> m_trackParentID; - NTuple::Array<double> m_trackKineticEnergy; + NTuple::Item<uint> m_trackIdx; NTuple::Array<double> m_trackPx, m_trackPy, m_trackPz; NTuple::Array<double> m_trackX, m_trackY, m_trackZ; - NTuple::Array<double> m_trackLength; - NTuple::Array<double> m_trackCharge; - NTuple::Array<int> m_trackPDGId; - NTuple::Array<int> m_trackStepNum; + NTuple::Array<double> m_trackLength, m_trackE, m_trackdE; + NTuple::Array<int> m_trackPDGId, m_trackStepNum; NTuple::Array<time_t> m_trackTime; - NTuple::Array<size_t> m_trackStartSubdet; - NTuple::Array<size_t> m_trackEndSubdet; - - NTuple::Matrix<time_t> - m_trackTimePerSubdet; // tracknum * subdet_size + subdet_idx + NTuple::Array<uint8_t> m_trackStartSubdet, m_trackEndSubdet; + + static constexpr uint MAX_SUBDET_NUM = 26; + NTuple::Matrix<time_t> m_trackTimePerSubdet; + NTuple::Matrix<int> m_trackStepPerSubdet; + static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 10; + NTuple::Array<int> m_trackNumSubdetSequence; + NTuple::Matrix<uint64_t> + m_trackSubdetSequence; // 5bit for one subdet, uint64 for 12 subdets }; #endif diff --git a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh index ce63e602..7ae3590d 100644 --- a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh +++ b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh @@ -14,22 +14,78 @@ */ #include "G4VUserTrackInformation.hh" +#include "Gaudi/Timers/RdtscClock.h" +#include <array> +#include <cstdint> -class CommonUserTrackInfo: public G4VUserTrackInformation { +class CommonUserTrackInfo : public G4VUserTrackInformation { public: - CommonUserTrackInfo(); - ~CommonUserTrackInfo(); + using NanoClock = Gaudi::Timers::RdtscClock<std::chrono::nanoseconds>; + static constexpr uint MAX_SUBDET_NUM = 26; + CommonUserTrackInfo(); + ~CommonUserTrackInfo(); public: + virtual void Print() const; - virtual void Print() const; + // get the idx in the EDM4hep MC particle collection + bool setIdxEdm4hep(int idxEdm4hep); + int idxEdm4hep() const; - // get the idx in the EDM4hep MC particle collection - bool setIdxEdm4hep(int idxEdm4hep); - int idxEdm4hep() const; + inline int GetChronoTrackIdx() { return m_chronoTrackIdx; }; + inline void SetChronoTrackIdx(const int chronoTrackIdx) { + m_chronoTrackIdx = chronoTrackIdx; + }; + inline uint8_t GetCurrentSubdet() const { return m_currentSubdet; }; + inline bool IsSubdetChanged(const uint8_t newSubdet) { + return newSubdet != m_currentSubdet; + }; + inline void SetCurrentSubdet(const uint8_t newSubdet) { + m_currentSubdet = newSubdet; + }; + inline int GetStepNumDeltaAndSet(const int newStepNum) { + const int delta = newStepNum - m_currentStepNum; + m_currentStepNum = newStepNum; + return delta; + }; + + inline void UpdateTrackInfo(const NanoClock::time_point &stop, + const int currentStep) { + m_trackTimePerSubdet[m_currentSubdet] += + NanoClock::duration(stop - m_trackSubdetChangeTime).count(); + m_trackStepPerSubdet[m_currentSubdet] += GetStepNumDeltaAndSet(currentStep); + } + + inline NanoClock::time_point GetTrackStartTime() const { + return m_trackStartTime; + } + inline NanoClock::time_point GetTrackSubdetChangeTime() const { + return m_trackSubdetChangeTime; + } + inline const std::array<unsigned long long, MAX_SUBDET_NUM> & + GetTrackTimePerSubdet() const { + return m_trackTimePerSubdet; + } + inline const std::array<unsigned long long, MAX_SUBDET_NUM> & + GetTrackStepPerSubdet() const { + return m_trackStepPerSubdet; + } + + inline void SetTrackStartTime(const NanoClock::time_point &time) { + m_trackStartTime = time; + } + inline void SetTrackSubdetChangeTime(const NanoClock::time_point &time) { + m_trackSubdetChangeTime = time; + } private: - int m_idxEdm4hep = -1; + int m_idxEdm4hep = -1; + int m_chronoTrackIdx = -1; + uint8_t m_currentSubdet = 0; + int m_currentStepNum = 0; + NanoClock::time_point m_trackStartTime, m_trackSubdetChangeTime; + std::array<unsigned long long, MAX_SUBDET_NUM> m_trackTimePerSubdet{}, + m_trackStepPerSubdet{}; }; #endif -- GitLab From fcfe9b7c70aa9f86862750c60c58e1e8e9603d18 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 11:25:59 +0800 Subject: [PATCH 55/74] fix: SetCurrentSubdet in post tracking --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 7c193eb5..2bf422e0 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -263,6 +263,7 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { m_trackEndSubdet[chronoTrackIdx] = track_end_subdet; // add remained time info->UpdateTrackInfo(trackStop, currentStep); + info->SetCurrentSubdet(track_end_subdet); const auto trackStepPerSubdet = info->GetTrackStepPerSubdet(); const auto trackTimePerSubdet = info->GetTrackTimePerSubdet(); for (size_t i = 0; i < MAX_SUBDET_NUM; i++) { -- GitLab From 22fb9c15d40441c93c9969d7247a75c1c578339b Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 12:11:45 +0800 Subject: [PATCH 56/74] feat: record track sequence --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 22 ++-- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 2 +- .../DetSimInterface/CommonUserTrackInfo.hh | 74 +++++------- .../src/CommonUserTrackInfo.cc | 105 ++++++++++++++++-- 4 files changed, 142 insertions(+), 61 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 2bf422e0..67ded825 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -140,10 +140,10 @@ StatusCode ChronoAnaElemTool::initNtuple() { ->addIndexedItem("TrackStepPerSubdet", m_trackIdx, MAX_SUBDET_NUM, m_trackStepPerSubdet) .isSuccess(); - suc &= m_ntuple - ->addIndexedItem("TrackNumSubdetSequence", m_trackIdx, - m_trackNumSubdetSequence) - .isSuccess(); + suc &= + m_ntuple + ->addIndexedItem("TrackNumSubdet", m_trackIdx, m_trackNumSubdet) + .isSuccess(); suc &= m_ntuple ->addIndexedItem("TrackSubdetSequence", m_trackIdx, @@ -230,13 +230,12 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_trackPDGId[chronoTrackIdx] = track->GetParticleDefinition()->GetParticleDefinitionID(); m_trackStartSubdet[chronoTrackIdx] = currentSubdet; + info->SetStepNum(track->GetCurrentStepNumber()); + info->SetCurrentSubdet(currentSubdet); } else { // resumed track error() << "resumed track!!! TrackIdx=" << chronoTrackIdx << endmsg; } - - info->GetStepNumDeltaAndSet(track->GetCurrentStepNumber()); - info->SetCurrentSubdet(currentSubdet); const auto start = NanoClock::now(); info->SetTrackStartTime(start); info->SetTrackSubdetChangeTime(start); @@ -263,13 +262,17 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { m_trackEndSubdet[chronoTrackIdx] = track_end_subdet; // add remained time info->UpdateTrackInfo(trackStop, currentStep); - info->SetCurrentSubdet(track_end_subdet); const auto trackStepPerSubdet = info->GetTrackStepPerSubdet(); const auto trackTimePerSubdet = info->GetTrackTimePerSubdet(); for (size_t i = 0; i < MAX_SUBDET_NUM; i++) { m_trackTimePerSubdet[chronoTrackIdx][i] = trackTimePerSubdet[i]; m_trackStepPerSubdet[chronoTrackIdx][i] = trackStepPerSubdet[i]; } + const auto trackSubdetSequence = info->GetTrackSubdetSequence(); + m_trackNumSubdet[chronoTrackIdx] = info->GetNumSubdet(); + for (size_t i = 0; i < MAX_SUBDET_SEQUENCE_NUM; i++) { + m_trackSubdetSequence[chronoTrackIdx][i] = trackSubdetSequence[i]; + } } void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { @@ -285,9 +288,10 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { auto newSubdet = getSubdetNameIdx(track->GetNextTouchable()); if (info->IsSubdetChanged(newSubdet)) { auto stop = NanoClock::now(); + info->SetCurrentSubdet(newSubdet); auto currentStep = track->GetCurrentStepNumber(); info->UpdateTrackInfo(stop, currentStep); - info->SetCurrentSubdet(newSubdet); + info->SetStepNum(currentStep); info->SetTrackSubdetChangeTime(stop); } } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 463edabb..90890a37 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -81,7 +81,7 @@ private: NTuple::Matrix<time_t> m_trackTimePerSubdet; NTuple::Matrix<int> m_trackStepPerSubdet; static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 10; - NTuple::Array<int> m_trackNumSubdetSequence; + NTuple::Array<int> m_trackNumSubdet; NTuple::Matrix<uint64_t> m_trackSubdetSequence; // 5bit for one subdet, uint64 for 12 subdets }; diff --git a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh index 7ae3590d..33e80187 100644 --- a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh +++ b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh @@ -22,6 +22,7 @@ class CommonUserTrackInfo : public G4VUserTrackInformation { public: using NanoClock = Gaudi::Timers::RdtscClock<std::chrono::nanoseconds>; static constexpr uint MAX_SUBDET_NUM = 26; + static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 10; CommonUserTrackInfo(); ~CommonUserTrackInfo(); @@ -32,60 +33,45 @@ public: bool setIdxEdm4hep(int idxEdm4hep); int idxEdm4hep() const; - inline int GetChronoTrackIdx() { return m_chronoTrackIdx; }; - inline void SetChronoTrackIdx(const int chronoTrackIdx) { - m_chronoTrackIdx = chronoTrackIdx; - }; - inline uint8_t GetCurrentSubdet() const { return m_currentSubdet; }; - inline bool IsSubdetChanged(const uint8_t newSubdet) { - return newSubdet != m_currentSubdet; - }; - inline void SetCurrentSubdet(const uint8_t newSubdet) { - m_currentSubdet = newSubdet; - }; - inline int GetStepNumDeltaAndSet(const int newStepNum) { - const int delta = newStepNum - m_currentStepNum; - m_currentStepNum = newStepNum; - return delta; - }; + int GetChronoTrackIdx(); + void SetChronoTrackIdx(const int chronoTrackIdx); - inline void UpdateTrackInfo(const NanoClock::time_point &stop, - const int currentStep) { - m_trackTimePerSubdet[m_currentSubdet] += - NanoClock::duration(stop - m_trackSubdetChangeTime).count(); - m_trackStepPerSubdet[m_currentSubdet] += GetStepNumDeltaAndSet(currentStep); - } + // Subdetector related + uint8_t GetCurrentSubdet() const; + bool IsSubdetChanged(const uint8_t newSubdet); + void SetCurrentSubdet(const uint8_t newSubdet); - inline NanoClock::time_point GetTrackStartTime() const { - return m_trackStartTime; - } - inline NanoClock::time_point GetTrackSubdetChangeTime() const { - return m_trackSubdetChangeTime; - } - inline const std::array<unsigned long long, MAX_SUBDET_NUM> & - GetTrackTimePerSubdet() const { - return m_trackTimePerSubdet; - } - inline const std::array<unsigned long long, MAX_SUBDET_NUM> & - GetTrackStepPerSubdet() const { - return m_trackStepPerSubdet; - } + // Step number related + void SetStepNum(const int newStepNum); - inline void SetTrackStartTime(const NanoClock::time_point &time) { - m_trackStartTime = time; - } - inline void SetTrackSubdetChangeTime(const NanoClock::time_point &time) { - m_trackSubdetChangeTime = time; - } + // Track timing and step information + void UpdateTrackInfo(const NanoClock::time_point &stop, + const int currentStep); + NanoClock::time_point GetTrackStartTime() const; + NanoClock::time_point GetTrackSubdetChangeTime() const; + const std::array<unsigned long long, MAX_SUBDET_NUM> & + GetTrackTimePerSubdet() const; + const std::array<int, MAX_SUBDET_NUM> &GetTrackStepPerSubdet() const; + void SetTrackStartTime(const NanoClock::time_point &time); + void SetTrackSubdetChangeTime(const NanoClock::time_point &time); + + int GetNumSubdet() const; + void AddSubdet(const uint8_t subdet); + const std::array<unsigned long long, MAX_SUBDET_SEQUENCE_NUM> & + GetTrackSubdetSequence() const; private: int m_idxEdm4hep = -1; int m_chronoTrackIdx = -1; uint8_t m_currentSubdet = 0; int m_currentStepNum = 0; + int m_currentSubdetNum = 0; + NanoClock::time_point m_trackStartTime, m_trackSubdetChangeTime; - std::array<unsigned long long, MAX_SUBDET_NUM> m_trackTimePerSubdet{}, - m_trackStepPerSubdet{}; + std::array<unsigned long long, MAX_SUBDET_NUM> m_trackTimePerSubdet{}; + std::array<int, MAX_SUBDET_NUM> m_trackStepPerSubdet{}; + std::array<unsigned long long, MAX_SUBDET_SEQUENCE_NUM> + m_trackSubdetSequence{}; }; #endif diff --git a/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc b/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc index 9a923a35..f211f19a 100644 --- a/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc +++ b/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc @@ -1,22 +1,113 @@ #include "DetSimInterface/CommonUserTrackInfo.hh" #include <iostream> +#include <ostream> -CommonUserTrackInfo::CommonUserTrackInfo() { +CommonUserTrackInfo::CommonUserTrackInfo() {} +CommonUserTrackInfo::~CommonUserTrackInfo() {} + +inline void CommonUserTrackInfo::Print() const {} + +inline bool CommonUserTrackInfo::setIdxEdm4hep(int idxEdm4hep) { + m_idxEdm4hep = idxEdm4hep; } -CommonUserTrackInfo::~CommonUserTrackInfo() { +inline int CommonUserTrackInfo::idxEdm4hep() const { return m_idxEdm4hep; } + +inline int CommonUserTrackInfo::GetChronoTrackIdx() { + return m_chronoTrackIdx; +}; + +inline void CommonUserTrackInfo::SetChronoTrackIdx(const int chronoTrackIdx) { + m_chronoTrackIdx = chronoTrackIdx; +}; + +inline uint8_t CommonUserTrackInfo::GetCurrentSubdet() const { + return m_currentSubdet; +}; + +inline bool CommonUserTrackInfo::IsSubdetChanged(const uint8_t newSubdet) { + return newSubdet != m_currentSubdet; +}; +inline void CommonUserTrackInfo::SetCurrentSubdet(const uint8_t newSubdet) { + m_currentSubdet = newSubdet; + AddSubdet(newSubdet); +}; + +inline void CommonUserTrackInfo::SetStepNum(const int newStepNum) { + m_currentStepNum = newStepNum; +}; + +inline void +CommonUserTrackInfo::UpdateTrackInfo(const NanoClock::time_point &stop, + const int currentStep) { + m_trackTimePerSubdet[m_currentSubdet] += + NanoClock::duration(stop - m_trackSubdetChangeTime).count(); + m_trackStepPerSubdet[m_currentSubdet] += currentStep - m_currentStepNum; } -void CommonUserTrackInfo::Print() const { +inline CommonUserTrackInfo::NanoClock::time_point +CommonUserTrackInfo::GetTrackStartTime() const { + return m_trackStartTime; +} + +inline CommonUserTrackInfo::NanoClock::time_point +CommonUserTrackInfo::GetTrackSubdetChangeTime() const { + return m_trackSubdetChangeTime; +} +inline const std::array<unsigned long long, + CommonUserTrackInfo::MAX_SUBDET_NUM> & +CommonUserTrackInfo::GetTrackTimePerSubdet() const { + return m_trackTimePerSubdet; } -bool CommonUserTrackInfo::setIdxEdm4hep(int idxEdm4hep) { - m_idxEdm4hep = idxEdm4hep; +inline const std::array<int, CommonUserTrackInfo::MAX_SUBDET_NUM> & +CommonUserTrackInfo::GetTrackStepPerSubdet() const { + return m_trackStepPerSubdet; } -int CommonUserTrackInfo::idxEdm4hep() const { - return m_idxEdm4hep; +inline void +CommonUserTrackInfo::SetTrackStartTime(const NanoClock::time_point &time) { + m_trackStartTime = time; } + +inline void CommonUserTrackInfo::SetTrackSubdetChangeTime( + const NanoClock::time_point &time) { + m_trackSubdetChangeTime = time; +} + +inline const std::array<unsigned long long, + CommonUserTrackInfo::MAX_SUBDET_SEQUENCE_NUM> & +CommonUserTrackInfo::GetTrackSubdetSequence() const { + return m_trackSubdetSequence; +} + +inline int CommonUserTrackInfo::GetNumSubdet() const { + return m_currentSubdetNum; +}; + +inline void CommonUserTrackInfo::AddSubdet(const uint8_t subdet) { + static constexpr int kSlotsPerULL = 64 / 5; + + if (m_currentSubdetNum >= MAX_SUBDET_SEQUENCE_NUM * kSlotsPerULL) { + std::cerr + << "CommonUserTrackInfo::SetNthSubdet: error! subdet num overflow!" + << std::endl; + return; + } + // æ¯ä¸ªunsigned long longå¯ä»¥å˜å‚¨12个5bit值(64/5=12) + const int array_idx = m_currentSubdetNum / kSlotsPerULL; + // 在当å‰å…ƒç´ ä¸çš„bitä½ç½® + const int bit_pos = (m_currentSubdetNum % kSlotsPerULL) * 5; + + // ç¡®ä¿subdet值ä¸è¶…过5bit范围 + uint8_t masked_subdet = subdet & 0x1F; // 0x1F = 0b11111 + + // 清除原有ä½ç½®çš„值并写入新值 + m_trackSubdetSequence[array_idx] &= ~(0x1FULL << bit_pos); + m_trackSubdetSequence[array_idx] |= (masked_subdet & 0x1FULL) << bit_pos; + + m_currentSubdetNum++; +}; \ No newline at end of file -- GitLab From dd28fe518a195b496dfb288701b59985ffdbe66a Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 12:12:29 +0800 Subject: [PATCH 57/74] chore: comment --- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 90890a37..ed8f4537 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -82,8 +82,8 @@ private: NTuple::Matrix<int> m_trackStepPerSubdet; static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 10; NTuple::Array<int> m_trackNumSubdet; - NTuple::Matrix<uint64_t> - m_trackSubdetSequence; // 5bit for one subdet, uint64 for 12 subdets + // 5bit for one subdet, uint64 for 12 subdets + NTuple::Matrix<uint64_t> m_trackSubdetSequence; }; #endif -- GitLab From f423eb7feb0aadcc050ee381e7eba356badf1e19 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 12:16:32 +0800 Subject: [PATCH 58/74] fix: always enable magnetic field even disable SD --- Simulation/DetSimGeom/src/DDG4DetElemTool.cpp | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/Simulation/DetSimGeom/src/DDG4DetElemTool.cpp b/Simulation/DetSimGeom/src/DDG4DetElemTool.cpp index 63f33a25..ac308888 100644 --- a/Simulation/DetSimGeom/src/DDG4DetElemTool.cpp +++ b/Simulation/DetSimGeom/src/DDG4DetElemTool.cpp @@ -77,6 +77,37 @@ DDG4DetElemTool::getLV() { void DDG4DetElemTool::ConstructSDandField() { + auto lcdd = m_geosvc->lcdd(); + + // ======================================================================= + // Construct Field + // ======================================================================= + // TODO: integrate the field between DD4hep and Geant4 + // Note: + // DD4hep provides the parameters of fields + // Geant4 will setup the field based on the DD4hep fields + + // Related Examples: + // - G4: G4GlobalMagFieldMessenger.cc + + G4FieldManager* fieldManager + = G4TransportationManager::GetTransportationManager()->GetFieldManager(); + + // // Below is a uniform B-field + // G4ThreeVector value(0,0,3.*tesla); + // G4UniformMagField* mag_field = new G4UniformMagField(value); + + // DDG4 based B-field + dd4hep::OverlayedField fld = lcdd->field(); + G4MagneticField* mag_field = new dd4hep::sim::Geant4Field(fld); + + fieldManager->SetDetectorField(mag_field); + fieldManager->CreateChordFinder(mag_field); + fieldManager->SetDeltaIntersection(m_DeltaIntersection.value()); + fieldManager->SetDeltaOneStep(m_DeltaOneStep.value()); + fieldManager->SetMinimumEpsilonStep(m_MinimumEpsilonStep.value()); + fieldManager->SetMaximumEpsilonStep(m_MaximumEpsilonStep.value()); + // DEBUG ONLY: turn off all the SD. if (not m_SD_enabled) { warning() << "All the Sensitive Detectors will be disabled by default. " << endmsg; @@ -94,8 +125,6 @@ DDG4DetElemTool::ConstructSDandField() { dd4hep::sim::Geant4GeometryInfo* p = dd4hep::sim::Geant4Mapping::instance().ptr(); _SV& vols = p->sensitives; - auto lcdd = m_geosvc->lcdd(); - for (_SV::const_iterator iv = vols.begin(); iv != vols.end(); ++iv) { dd4hep::SensitiveDetector sd = (*iv).first; std::string typ = sd.type(), nam = sd.name(); @@ -200,35 +229,6 @@ DDG4DetElemTool::ConstructSDandField() { << " senstive volumes are registered. " << endmsg; } - // ======================================================================= - // Construct Field - // ======================================================================= - // TODO: integrate the field between DD4hep and Geant4 - // Note: - // DD4hep provides the parameters of fields - // Geant4 will setup the field based on the DD4hep fields - - // Related Examples: - // - G4: G4GlobalMagFieldMessenger.cc - - G4FieldManager* fieldManager - = G4TransportationManager::GetTransportationManager()->GetFieldManager(); - - // // Below is a uniform B-field - // G4ThreeVector value(0,0,3.*tesla); - // G4UniformMagField* mag_field = new G4UniformMagField(value); - - // DDG4 based B-field - dd4hep::OverlayedField fld = lcdd->field(); - G4MagneticField* mag_field = new dd4hep::sim::Geant4Field(fld); - - fieldManager->SetDetectorField(mag_field); - fieldManager->CreateChordFinder(mag_field); - fieldManager->SetDeltaIntersection(m_DeltaIntersection.value()); - fieldManager->SetDeltaOneStep(m_DeltaOneStep.value()); - fieldManager->SetMinimumEpsilonStep(m_MinimumEpsilonStep.value()); - fieldManager->SetMaximumEpsilonStep(m_MaximumEpsilonStep.value()); - } StatusCode -- GitLab From 630f1df35e22333994828d7737c17cff11a49b8c Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 12:54:26 +0800 Subject: [PATCH 59/74] fix: put inline func into header file --- .../DetSimInterface/CommonUserTrackInfo.hh | 62 ++++++++++--- .../src/CommonUserTrackInfo.cc | 86 +++---------------- 2 files changed, 65 insertions(+), 83 deletions(-) diff --git a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh index 33e80187..d61e14c9 100644 --- a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh +++ b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh @@ -17,6 +17,7 @@ #include "Gaudi/Timers/RdtscClock.h" #include <array> #include <cstdint> +#include <sys/types.h> class CommonUserTrackInfo : public G4VUserTrackInformation { public: @@ -38,25 +39,15 @@ public: // Subdetector related uint8_t GetCurrentSubdet() const; - bool IsSubdetChanged(const uint8_t newSubdet); - void SetCurrentSubdet(const uint8_t newSubdet); - - // Step number related - void SetStepNum(const int newStepNum); // Track timing and step information - void UpdateTrackInfo(const NanoClock::time_point &stop, - const int currentStep); NanoClock::time_point GetTrackStartTime() const; NanoClock::time_point GetTrackSubdetChangeTime() const; const std::array<unsigned long long, MAX_SUBDET_NUM> & GetTrackTimePerSubdet() const; const std::array<int, MAX_SUBDET_NUM> &GetTrackStepPerSubdet() const; void SetTrackStartTime(const NanoClock::time_point &time); - void SetTrackSubdetChangeTime(const NanoClock::time_point &time); - int GetNumSubdet() const; - void AddSubdet(const uint8_t subdet); const std::array<unsigned long long, MAX_SUBDET_SEQUENCE_NUM> & GetTrackSubdetSequence() const; @@ -65,13 +56,62 @@ private: int m_chronoTrackIdx = -1; uint8_t m_currentSubdet = 0; int m_currentStepNum = 0; - int m_currentSubdetNum = 0; + uint m_currentSubdetNum = 0; NanoClock::time_point m_trackStartTime, m_trackSubdetChangeTime; std::array<unsigned long long, MAX_SUBDET_NUM> m_trackTimePerSubdet{}; std::array<int, MAX_SUBDET_NUM> m_trackStepPerSubdet{}; std::array<unsigned long long, MAX_SUBDET_SEQUENCE_NUM> m_trackSubdetSequence{}; + +public: + inline bool IsSubdetChanged(const uint8_t newSubdet) { + return newSubdet != m_currentSubdet; + }; + + inline void SetCurrentSubdet(const uint8_t newSubdet) { + m_currentSubdet = newSubdet; + AddSubdet(newSubdet); + }; + + void SetTrackSubdetChangeTime(const NanoClock::time_point &time) { + m_trackSubdetChangeTime = time; + }; + + inline void AddSubdet(const uint8_t subdet) { + static constexpr int kSlotsPerULL = 64 / 5; + + if (m_currentSubdetNum >= MAX_SUBDET_SEQUENCE_NUM * kSlotsPerULL) { + std::cerr + << "CommonUserTrackInfo::SetNthSubdet: error! subdet num overflow!" + << std::endl; + return; + } + // æ¯ä¸ªunsigned long longå¯ä»¥å˜å‚¨12个5bit值(64/5=12) + const int array_idx = m_currentSubdetNum / kSlotsPerULL; + // 在当å‰å…ƒç´ ä¸çš„bitä½ç½® + const int bit_pos = (m_currentSubdetNum % kSlotsPerULL) * 5; + + // ç¡®ä¿subdet值ä¸è¶…过5bit范围 + uint8_t masked_subdet = subdet & 0x1F; // 0x1F = 0b11111 + + // 清除原有ä½ç½®çš„值并写入新值 + m_trackSubdetSequence[array_idx] &= ~(0x1FULL << bit_pos); + m_trackSubdetSequence[array_idx] |= (masked_subdet & 0x1FULL) << bit_pos; + + m_currentSubdetNum++; + }; + + inline void UpdateTrackInfo(const NanoClock::time_point &stop, + const int currentStep) { + m_trackTimePerSubdet[m_currentSubdet] += + NanoClock::duration(stop - m_trackSubdetChangeTime).count(); + m_trackStepPerSubdet[m_currentSubdet] += currentStep - m_currentStepNum; + }; + + inline void SetStepNum(const int newStepNum) { + m_currentStepNum = newStepNum; + }; }; #endif diff --git a/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc b/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc index f211f19a..d83f53d5 100644 --- a/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc +++ b/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc @@ -1,113 +1,55 @@ #include "DetSimInterface/CommonUserTrackInfo.hh" -#include <iostream> -#include <ostream> CommonUserTrackInfo::CommonUserTrackInfo() {} CommonUserTrackInfo::~CommonUserTrackInfo() {} -inline void CommonUserTrackInfo::Print() const {} +void CommonUserTrackInfo::Print() const {} -inline bool CommonUserTrackInfo::setIdxEdm4hep(int idxEdm4hep) { +bool CommonUserTrackInfo::setIdxEdm4hep(int idxEdm4hep) { m_idxEdm4hep = idxEdm4hep; } -inline int CommonUserTrackInfo::idxEdm4hep() const { return m_idxEdm4hep; } +int CommonUserTrackInfo::idxEdm4hep() const { return m_idxEdm4hep; } -inline int CommonUserTrackInfo::GetChronoTrackIdx() { - return m_chronoTrackIdx; -}; +int CommonUserTrackInfo::GetChronoTrackIdx() { return m_chronoTrackIdx; }; -inline void CommonUserTrackInfo::SetChronoTrackIdx(const int chronoTrackIdx) { +void CommonUserTrackInfo::SetChronoTrackIdx(const int chronoTrackIdx) { m_chronoTrackIdx = chronoTrackIdx; }; -inline uint8_t CommonUserTrackInfo::GetCurrentSubdet() const { +uint8_t CommonUserTrackInfo::GetCurrentSubdet() const { return m_currentSubdet; }; -inline bool CommonUserTrackInfo::IsSubdetChanged(const uint8_t newSubdet) { - return newSubdet != m_currentSubdet; -}; - -inline void CommonUserTrackInfo::SetCurrentSubdet(const uint8_t newSubdet) { - m_currentSubdet = newSubdet; - AddSubdet(newSubdet); -}; - -inline void CommonUserTrackInfo::SetStepNum(const int newStepNum) { - m_currentStepNum = newStepNum; -}; - -inline void -CommonUserTrackInfo::UpdateTrackInfo(const NanoClock::time_point &stop, - const int currentStep) { - m_trackTimePerSubdet[m_currentSubdet] += - NanoClock::duration(stop - m_trackSubdetChangeTime).count(); - m_trackStepPerSubdet[m_currentSubdet] += currentStep - m_currentStepNum; -} - -inline CommonUserTrackInfo::NanoClock::time_point +CommonUserTrackInfo::NanoClock::time_point CommonUserTrackInfo::GetTrackStartTime() const { return m_trackStartTime; } -inline CommonUserTrackInfo::NanoClock::time_point +CommonUserTrackInfo::NanoClock::time_point CommonUserTrackInfo::GetTrackSubdetChangeTime() const { return m_trackSubdetChangeTime; } -inline const std::array<unsigned long long, - CommonUserTrackInfo::MAX_SUBDET_NUM> & +const std::array<unsigned long long, CommonUserTrackInfo::MAX_SUBDET_NUM> & CommonUserTrackInfo::GetTrackTimePerSubdet() const { return m_trackTimePerSubdet; } -inline const std::array<int, CommonUserTrackInfo::MAX_SUBDET_NUM> & +const std::array<int, CommonUserTrackInfo::MAX_SUBDET_NUM> & CommonUserTrackInfo::GetTrackStepPerSubdet() const { return m_trackStepPerSubdet; } -inline void -CommonUserTrackInfo::SetTrackStartTime(const NanoClock::time_point &time) { +void CommonUserTrackInfo::SetTrackStartTime(const NanoClock::time_point &time) { m_trackStartTime = time; } -inline void CommonUserTrackInfo::SetTrackSubdetChangeTime( - const NanoClock::time_point &time) { - m_trackSubdetChangeTime = time; -} - -inline const std::array<unsigned long long, - CommonUserTrackInfo::MAX_SUBDET_SEQUENCE_NUM> & +const std::array<unsigned long long, + CommonUserTrackInfo::MAX_SUBDET_SEQUENCE_NUM> & CommonUserTrackInfo::GetTrackSubdetSequence() const { return m_trackSubdetSequence; } -inline int CommonUserTrackInfo::GetNumSubdet() const { - return m_currentSubdetNum; -}; - -inline void CommonUserTrackInfo::AddSubdet(const uint8_t subdet) { - static constexpr int kSlotsPerULL = 64 / 5; - - if (m_currentSubdetNum >= MAX_SUBDET_SEQUENCE_NUM * kSlotsPerULL) { - std::cerr - << "CommonUserTrackInfo::SetNthSubdet: error! subdet num overflow!" - << std::endl; - return; - } - // æ¯ä¸ªunsigned long longå¯ä»¥å˜å‚¨12个5bit值(64/5=12) - const int array_idx = m_currentSubdetNum / kSlotsPerULL; - // 在当å‰å…ƒç´ ä¸çš„bitä½ç½® - const int bit_pos = (m_currentSubdetNum % kSlotsPerULL) * 5; - - // ç¡®ä¿subdet值ä¸è¶…过5bit范围 - uint8_t masked_subdet = subdet & 0x1F; // 0x1F = 0b11111 - - // 清除原有ä½ç½®çš„值并写入新值 - m_trackSubdetSequence[array_idx] &= ~(0x1FULL << bit_pos); - m_trackSubdetSequence[array_idx] |= (masked_subdet & 0x1FULL) << bit_pos; - - m_currentSubdetNum++; -}; \ No newline at end of file +int CommonUserTrackInfo::GetNumSubdet() const { return m_currentSubdetNum; }; -- GitLab From 74d154ef538254cd58fa2e90202905bd28623d71 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 13:01:40 +0800 Subject: [PATCH 60/74] fix: chronoTrackIdx start from -1 --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 3 ++- .../include/DetSimInterface/CommonUserTrackInfo.hh | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 67ded825..4caeb644 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -216,7 +216,8 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { int chronoTrackIdx = info->GetChronoTrackIdx(); if (chronoTrackIdx < 0) { // new track - chronoTrackIdx = m_trackIdx++; // first copy then self-add + // first self-add then copy, for m_trackIdx start from -1 + chronoTrackIdx = ++m_trackIdx; info->SetChronoTrackIdx(chronoTrackIdx); const auto &mom = track->GetMomentum(); const auto &pos = track->GetPosition(); diff --git a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh index d61e14c9..b6d63767 100644 --- a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh +++ b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh @@ -79,7 +79,7 @@ public: }; inline void AddSubdet(const uint8_t subdet) { - static constexpr int kSlotsPerULL = 64 / 5; + static constexpr uint kSlotsPerULL = 64 / 5; if (m_currentSubdetNum >= MAX_SUBDET_SEQUENCE_NUM * kSlotsPerULL) { std::cerr @@ -88,9 +88,9 @@ public: return; } // æ¯ä¸ªunsigned long longå¯ä»¥å˜å‚¨12个5bit值(64/5=12) - const int array_idx = m_currentSubdetNum / kSlotsPerULL; + const uint array_idx = m_currentSubdetNum / kSlotsPerULL; // 在当å‰å…ƒç´ ä¸çš„bitä½ç½® - const int bit_pos = (m_currentSubdetNum % kSlotsPerULL) * 5; + const uint bit_pos = (m_currentSubdetNum % kSlotsPerULL) * 5; // ç¡®ä¿subdet值ä¸è¶…过5bit范围 uint8_t masked_subdet = subdet & 0x1F; // 0x1F = 0b11111 -- GitLab From 596b6c28d1c29d4f8cf3ecfb708cce1cc3e2e258 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 14:44:02 +0800 Subject: [PATCH 61/74] fix(Edm4hepWriter): add idxEdm4hep initialization check in track handling --- Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp | 6 +++--- .../include/DetSimInterface/CommonUserTrackInfo.hh | 9 +++++++-- Simulation/DetSimInterface/src/CommonUserTrackInfo.cc | 6 ------ 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp index 3139e2ef..19046c54 100644 --- a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp @@ -368,7 +368,7 @@ Edm4hepWriterAnaElemTool::PreUserTrackingAction(const G4Track* track) { // If it is associated, then we will record this info. if (not m_istrk2primary.value()) { auto trackinfo = dynamic_cast<CommonUserTrackInfo*>(track->GetUserInformation()); - if (trackinfo) { + if (trackinfo && trackinfo->IsIdxEdm4hepInited()) { curparid = 0; // force to zero, so that it will be set as primary } } @@ -437,7 +437,7 @@ Edm4hepWriterAnaElemTool::PostUserTrackingAction(const G4Track* track) { if (idxedm4hep == -1) { auto trackinfo = dynamic_cast<CommonUserTrackInfo*>(track->GetUserInformation()); - if (trackinfo) { + if (trackinfo && trackinfo->IsIdxEdm4hepInited()) { idxedm4hep = trackinfo->idxEdm4hep(); // if the current track is a secondary track and it is associated // with a MCParticle, we need to update the event level user info @@ -591,7 +591,7 @@ Edm4hepWriterAnaElemTool::UserSteppingAction(const G4Step* aStep) { // Note: // if there is no track info, then do nothing. // ======================================================================== - if (trackinfo) { + if (trackinfo && trackinfo->IsIdxEdm4hepInited()) { // back scattering is defined as following: // - pre point is not in tracker // - post point is in tracker diff --git a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh index b6d63767..49b4e5d9 100644 --- a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh +++ b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh @@ -31,8 +31,12 @@ public: virtual void Print() const; // get the idx in the EDM4hep MC particle collection - bool setIdxEdm4hep(int idxEdm4hep); - int idxEdm4hep() const; + inline void setIdxEdm4hep(int idxEdm4hep) { + m_idxEdm4hep = idxEdm4hep; + m_idxEdm4hepInited = true; + }; + inline int idxEdm4hep() const { return m_idxEdm4hep; }; + inline bool IsIdxEdm4hepInited() const { return m_idxEdm4hepInited; }; int GetChronoTrackIdx(); void SetChronoTrackIdx(const int chronoTrackIdx); @@ -53,6 +57,7 @@ public: private: int m_idxEdm4hep = -1; + bool m_idxEdm4hepInited = false; int m_chronoTrackIdx = -1; uint8_t m_currentSubdet = 0; int m_currentStepNum = 0; diff --git a/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc b/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc index d83f53d5..84bcddb2 100644 --- a/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc +++ b/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc @@ -6,12 +6,6 @@ CommonUserTrackInfo::~CommonUserTrackInfo() {} void CommonUserTrackInfo::Print() const {} -bool CommonUserTrackInfo::setIdxEdm4hep(int idxEdm4hep) { - m_idxEdm4hep = idxEdm4hep; -} - -int CommonUserTrackInfo::idxEdm4hep() const { return m_idxEdm4hep; } - int CommonUserTrackInfo::GetChronoTrackIdx() { return m_chronoTrackIdx; }; void CommonUserTrackInfo::SetChronoTrackIdx(const int chronoTrackIdx) { -- GitLab From 342097d11c5df9118b63610eeb8fb39b0ab6cad6 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 14:44:24 +0800 Subject: [PATCH 62/74] fix: change name not shadow --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 87 ++++++++++--------- 1 file changed, 46 insertions(+), 41 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 4caeb644..c501eee7 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -31,28 +31,28 @@ StatusCode ChronoAnaElemTool::initSubdetVolumes() { ->GetNavigatorForTracking() ->GetWorldVolume(); auto num_dau = world_vol->GetLogicalVolume()->GetNoDaughters(); - // debug() << "World Physical Volume - Name: " << world_vol->GetName() - // << " Pointer: " << world_vol << " World Logical Volume - Name: " - // << world_vol->GetLogicalVolume()->GetName() - // << " Pointer: " << world_vol->GetLogicalVolume() << endmsg; + debug() << "World Physical Volume - Name: " << world_vol->GetName() + << " Pointer: " << world_vol << " World Logical Volume - Name: " + << world_vol->GetLogicalVolume()->GetName() + << " Pointer: " << world_vol->GetLogicalVolume() << endmsg; m_logicalVolumePtrToSubdetIdx[world_vol->GetLogicalVolume()] = PWorldIndex; - // debug() << "Set m_logicalVolumePtrToSubdetIdx[" - // << world_vol->GetLogicalVolume() << "] to subdet index " - // << PWorldIndex << endmsg; + debug() << "Set m_logicalVolumePtrToSubdetIdx[" + << world_vol->GetLogicalVolume() << "] to subdet index " + << PWorldIndex << endmsg; for (size_t _dau = 0; _dau < num_dau; ++_dau) { auto dau_vol = world_vol->GetLogicalVolume()->GetDaughter(_dau); - // debug() << "Daughter Physical Volume - Name: " << dau_vol->GetName() - // << " Pointer: " << dau_vol << " Daughter Logical Volume - Name: " - // << dau_vol->GetLogicalVolume()->GetName() - // << " Pointer: " << dau_vol->GetLogicalVolume() << endmsg; + debug() << "Daughter Physical Volume - Name: " << dau_vol->GetName() + << " Pointer: " << dau_vol << " Daughter Logical Volume - Name: " + << dau_vol->GetLogicalVolume()->GetName() + << " Pointer: " << dau_vol->GetLogicalVolume() << endmsg; auto dau_name = dau_vol->GetName(); for (uint8_t _subdet = PWorldIndex; _subdet < m_subdetNames.size(); ++_subdet) { if (dau_name.find(m_subdetNames[_subdet]) != std::string::npos) { m_logicalVolumePtrToSubdetIdx[dau_vol->GetLogicalVolume()] = _subdet; - // debug() << "Set m_logicalVolumePtrToSubdetIdx[" - // << dau_vol->GetLogicalVolume() << "] to subdet index " - // << _subdet << endmsg; + debug() << "Set m_logicalVolumePtrToSubdetIdx[" + << dau_vol->GetLogicalVolume() << "] to subdet index " + << _subdet << endmsg; continue; } } @@ -206,19 +206,22 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { } // ensure info exists - auto info = static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); - if (!info) { - info = new CommonUserTrackInfo(); - track->SetUserInformation(info); + auto trackInfo = + static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); + if (!trackInfo) { + trackInfo = new CommonUserTrackInfo(); + track->SetUserInformation(trackInfo); + info() << "initialize new user track info " << track->GetTrackID() + << endmsg; } auto currentSubdet = getSubdetNameIdx(track->GetTouchable()); // æ ¹æ®å·²æœ‰çš„ chronoTrackIdx åˆ¤æ–æ˜¯æ–° track 还是 resumed - int chronoTrackIdx = info->GetChronoTrackIdx(); + int chronoTrackIdx = trackInfo->GetChronoTrackIdx(); if (chronoTrackIdx < 0) { // new track - // first self-add then copy, for m_trackIdx start from -1 - chronoTrackIdx = ++m_trackIdx; - info->SetChronoTrackIdx(chronoTrackIdx); + // first self-add then copy, for m_trackIdx start from 0 + chronoTrackIdx = m_trackIdx++; + trackInfo->SetChronoTrackIdx(chronoTrackIdx); const auto &mom = track->GetMomentum(); const auto &pos = track->GetPosition(); m_trackPx[chronoTrackIdx] = mom.x(); @@ -231,15 +234,15 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_trackPDGId[chronoTrackIdx] = track->GetParticleDefinition()->GetParticleDefinitionID(); m_trackStartSubdet[chronoTrackIdx] = currentSubdet; - info->SetStepNum(track->GetCurrentStepNumber()); - info->SetCurrentSubdet(currentSubdet); + trackInfo->SetStepNum(track->GetCurrentStepNumber()); + trackInfo->SetCurrentSubdet(currentSubdet); } else { // resumed track - error() << "resumed track!!! TrackIdx=" << chronoTrackIdx << endmsg; + error() << "Resumed track!!! TrackIdx=" << chronoTrackIdx << endmsg; } const auto start = NanoClock::now(); - info->SetTrackStartTime(start); - info->SetTrackSubdetChangeTime(start); + trackInfo->SetTrackStartTime(start); + trackInfo->SetTrackSubdetChangeTime(start); } void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { @@ -248,29 +251,30 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { } auto trackStop = NanoClock::now(); - auto info = static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); - auto chronoTrackIdx = info->GetChronoTrackIdx(); + auto trackInfo = + static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); + auto chronoTrackIdx = trackInfo->GetChronoTrackIdx(); auto currentStep = track->GetCurrentStepNumber(); // record value m_trackdE[chronoTrackIdx] = track->GetTotalEnergy() - m_trackE[chronoTrackIdx]; m_trackTime[chronoTrackIdx] += - NanoClock::duration(trackStop - info->GetTrackStartTime()).count(); + NanoClock::duration(trackStop - trackInfo->GetTrackStartTime()).count(); auto track_end_subdet = getSubdetNameIdx(track->GetTouchable()); m_trackLength[chronoTrackIdx] = track->GetTrackLength(); m_trackStepNum[chronoTrackIdx] = currentStep; m_trackEndSubdet[chronoTrackIdx] = track_end_subdet; // add remained time - info->UpdateTrackInfo(trackStop, currentStep); - const auto trackStepPerSubdet = info->GetTrackStepPerSubdet(); - const auto trackTimePerSubdet = info->GetTrackTimePerSubdet(); + trackInfo->UpdateTrackInfo(trackStop, currentStep); + const auto trackStepPerSubdet = trackInfo->GetTrackStepPerSubdet(); + const auto trackTimePerSubdet = trackInfo->GetTrackTimePerSubdet(); for (size_t i = 0; i < MAX_SUBDET_NUM; i++) { m_trackTimePerSubdet[chronoTrackIdx][i] = trackTimePerSubdet[i]; m_trackStepPerSubdet[chronoTrackIdx][i] = trackStepPerSubdet[i]; } - const auto trackSubdetSequence = info->GetTrackSubdetSequence(); - m_trackNumSubdet[chronoTrackIdx] = info->GetNumSubdet(); + const auto trackSubdetSequence = trackInfo->GetTrackSubdetSequence(); + m_trackNumSubdet[chronoTrackIdx] = trackInfo->GetNumSubdet(); for (size_t i = 0; i < MAX_SUBDET_SEQUENCE_NUM; i++) { m_trackSubdetSequence[chronoTrackIdx][i] = trackSubdetSequence[i]; } @@ -285,15 +289,16 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { if (stepStatus == fGeomBoundary || stepStatus == fWorldBoundary) { // last step in a volume or world const auto &track = step->GetTrack(); - auto info = static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); + auto trackInfo = + static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); auto newSubdet = getSubdetNameIdx(track->GetNextTouchable()); - if (info->IsSubdetChanged(newSubdet)) { + if (trackInfo->IsSubdetChanged(newSubdet)) { auto stop = NanoClock::now(); - info->SetCurrentSubdet(newSubdet); + trackInfo->SetCurrentSubdet(newSubdet); auto currentStep = track->GetCurrentStepNumber(); - info->UpdateTrackInfo(stop, currentStep); - info->SetStepNum(currentStep); - info->SetTrackSubdetChangeTime(stop); + trackInfo->UpdateTrackInfo(stop, currentStep); + trackInfo->SetStepNum(currentStep); + trackInfo->SetTrackSubdetChangeTime(stop); } } } -- GitLab From c01d0d80c7e935aea723e53343e059bc4ae0c325 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 14:53:23 +0800 Subject: [PATCH 63/74] fix: remove frequent log --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index c501eee7..bd0ba285 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -211,8 +211,8 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { if (!trackInfo) { trackInfo = new CommonUserTrackInfo(); track->SetUserInformation(trackInfo); - info() << "initialize new user track info " << track->GetTrackID() - << endmsg; + // debug() << "initialize new user track info " << track->GetTrackID() + // << endmsg; } auto currentSubdet = getSubdetNameIdx(track->GetTouchable()); // æ ¹æ®å·²æœ‰çš„ chronoTrackIdx åˆ¤æ–æ˜¯æ–° track 还是 resumed -- GitLab From 515df98b91d0edf5c4c00b45da38f8ee7a19409f Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 15:06:16 +0800 Subject: [PATCH 64/74] fix: add doc --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index bd0ba285..8e04d84f 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -209,6 +209,7 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { auto trackInfo = static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); if (!trackInfo) { + // ä¸å½±å“,edm4heptool设置trackinfo是secondary,secondaryçš„preä¸ä¼šæ¯”primaryçš„postæ—© trackInfo = new CommonUserTrackInfo(); track->SetUserInformation(trackInfo); // debug() << "initialize new user track info " << track->GetTrackID() -- GitLab From 9c6fc18c1c7b00dd364086472eed03d85302454b Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 15:39:12 +0800 Subject: [PATCH 65/74] fix: enlarge subdet sequence --- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 2 +- .../include/DetSimInterface/CommonUserTrackInfo.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index ed8f4537..52e4ec46 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -80,7 +80,7 @@ private: static constexpr uint MAX_SUBDET_NUM = 26; NTuple::Matrix<time_t> m_trackTimePerSubdet; NTuple::Matrix<int> m_trackStepPerSubdet; - static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 10; + static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 100; NTuple::Array<int> m_trackNumSubdet; // 5bit for one subdet, uint64 for 12 subdets NTuple::Matrix<uint64_t> m_trackSubdetSequence; diff --git a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh index 49b4e5d9..b82d3b3f 100644 --- a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh +++ b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh @@ -23,7 +23,7 @@ class CommonUserTrackInfo : public G4VUserTrackInformation { public: using NanoClock = Gaudi::Timers::RdtscClock<std::chrono::nanoseconds>; static constexpr uint MAX_SUBDET_NUM = 26; - static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 10; + static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 100; CommonUserTrackInfo(); ~CommonUserTrackInfo(); -- GitLab From 86cf149f81c79caa61d2f4e35d65133e837dc898 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 9 Jun 2025 16:10:52 +0800 Subject: [PATCH 66/74] fix: remove cout --- .../include/DetSimInterface/CommonUserTrackInfo.hh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh index b82d3b3f..0004be9f 100644 --- a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh +++ b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh @@ -87,9 +87,9 @@ public: static constexpr uint kSlotsPerULL = 64 / 5; if (m_currentSubdetNum >= MAX_SUBDET_SEQUENCE_NUM * kSlotsPerULL) { - std::cerr - << "CommonUserTrackInfo::SetNthSubdet: error! subdet num overflow!" - << std::endl; + // std::cerr << "CommonUserTrackInfo::SetNthSubdet: error! subdet num " + // << m_currentSubdetNum << " overflow!" << std::endl; + m_currentSubdetNum++; return; } // æ¯ä¸ªunsigned long longå¯ä»¥å˜å‚¨12个5bit值(64/5=12) -- GitLab From 9e00639f8bdd3d73ba39a263d47ed60405ea32ba Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 10 Jun 2025 10:28:55 +0800 Subject: [PATCH 67/74] fix: update CurrentSubdet after UpdateTrackInfo --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 8e04d84f..39ad3a3c 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -295,11 +295,11 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { auto newSubdet = getSubdetNameIdx(track->GetNextTouchable()); if (trackInfo->IsSubdetChanged(newSubdet)) { auto stop = NanoClock::now(); - trackInfo->SetCurrentSubdet(newSubdet); auto currentStep = track->GetCurrentStepNumber(); trackInfo->UpdateTrackInfo(stop, currentStep); trackInfo->SetStepNum(currentStep); trackInfo->SetTrackSubdetChangeTime(stop); + trackInfo->SetCurrentSubdet(newSubdet); } } } -- GitLab From ca4e53c489d7ecb6787884fb0a97a1f250cdbbc8 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 10 Jun 2025 10:31:12 +0800 Subject: [PATCH 68/74] fix: SetCurrentSubdet after UpdateTrackInfo --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 39ad3a3c..d6d68c7b 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -297,9 +297,9 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { auto stop = NanoClock::now(); auto currentStep = track->GetCurrentStepNumber(); trackInfo->UpdateTrackInfo(stop, currentStep); + trackInfo->SetCurrentSubdet(newSubdet); trackInfo->SetStepNum(currentStep); trackInfo->SetTrackSubdetChangeTime(stop); - trackInfo->SetCurrentSubdet(newSubdet); } } } -- GitLab From cb3413af7a22fbc7d622e4134f223f3b7c66e710 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 10 Jun 2025 11:54:50 +0800 Subject: [PATCH 69/74] fix: subdet num error --- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 2 +- .../include/DetSimInterface/CommonUserTrackInfo.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 52e4ec46..0bb3e675 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -77,7 +77,7 @@ private: NTuple::Array<time_t> m_trackTime; NTuple::Array<uint8_t> m_trackStartSubdet, m_trackEndSubdet; - static constexpr uint MAX_SUBDET_NUM = 26; + static constexpr uint MAX_SUBDET_NUM = 27; NTuple::Matrix<time_t> m_trackTimePerSubdet; NTuple::Matrix<int> m_trackStepPerSubdet; static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 100; diff --git a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh index 0004be9f..60f1e5c2 100644 --- a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh +++ b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh @@ -22,7 +22,7 @@ class CommonUserTrackInfo : public G4VUserTrackInformation { public: using NanoClock = Gaudi::Timers::RdtscClock<std::chrono::nanoseconds>; - static constexpr uint MAX_SUBDET_NUM = 26; + static constexpr uint MAX_SUBDET_NUM = 27; static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 100; CommonUserTrackInfo(); ~CommonUserTrackInfo(); -- GitLab From 5e7055802a80ef0158d193b597f117ab84c98a71 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Tue, 10 Jun 2025 15:39:04 +0800 Subject: [PATCH 70/74] fix: get real pdgid --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index d6d68c7b..5405d0d1 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -233,7 +233,7 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { m_trackZ[chronoTrackIdx] = pos.z(); m_trackE[chronoTrackIdx] = track->GetTotalEnergy(); m_trackPDGId[chronoTrackIdx] = - track->GetParticleDefinition()->GetParticleDefinitionID(); + track->GetParticleDefinition()->GetPDGEncoding(); m_trackStartSubdet[chronoTrackIdx] = currentSubdet; trackInfo->SetStepNum(track->GetCurrentStepNumber()); trackInfo->SetCurrentSubdet(currentSubdet); -- GitLab From b65d30726286f80e0e2153012ac04f3da5c6506e Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Thu, 12 Jun 2025 21:46:02 +0800 Subject: [PATCH 71/74] fix: add track length per subdet --- Simulation/DetSimAna/src/ChronoAnaElemTool.cpp | 16 +++++++++++++--- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 1 + .../DetSimInterface/CommonUserTrackInfo.hh | 12 +++++++++++- .../DetSimInterface/src/CommonUserTrackInfo.cc | 5 +++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 5405d0d1..3481a186 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -140,6 +140,10 @@ StatusCode ChronoAnaElemTool::initNtuple() { ->addIndexedItem("TrackStepPerSubdet", m_trackIdx, MAX_SUBDET_NUM, m_trackStepPerSubdet) .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("TrackLengthPerSubdet", m_trackIdx, + MAX_SUBDET_NUM, m_trackLengthPerSubdet) + .isSuccess(); suc &= m_ntuple ->addIndexedItem("TrackNumSubdet", m_trackIdx, m_trackNumSubdet) @@ -236,6 +240,7 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { track->GetParticleDefinition()->GetPDGEncoding(); m_trackStartSubdet[chronoTrackIdx] = currentSubdet; trackInfo->SetStepNum(track->GetCurrentStepNumber()); + trackInfo->SetTrackLength(track->GetTrackLength()); trackInfo->SetCurrentSubdet(currentSubdet); } else { // resumed track @@ -256,6 +261,7 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); auto chronoTrackIdx = trackInfo->GetChronoTrackIdx(); auto currentStep = track->GetCurrentStepNumber(); + auto currentTrackLength = track->GetTrackLength(); // record value m_trackdE[chronoTrackIdx] = @@ -263,16 +269,18 @@ void ChronoAnaElemTool::PostUserTrackingAction(const G4Track *track) { m_trackTime[chronoTrackIdx] += NanoClock::duration(trackStop - trackInfo->GetTrackStartTime()).count(); auto track_end_subdet = getSubdetNameIdx(track->GetTouchable()); - m_trackLength[chronoTrackIdx] = track->GetTrackLength(); + m_trackLength[chronoTrackIdx] = currentTrackLength; m_trackStepNum[chronoTrackIdx] = currentStep; m_trackEndSubdet[chronoTrackIdx] = track_end_subdet; // add remained time - trackInfo->UpdateTrackInfo(trackStop, currentStep); + trackInfo->UpdateTrackInfo(trackStop, currentStep, currentTrackLength); const auto trackStepPerSubdet = trackInfo->GetTrackStepPerSubdet(); const auto trackTimePerSubdet = trackInfo->GetTrackTimePerSubdet(); + const auto trackLenPerSubdet = trackInfo->GetTrackLengthPerSubdet(); for (size_t i = 0; i < MAX_SUBDET_NUM; i++) { m_trackTimePerSubdet[chronoTrackIdx][i] = trackTimePerSubdet[i]; m_trackStepPerSubdet[chronoTrackIdx][i] = trackStepPerSubdet[i]; + m_trackLengthPerSubdet[chronoTrackIdx][i] = trackLenPerSubdet[i]; } const auto trackSubdetSequence = trackInfo->GetTrackSubdetSequence(); m_trackNumSubdet[chronoTrackIdx] = trackInfo->GetNumSubdet(); @@ -296,8 +304,10 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { if (trackInfo->IsSubdetChanged(newSubdet)) { auto stop = NanoClock::now(); auto currentStep = track->GetCurrentStepNumber(); - trackInfo->UpdateTrackInfo(stop, currentStep); + auto currentTrackLength = track->GetTrackLength(); + trackInfo->UpdateTrackInfo(stop, currentStep, currentTrackLength); trackInfo->SetCurrentSubdet(newSubdet); + trackInfo->SetTrackLength(currentTrackLength); trackInfo->SetStepNum(currentStep); trackInfo->SetTrackSubdetChangeTime(stop); } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 0bb3e675..1ae63488 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -80,6 +80,7 @@ private: static constexpr uint MAX_SUBDET_NUM = 27; NTuple::Matrix<time_t> m_trackTimePerSubdet; NTuple::Matrix<int> m_trackStepPerSubdet; + NTuple::Matrix<double> m_trackLengthPerSubdet; static constexpr uint MAX_SUBDET_SEQUENCE_NUM = 100; NTuple::Array<int> m_trackNumSubdet; // 5bit for one subdet, uint64 for 12 subdets diff --git a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh index 60f1e5c2..836e0b80 100644 --- a/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh +++ b/Simulation/DetSimInterface/include/DetSimInterface/CommonUserTrackInfo.hh @@ -54,6 +54,7 @@ public: int GetNumSubdet() const; const std::array<unsigned long long, MAX_SUBDET_SEQUENCE_NUM> & GetTrackSubdetSequence() const; + const std::array<double, MAX_SUBDET_NUM> &GetTrackLengthPerSubdet() const; private: int m_idxEdm4hep = -1; @@ -62,10 +63,12 @@ private: uint8_t m_currentSubdet = 0; int m_currentStepNum = 0; uint m_currentSubdetNum = 0; + double m_currentTrackLength = 0.0; NanoClock::time_point m_trackStartTime, m_trackSubdetChangeTime; std::array<unsigned long long, MAX_SUBDET_NUM> m_trackTimePerSubdet{}; std::array<int, MAX_SUBDET_NUM> m_trackStepPerSubdet{}; + std::array<double, MAX_SUBDET_NUM> m_trackLengthPerSubdet{}; std::array<unsigned long long, MAX_SUBDET_SEQUENCE_NUM> m_trackSubdetSequence{}; @@ -108,15 +111,22 @@ public: }; inline void UpdateTrackInfo(const NanoClock::time_point &stop, - const int currentStep) { + const int currentStep, + const double currentTrackLength) { m_trackTimePerSubdet[m_currentSubdet] += NanoClock::duration(stop - m_trackSubdetChangeTime).count(); m_trackStepPerSubdet[m_currentSubdet] += currentStep - m_currentStepNum; + m_trackLengthPerSubdet[m_currentSubdet] += + currentTrackLength - m_currentTrackLength; }; inline void SetStepNum(const int newStepNum) { m_currentStepNum = newStepNum; }; + + inline void SetTrackLength(const double newStepLen) { + m_currentTrackLength = newStepLen; + } }; #endif diff --git a/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc b/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc index 84bcddb2..cf90d9fc 100644 --- a/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc +++ b/Simulation/DetSimInterface/src/CommonUserTrackInfo.cc @@ -47,3 +47,8 @@ CommonUserTrackInfo::GetTrackSubdetSequence() const { } int CommonUserTrackInfo::GetNumSubdet() const { return m_currentSubdetNum; }; + +const std::array<double, CommonUserTrackInfo::MAX_SUBDET_NUM> & +CommonUserTrackInfo::GetTrackLengthPerSubdet() const { + return m_trackLengthPerSubdet; +} \ No newline at end of file -- GitLab From ebffda886641d8ecc877810289a2954724dba5d6 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Fri, 20 Jun 2025 16:56:27 +0800 Subject: [PATCH 72/74] fix: add simplified TPC and wrapped volume --- Detector/DetCRD/CMakeLists.txt | 2 + .../TPC_ModularEndcap_o1_v02_simplified.xml | 220 +++++++ .../TPC_ModularEndcap_o1_v02_wrap.xml | 220 +++++++ .../compact/TDR_o1_v01/TDR_o1_v01_noB.xml | 85 +++ .../TDR_o1_v01/TDR_o1_v01_simpleTPC.xml | 85 +++ .../compact/TDR_o1_v01/TDR_o1_v01_wrap.xml | 85 +++ .../TPC_ModularEndcap_o1_v01_simplified.cpp | 557 +++++++++++++++++ .../TPC_ModularEndcap_o1_v01_wrapvolume.cpp | 582 ++++++++++++++++++ 8 files changed, 1836 insertions(+) create mode 100644 Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v02_simplified.xml create mode 100644 Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v02_wrap.xml create mode 100644 Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_noB.xml create mode 100644 Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_simpleTPC.xml create mode 100644 Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_wrap.xml create mode 100644 Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01_simplified.cpp create mode 100644 Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01_wrapvolume.cpp diff --git a/Detector/DetCRD/CMakeLists.txt b/Detector/DetCRD/CMakeLists.txt index c71a0e02..7909ead5 100644 --- a/Detector/DetCRD/CMakeLists.txt +++ b/Detector/DetCRD/CMakeLists.txt @@ -31,6 +31,8 @@ gaudi_add_module(DetCRD src/Tracker/SiTrackerComposite_v03_geo.cpp src/Tracker/TPC_Simple_o1_v01.cpp src/Tracker/TPC_ModularEndcap_o1_v01.cpp + src/Tracker/TPC_ModularEndcap_o1_v01_simplified.cpp + src/Tracker/TPC_ModularEndcap_o1_v01_wrapvolume.cpp src/Tracker/SiTracker_itkbarrel_v01_geo.cpp src/Tracker/SiTracker_itkbarrel_v02_geo.cpp src/Tracker/SiTracker_otkbarrel_v01_geo.cpp diff --git a/Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v02_simplified.xml b/Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v02_simplified.xml new file mode 100644 index 00000000..799174a9 --- /dev/null +++ b/Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v02_simplified.xml @@ -0,0 +1,220 @@ +<lccdd> + <info + name ="TPC_ModularEndcap_TDR_o1_v02" + status ="developing" + version = "TPC_ModularEndcap_TDR_o1_v02" + author = "Xin She"> + <comment> The compact format for the CEPC TPC used for the TDR </comment> + </info> + + <define> + <!--from CDR baseline--> + <!--Readout pad size, clustering in each 10 rows--> + <constant name="TPC_pad_height" value="5.0*mm" /> + <constant name="TPC_pad_width" value="0.5*mm" /> + <constant name="TPC_max_step_length" value="5*mm" /> + <constant name="TPC_sensitive_threshold_eV" value="32*eV" /> + <!--Wall/Cathode/Readout/Endplate--> + <constant name="TPC_dr_InnerWall" value="25.*mm" /> + <constant name="TPC_dr_InnerServiceArea" value="10*mm" /> + <constant name="TPC_dr_OuterServiceArea" value="23*mm" /> + <constant name="TPC_dr_OuterWall" value="25.*mm" /> + <constant name="TPC_dz_Cathode" value="0.06*mm" /> + <constant name="TPC_dz_Readout" value="3.50*mm" /> + <constant name="TPC_dz_Endplate" value="135*mm" /> + <constant name="TPC_dz_Cathode_Insulator" value="0.0275*mm" /> + <constant name="TPC_dz_Cathode_Conductor" value="0.0025*mm" /> + <constant name="TPC_dr_Cathode_Grip" value="10.*mm" /> + <constant name="TPC_dz_Cathode_Grip" value="15*mm" /> + <!-- Inermeidate variables --> + <constant name="TPC_rMin_GasVolume" value="TPC_inner_radius+TPC_dr_InnerWall"/> + <constant name="TPC_rMax_GasVolume" value="TPC_outer_radius-TPC_dr_OuterWall"/> + <constant name="TPC_dz_GasVolume" value="TPC_half_length-TPC_dz_Endplate"/> + <constant name="TPC_rMin_Sensitive" value="TPC_rMin_GasVolume+TPC_dr_InnerServiceArea"/> + <constant name="TPC_rMax_Sensitive" value="TPC_rMax_GasVolume-TPC_dr_OuterServiceArea"/> + <constant name="TPC_dz_Wall" value="2*TPC_dz_GasVolume"/> + <constant name="TPC_dz_Sensitive" value="TPC_dz_GasVolume-TPC_dz_Readout-TPC_dz_Cathode/2."/> + <constant name="TPC_numberOfPadrows" value="int((TPC_rMax_Sensitive-TPC_rMin_Sensitive)/TPC_pad_height)"/> + </define> + + <display> + <vis name="CuVis" alpha="1.0" r="0.5" g=".5" b=".5" showDaughters="true" visible="true"/> + <vis name="KaptonVis" alpha="0.8" r="1" g="0." b="0." showDaughters="true" visible="true"/> + <vis name="gasVis" alpha="0.2" r="0.0" g="1.0" b="0.0" showDaughters="true" visible="true"/> + <vis name="transVis" alpha="0.1" r="1.0" g="1.0" b="1.0" showDaughters="true" visible="true"/> + <vis name="readoutVis" alpha="0.8" r="1.0" g=".0" b=".0" showDaughters="true" visible="true"/> + <vis name="aramidVis" alpha="1.0" r="0.0" g="0.3" b="0.7" showDaughters="true" visible="true"/> + <vis name="epoxyVis" alpha="0.2" r="0.0" g="0.3" b="0.3" showDaughters="true" visible="true"/> + <vis name="TPCMotherVis1" alpha="0.5" r="0.96" g="0.64" b="0.90" showDaughters="true" visible="true"/> + </display> + + <detectors> + <detector name="TPC" type="TPC_ModularEndcap_o1_v01_simplified" vis="TPCVis" id="DetID_TPC" limits="tpc_limits" readout="TPCCollection" insideTrackingVolume="true"> + + <envelope vis="TPCVis"> + <shape type="Tube" rmin="TPC_inner_radius" rmax="TPC_outer_radius" dz="TPC_half_length" material="Air"/> + </envelope> + + <type_flags type="DetType_TRACKER + DetType_BARREL + DetType_GASEOUS "/> + + <component name="TPCinnerWall" type="TPCinnerWall" R_start="TPC_inner_radius" R_end="TPC_rMin_GasVolume" Z_fulllength="TPC_dz_Wall" vis="SeeThrough"> + <!--HoneyComb wall --> + <!--layer material="G4_Cu" thickness = "0.01*mm" vis="CuVis" /> + <layer material="Kapton" thickness = "0.05*mm" vis="KaptonVis" /> + <layer material="g10-TPC" thickness = "0.3*mm" vis="gasVis" /> + <layer material="Aramid" thickness = "0.07*mm" vis="aramidVis" /> + <layer material="AramidHoneycomb" thickness = "23.5*mm" vis="aramidVis" /> + <layer material="g10-TPC" thickness = "0.3*mm" vis="gasVis" /> + <layer material="Kapton" thickness = "0.0125*mm" vis="KaptonVis" /> + <layer material="Copper80P" thickness = "0.035*mm" vis="CuVis" /> + <layer material="Kapton" thickness = "0.05*mm" vis="KaptonVis" /> + <layer material="Copper80P" thickness = "0.035*mm" vis="CuVis" /> + <layer material="epoxy" thickness = "0.042*mm" vis="epoxy" /--> + <!--CF wall --> + <layer material="G4_Cu" thickness = "0.010*mm" vis="CuVis"/> + <layer material="CarbonFiber" thickness = "0.1*mm" vis="aramidVis"/> + <layer material="G4_Cu" thickness = "0.03*mm" vis="CuVis"/> + <layer material="Polyimide" thickness = "0.05*mm" vis="KaptonVis"/> + <layer material="G4_Cu" thickness = "0.03*mm" vis="CuVis"/> + <layer material="CarbonFiber" thickness = "0.1*mm" vis="aramidVis"/> + </component> + <component name="TPCouterWall" type="TPCouterWall" R_start="TPC_rMax_GasVolume" R_end="TPC_outer_radius" Z_fulllength="TPC_dz_Wall" vis="SeeThrough"> + <!--HoneyComb wall --> + <!--layer material="Copper80P" thickness = "0.01*mm" vis="CuVis" /> + <layer material="Kapton" thickness = "0.05*mm" vis="KaptonVis" /> + <layer material="Copper80P" thickness = "0.03*mm" vis="CuVis" /> + <layer material="Kapton" thickness = "0.07*mm" vis="KaptonVis" /> + <layer material="g10-TPC" thickness = "0.3*mm" vis="gasVis" /> + <layer material="AramidHoneycomb" thickness = "23.5*mm" vis="aramidVis" /> + <layer material="Aramid" thickness = "0.07*mm" vis="aramidVis" /> + <layer material="g10-TPC" thickness = "0.3*mm" vis="gasVis" /> + <layer material="Kapton" thickness = "0.05*mm" vis="KaptonVis" /> + <layer material="G4_Cu" thickness = "0.01*mm" vis="CuVis" /> + <layer material="epoxy" thickness = "0.042*mm" vis="epoxy" /--> + <!--CF wall --> + <layer material="CarbonFiber" thickness = "0.1*mm" vis="aramidVis"/> + <layer material="G4_Cu" thickness = "0.03*mm" vis="CuVis"/> + <layer material="Polyimide" thickness = "0.05*mm" vis="KaptonVis"/> + <layer material="G4_Cu" thickness = "0.03*mm" vis="CuVis"/> + <layer material="CarbonFiber" thickness = "0.1*mm" vis="aramidVis"/> + <layer material="G4_Cu" thickness = "0.010*mm" vis="CuVis"/> + </component> + <component name="Grip" type="TPCGrip" material="SiC_foam" vis="SeeThrough"> + <layer name="TPCinnerGrip" rmin="TPC_rMin_GasVolume" rmax="TPC_rMin_GasVolume+TPC_dr_InnerServiceArea" z_length="TPC_dz_Cathode_Grip" vis="KaptonVis"/> + <layer name="TPCouterGrip" rmin="TPC_rMax_GasVolume-TPC_dr_OuterServiceArea" rmax="TPC_rMax_GasVolume" z_length="TPC_dz_Cathode_Grip" vis="KaptonVis"/> + </component> + <component name="Cathode" type="TPCCathode" vis="SeeThrough"> + <layer name="Cathodeinsulator" material= "Kapton" rmin="TPC_rMin_Sensitive" rmax="TPC_rMax_Sensitive" z_length="TPC_dz_Cathode_Insulator" vis="KaptonVis"> + <position x="0.*mm" y="0.*mm" z="+ TPC_dz_Cathode_Insulator/2."/> + <position x="0.*mm" y="0.*mm" z="- TPC_dz_Cathode_Insulator/2."/> + </layer> + <layer name="Cathodeconductor" material= "G4_Cu" rmin="TPC_rMin_Sensitive" rmax="TPC_rMax_Sensitive" z_length="TPC_dz_Cathode_Conductor" vis="CuVis"> + <position x="0.*mm" y="0.*mm" z="+ (TPC_dz_Cathode_Insulator+ (TPC_dz_Cathode_Conductor/2.))"/> + <position x="0.*mm" y="0.*mm" z="- (TPC_dz_Cathode_Insulator+ (TPC_dz_Cathode_Conductor/2.))"/> + </layer> + </component> + <component name="TPCreadout" type="TPCreadout" material="T2KGas1" vis="SeeThrough"> + <dimensions rmin = "TPC_rMin_GasVolume" rmax = "TPC_rMax_GasVolume" z_length = "TPC_dz_Readout"/> + <position x="0.*mm" y="0.*mm" z="+(TPC_half_length-TPC_dz_Endplate-TPC_dz_Readout/2.)"/> + <!--Triple Gem readout structure from CEPCV4--> + <!--layer material="G4_Cu" dz="0.003*mm" comment="gating" vis="CuVis" /> + <layer material="G4_KAPTON" dz="0.030*mm" comment="gating" vis="KaptonVis" /> + <layer material="G4_Cu" dz="0.003*mm" comment="gating" vis="CuVis"/> + <layer material="T2KGas1" dz="4.447*mm" comment="gating" vis="gasVis"/> + <layer material="G4_Cu" dz="0.003*mm" comment="mpgd" vis="CuVis"/> + <layer material="G4_KAPTON" dz="0.030*mm" comment="mpgd" vis="Kapton"/> + <layer material="G4_Cu" dz="0.003*mm" comment="mpgd" vis="CuVis"/> + <layer material="T2KGas1" dz="4.447*mm" comment="mpgd" vis="gasVis"/> + <layer material="G4_Cu" dz="0.003*mm" comment="mpgd" vis="CuVis"/> + <layer material="G4_KAPTON" dz="0.030*mm" comment="mpgd" vis="KaptonVis"/> + <layer material="G4_Cu" dz="0.003*mm" comment="mpgd" vis="CuVis"/> + <layer material="T2KGas1" dz="4.447*mm" comment="mpgd" vis="gasVis"/> + <layer material="G4_Cu" dz="0.050*mm" comment="pads" vis="CuVis"/> + <layer material="g10" dz="2.000*mm" comment="structural" vis="gasVis"/> + <layer material="G4_Si" dz="0.500*mm" comment="electronics" vis="epoxyVis" /> + <layer material="epoxy" dz="2*mm" comment="structural" vis="epoxyVis"/> + <layer material="G4_KAPTON" dz="1*mm" comment="structural" vis="KaptonVis" /> + <layer material="G4_Al" dz="2*mm" comment="Cooling" vis="GrayVis"/> + <layer material="G4_KAPTON" dz="1*mm" comment="structural" vis="KaptonVis"/> + <layer material="CarbonFiber" dz="3*mm" comment="structural" vis="GrayVis" /--> + <!--MicroMegas readout structure--> + <layer material="G4_Fe" dz="0.025*mm" comment="Mesh" vis="GrayVis"/> + <layer material="T2KGas1" dz="0.128*mm" comment="GasAmpRegion" vis="gasVis"/> + <layer material="G4_KAPTON" dz="0.050*mm" comment="Kaptonfoil" vis="KaptonVis"/> + <layer material="Acrylicglue" dz="0.008*mm" comment="gule" vis="BlueVis"/> + <layer material="G4_Cu" dz="0.017*mm" comment="ReadoutPad" vis="CuVis"/> + <layer material="PCB" dz="1.000*mm" comment="PCBboard" vis="GreenVis"/> + <layer material="G4_Si" dz="0.500*mm" comment="electronics" vis="BlackVis"/> + <layer material="epoxy" dz="1.500*mm" comment="structural" vis="epoxyVis"/> + </component> + <component name="TPCSensitiveVol" type="TPCSensitiveVol" material="T2KGas1" vis="gasVis"> + <dimensions rmin = "TPC_rMin_Sensitive" rmax = "TPC_rMax_Sensitive" z_length = "TPC_dz_Sensitive"/> + <layer repeat="TPC_numberOfPadrows" thickness="TPC_pad_height"/> + </component> + <component name="TPCEndplate" type="TPCEndplate" z_frame="20.*mm" s_frame="20.*mm" vis="SeeThrough"> + <dimensions rmin = "TPC_inner_radius" rmax = "TPC_outer_radius" z_length = "TPC_dz_Endplate"/> + <layer name="InnerPlate" type="Frame" thickness="25.*mm"/> + <layer name="ring1" type="Frame" thickness="10.*mm"/> + <layer name="module1" type="Module" thickness="151.*mm" repeat="23" phi0_offset="0.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring2" type="Frame" thickness="20.*mm"/> + <layer name="module2" type="Module" thickness="141.*mm" repeat="27" phi0_offset="+10.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + <slice material="PCB" dz="10.0*mm" comment="cooling"/> + </layer> + <layer name="ring3" type="Frame" thickness="20.*mm"/> + <layer name="module3" type="Module" thickness="141.*mm" repeat="32" phi0_offset="-5.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring4" type="Frame" thickness="20.*mm"/> + <layer name="module4" type="Module" thickness="141.*mm" repeat="34" phi0_offset="0.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring5" type="Frame" thickness="20.*mm"/> + <layer name="module5" type="Module" thickness="141.*mm" repeat="39" phi0_offset="+5.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring6" type="Frame" thickness="20.*mm"/> + <layer name="module6" type="Module" thickness="141.*mm" repeat="44" phi0_offset="-5.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring7" type="Frame" thickness="20.*mm"/> + <layer name="module7" type="Module" thickness="141.*mm" repeat="49" phi0_offset="0.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring8" type="Frame" thickness="23.*mm"/> + <layer name="Outerplate" type="Frame" thickness="25.*mm"/> + </component> + + </detector> + </detectors> + + <readouts> + <readout name="TPCCollection"> + <id>system:5,side:-2,layer:13,module:6,sensor:6</id> + </readout> + </readouts> + +</lccdd> diff --git a/Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v02_wrap.xml b/Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v02_wrap.xml new file mode 100644 index 00000000..70049c1b --- /dev/null +++ b/Detector/DetCRD/compact/CRD_common_v02/TPC_ModularEndcap_o1_v02_wrap.xml @@ -0,0 +1,220 @@ +<lccdd> + <info + name ="TPC_ModularEndcap_TDR_o1_v02" + status ="developing" + version = "TPC_ModularEndcap_TDR_o1_v02" + author = "Xin She"> + <comment> The compact format for the CEPC TPC used for the TDR </comment> + </info> + + <define> + <!--from CDR baseline--> + <!--Readout pad size, clustering in each 10 rows--> + <constant name="TPC_pad_height" value="5.0*mm" /> + <constant name="TPC_pad_width" value="0.5*mm" /> + <constant name="TPC_max_step_length" value="5*mm" /> + <constant name="TPC_sensitive_threshold_eV" value="32*eV" /> + <!--Wall/Cathode/Readout/Endplate--> + <constant name="TPC_dr_InnerWall" value="25.*mm" /> + <constant name="TPC_dr_InnerServiceArea" value="10*mm" /> + <constant name="TPC_dr_OuterServiceArea" value="23*mm" /> + <constant name="TPC_dr_OuterWall" value="25.*mm" /> + <constant name="TPC_dz_Cathode" value="0.06*mm" /> + <constant name="TPC_dz_Readout" value="3.50*mm" /> + <constant name="TPC_dz_Endplate" value="135*mm" /> + <constant name="TPC_dz_Cathode_Insulator" value="0.0275*mm" /> + <constant name="TPC_dz_Cathode_Conductor" value="0.0025*mm" /> + <constant name="TPC_dr_Cathode_Grip" value="10.*mm" /> + <constant name="TPC_dz_Cathode_Grip" value="15*mm" /> + <!-- Inermeidate variables --> + <constant name="TPC_rMin_GasVolume" value="TPC_inner_radius+TPC_dr_InnerWall"/> + <constant name="TPC_rMax_GasVolume" value="TPC_outer_radius-TPC_dr_OuterWall"/> + <constant name="TPC_dz_GasVolume" value="TPC_half_length-TPC_dz_Endplate"/> + <constant name="TPC_rMin_Sensitive" value="TPC_rMin_GasVolume+TPC_dr_InnerServiceArea"/> + <constant name="TPC_rMax_Sensitive" value="TPC_rMax_GasVolume-TPC_dr_OuterServiceArea"/> + <constant name="TPC_dz_Wall" value="2*TPC_dz_GasVolume"/> + <constant name="TPC_dz_Sensitive" value="TPC_dz_GasVolume-TPC_dz_Readout-TPC_dz_Cathode/2."/> + <constant name="TPC_numberOfPadrows" value="int((TPC_rMax_Sensitive-TPC_rMin_Sensitive)/TPC_pad_height)"/> + </define> + + <display> + <vis name="CuVis" alpha="1.0" r="0.5" g=".5" b=".5" showDaughters="true" visible="true"/> + <vis name="KaptonVis" alpha="0.8" r="1" g="0." b="0." showDaughters="true" visible="true"/> + <vis name="gasVis" alpha="0.2" r="0.0" g="1.0" b="0.0" showDaughters="true" visible="true"/> + <vis name="transVis" alpha="0.1" r="1.0" g="1.0" b="1.0" showDaughters="true" visible="true"/> + <vis name="readoutVis" alpha="0.8" r="1.0" g=".0" b=".0" showDaughters="true" visible="true"/> + <vis name="aramidVis" alpha="1.0" r="0.0" g="0.3" b="0.7" showDaughters="true" visible="true"/> + <vis name="epoxyVis" alpha="0.2" r="0.0" g="0.3" b="0.3" showDaughters="true" visible="true"/> + <vis name="TPCMotherVis1" alpha="0.5" r="0.96" g="0.64" b="0.90" showDaughters="true" visible="true"/> + </display> + + <detectors> + <detector name="TPC" type="TPC_ModularEndcap_o1_v01_wrapvolume" vis="TPCVis" id="DetID_TPC" limits="tpc_limits" readout="TPCCollection" insideTrackingVolume="true"> + + <envelope vis="TPCVis"> + <shape type="Tube" rmin="TPC_inner_radius" rmax="TPC_outer_radius" dz="TPC_half_length" material="Air"/> + </envelope> + + <type_flags type="DetType_TRACKER + DetType_BARREL + DetType_GASEOUS "/> + + <component name="TPCinnerWall" type="TPCinnerWall" R_start="TPC_inner_radius" R_end="TPC_rMin_GasVolume" Z_fulllength="TPC_dz_Wall" vis="SeeThrough"> + <!--HoneyComb wall --> + <!--layer material="G4_Cu" thickness = "0.01*mm" vis="CuVis" /> + <layer material="Kapton" thickness = "0.05*mm" vis="KaptonVis" /> + <layer material="g10-TPC" thickness = "0.3*mm" vis="gasVis" /> + <layer material="Aramid" thickness = "0.07*mm" vis="aramidVis" /> + <layer material="AramidHoneycomb" thickness = "23.5*mm" vis="aramidVis" /> + <layer material="g10-TPC" thickness = "0.3*mm" vis="gasVis" /> + <layer material="Kapton" thickness = "0.0125*mm" vis="KaptonVis" /> + <layer material="Copper80P" thickness = "0.035*mm" vis="CuVis" /> + <layer material="Kapton" thickness = "0.05*mm" vis="KaptonVis" /> + <layer material="Copper80P" thickness = "0.035*mm" vis="CuVis" /> + <layer material="epoxy" thickness = "0.042*mm" vis="epoxy" /--> + <!--CF wall --> + <layer material="G4_Cu" thickness = "0.010*mm" vis="CuVis"/> + <layer material="CarbonFiber" thickness = "0.1*mm" vis="aramidVis"/> + <layer material="G4_Cu" thickness = "0.03*mm" vis="CuVis"/> + <layer material="Polyimide" thickness = "0.05*mm" vis="KaptonVis"/> + <layer material="G4_Cu" thickness = "0.03*mm" vis="CuVis"/> + <layer material="CarbonFiber" thickness = "0.1*mm" vis="aramidVis"/> + </component> + <component name="TPCouterWall" type="TPCouterWall" R_start="TPC_rMax_GasVolume" R_end="TPC_outer_radius" Z_fulllength="TPC_dz_Wall" vis="SeeThrough"> + <!--HoneyComb wall --> + <!--layer material="Copper80P" thickness = "0.01*mm" vis="CuVis" /> + <layer material="Kapton" thickness = "0.05*mm" vis="KaptonVis" /> + <layer material="Copper80P" thickness = "0.03*mm" vis="CuVis" /> + <layer material="Kapton" thickness = "0.07*mm" vis="KaptonVis" /> + <layer material="g10-TPC" thickness = "0.3*mm" vis="gasVis" /> + <layer material="AramidHoneycomb" thickness = "23.5*mm" vis="aramidVis" /> + <layer material="Aramid" thickness = "0.07*mm" vis="aramidVis" /> + <layer material="g10-TPC" thickness = "0.3*mm" vis="gasVis" /> + <layer material="Kapton" thickness = "0.05*mm" vis="KaptonVis" /> + <layer material="G4_Cu" thickness = "0.01*mm" vis="CuVis" /> + <layer material="epoxy" thickness = "0.042*mm" vis="epoxy" /--> + <!--CF wall --> + <layer material="CarbonFiber" thickness = "0.1*mm" vis="aramidVis"/> + <layer material="G4_Cu" thickness = "0.03*mm" vis="CuVis"/> + <layer material="Polyimide" thickness = "0.05*mm" vis="KaptonVis"/> + <layer material="G4_Cu" thickness = "0.03*mm" vis="CuVis"/> + <layer material="CarbonFiber" thickness = "0.1*mm" vis="aramidVis"/> + <layer material="G4_Cu" thickness = "0.010*mm" vis="CuVis"/> + </component> + <component name="Grip" type="TPCGrip" material="SiC_foam" vis="SeeThrough"> + <layer name="TPCinnerGrip" rmin="TPC_rMin_GasVolume" rmax="TPC_rMin_GasVolume+TPC_dr_InnerServiceArea" z_length="TPC_dz_Cathode_Grip" vis="KaptonVis"/> + <layer name="TPCouterGrip" rmin="TPC_rMax_GasVolume-TPC_dr_OuterServiceArea" rmax="TPC_rMax_GasVolume" z_length="TPC_dz_Cathode_Grip" vis="KaptonVis"/> + </component> + <component name="Cathode" type="TPCCathode" vis="SeeThrough"> + <layer name="Cathodeinsulator" material= "Kapton" rmin="TPC_rMin_Sensitive" rmax="TPC_rMax_Sensitive" z_length="TPC_dz_Cathode_Insulator" vis="KaptonVis"> + <position x="0.*mm" y="0.*mm" z="+ TPC_dz_Cathode_Insulator/2."/> + <position x="0.*mm" y="0.*mm" z="- TPC_dz_Cathode_Insulator/2."/> + </layer> + <layer name="Cathodeconductor" material= "G4_Cu" rmin="TPC_rMin_Sensitive" rmax="TPC_rMax_Sensitive" z_length="TPC_dz_Cathode_Conductor" vis="CuVis"> + <position x="0.*mm" y="0.*mm" z="+ (TPC_dz_Cathode_Insulator+ (TPC_dz_Cathode_Conductor/2.))"/> + <position x="0.*mm" y="0.*mm" z="- (TPC_dz_Cathode_Insulator+ (TPC_dz_Cathode_Conductor/2.))"/> + </layer> + </component> + <component name="TPCreadout" type="TPCreadout" material="T2KGas1" vis="SeeThrough"> + <dimensions rmin = "TPC_rMin_GasVolume" rmax = "TPC_rMax_GasVolume" z_length = "TPC_dz_Readout"/> + <position x="0.*mm" y="0.*mm" z="+(TPC_half_length-TPC_dz_Endplate-TPC_dz_Readout/2.)"/> + <!--Triple Gem readout structure from CEPCV4--> + <!--layer material="G4_Cu" dz="0.003*mm" comment="gating" vis="CuVis" /> + <layer material="G4_KAPTON" dz="0.030*mm" comment="gating" vis="KaptonVis" /> + <layer material="G4_Cu" dz="0.003*mm" comment="gating" vis="CuVis"/> + <layer material="T2KGas1" dz="4.447*mm" comment="gating" vis="gasVis"/> + <layer material="G4_Cu" dz="0.003*mm" comment="mpgd" vis="CuVis"/> + <layer material="G4_KAPTON" dz="0.030*mm" comment="mpgd" vis="Kapton"/> + <layer material="G4_Cu" dz="0.003*mm" comment="mpgd" vis="CuVis"/> + <layer material="T2KGas1" dz="4.447*mm" comment="mpgd" vis="gasVis"/> + <layer material="G4_Cu" dz="0.003*mm" comment="mpgd" vis="CuVis"/> + <layer material="G4_KAPTON" dz="0.030*mm" comment="mpgd" vis="KaptonVis"/> + <layer material="G4_Cu" dz="0.003*mm" comment="mpgd" vis="CuVis"/> + <layer material="T2KGas1" dz="4.447*mm" comment="mpgd" vis="gasVis"/> + <layer material="G4_Cu" dz="0.050*mm" comment="pads" vis="CuVis"/> + <layer material="g10" dz="2.000*mm" comment="structural" vis="gasVis"/> + <layer material="G4_Si" dz="0.500*mm" comment="electronics" vis="epoxyVis" /> + <layer material="epoxy" dz="2*mm" comment="structural" vis="epoxyVis"/> + <layer material="G4_KAPTON" dz="1*mm" comment="structural" vis="KaptonVis" /> + <layer material="G4_Al" dz="2*mm" comment="Cooling" vis="GrayVis"/> + <layer material="G4_KAPTON" dz="1*mm" comment="structural" vis="KaptonVis"/> + <layer material="CarbonFiber" dz="3*mm" comment="structural" vis="GrayVis" /--> + <!--MicroMegas readout structure--> + <layer material="G4_Fe" dz="0.025*mm" comment="Mesh" vis="GrayVis"/> + <layer material="T2KGas1" dz="0.128*mm" comment="GasAmpRegion" vis="gasVis"/> + <layer material="G4_KAPTON" dz="0.050*mm" comment="Kaptonfoil" vis="KaptonVis"/> + <layer material="Acrylicglue" dz="0.008*mm" comment="gule" vis="BlueVis"/> + <layer material="G4_Cu" dz="0.017*mm" comment="ReadoutPad" vis="CuVis"/> + <layer material="PCB" dz="1.000*mm" comment="PCBboard" vis="GreenVis"/> + <layer material="G4_Si" dz="0.500*mm" comment="electronics" vis="BlackVis"/> + <layer material="epoxy" dz="1.500*mm" comment="structural" vis="epoxyVis"/> + </component> + <component name="TPCSensitiveVol" type="TPCSensitiveVol" material="T2KGas1" vis="gasVis"> + <dimensions rmin = "TPC_rMin_Sensitive" rmax = "TPC_rMax_Sensitive" z_length = "TPC_dz_Sensitive"/> + <layer repeat="TPC_numberOfPadrows" thickness="TPC_pad_height"/> + </component> + <component name="TPCEndplate" type="TPCEndplate" z_frame="20.*mm" s_frame="20.*mm" vis="SeeThrough"> + <dimensions rmin = "TPC_inner_radius" rmax = "TPC_outer_radius" z_length = "TPC_dz_Endplate"/> + <layer name="InnerPlate" type="Frame" thickness="25.*mm"/> + <layer name="ring1" type="Frame" thickness="10.*mm"/> + <layer name="module1" type="Module" thickness="151.*mm" repeat="23" phi0_offset="0.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring2" type="Frame" thickness="20.*mm"/> + <layer name="module2" type="Module" thickness="141.*mm" repeat="27" phi0_offset="+10.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + <slice material="PCB" dz="10.0*mm" comment="cooling"/> + </layer> + <layer name="ring3" type="Frame" thickness="20.*mm"/> + <layer name="module3" type="Module" thickness="141.*mm" repeat="32" phi0_offset="-5.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring4" type="Frame" thickness="20.*mm"/> + <layer name="module4" type="Module" thickness="141.*mm" repeat="34" phi0_offset="0.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring5" type="Frame" thickness="20.*mm"/> + <layer name="module5" type="Module" thickness="141.*mm" repeat="39" phi0_offset="+5.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring6" type="Frame" thickness="20.*mm"/> + <layer name="module6" type="Module" thickness="141.*mm" repeat="44" phi0_offset="-5.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring7" type="Frame" thickness="20.*mm"/> + <layer name="module7" type="Module" thickness="141.*mm" repeat="49" phi0_offset="0.*deg"> + <slice material="PCB" dz="5.0*mm" comment="FEE_BEEPCB"/> + <slice material="G4_Al" dz="1.5*mm" comment="cooling"/> + <slice material="TPC_endplate_mix" dz="50.0*mm" comment="MonitorMix"/> + <slice material="CarbonFiber" dz="3.0*mm" comment="structural"/> + </layer> + <layer name="ring8" type="Frame" thickness="23.*mm"/> + <layer name="Outerplate" type="Frame" thickness="25.*mm"/> + </component> + + </detector> + </detectors> + + <readouts> + <readout name="TPCCollection"> + <id>system:5,side:-2,layer:13,module:6,sensor:6</id> + </readout> + </readouts> + +</lccdd> diff --git a/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_noB.xml b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_noB.xml new file mode 100644 index 00000000..17c87159 --- /dev/null +++ b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_noB.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd"> + <info name="TDR_o1_v01" + title="CepC reference detctor for TDR" + author="" + url="http://cepc.ihep.ac.cn" + status="developing" + version="v01"> + <comment>CepC reference detector simulation models used for TDR </comment> + </info> + + <includes> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/elements.xml"/> + <gdmlFile ref="../CRD_common_v02/materials.xml"/> + </includes> + + <define> + <constant name="world_size" value="10*m"/> + <constant name="world_x" value="world_size"/> + <constant name="world_y" value="world_size"/> + <constant name="world_z" value="world_size"/> + + <include ref="${DD4hepINSTALL}/DDDetectors/compact/detector_types.xml"/> + </define> + + <include ref="./TDR_Dimensions_v01_01.xml"/> + + <include ref="../CRD_common_v02/Beampipe_v01_07.xml"/> + <!--preliminary vertex and tracker, to update/--> + <!--include ref="../CRD_common_v02/VXD_StaggeredLadder_v02_01.xml"/--> + <include ref="../CRD_common_v02/VXD_Composite_v01_03.xml"/> + <!--include ref="../CRD_common_v02/FTD_SkewRing_v01_07.xml"/--> + <!--include ref="../CRD_common_v02/SIT_SimplePixel_v01_04.xml"/--> + <!--include ref="../CRD_common_v02/SIT_StaggeredStave_v02.xml"/--> + <include ref="../CRD_common_v02/ITK_StaggeredStave_v03_01.xml"/> + <include ref="../CRD_common_v02/ITK_EndCap_v01.xml"/> + <!--include ref="../CRD_common_v01/TPC_Simple_v10_02.xml"/--> + <!-- use 10 rows clustering version--> + <include ref="../CRD_common_v02/TPC_ModularEndcap_o1_v02.xml"/> + <!--include ref="../CRD_common_v01/SET_SimplePixel_v01_01.xml"/--> + <!--include ref="../CRD_common_v01/OTKBarrel_v01_01.xml"/--> + <include ref="../CRD_common_v01/OTKBarrel_v02.xml"/> + <!--include ref="../CRD_common_v01/OTKEndcap_v01_01.xml"/--> + <include ref="../CRD_common_v01/OTKEndcap_v02.xml"/> + + <include ref="../CRD_common_v01/Ecal_Crystal_Barrel_v02_02.xml"/> + <include ref="../CRD_common_v01/Ecal_Crystal_Endcap_v02_01.xml"/> + <include ref="../CRD_common_v01/SHcalGlass_Barrel_v05.xml"/> + <include ref="../CRD_common_v01/SHcalGlass_Endcaps_v01.xml"/> + + <!--Lumical to update--> + <include ref="../CRD_common_v01/Lumical_o1_v01.xml"/> + <!--preliminary Magnet, to update/--> + <include ref="../CRD_common_v02/Coil_Simple_v01_03.xml"/> + <!--preliminary Muon, obselete/--> + <!--include ref="../CRD_common_v02/Yoke_Polyhedra_Barrel_v01_01.xml"/> + <include ref="../CRD_common_v02/Yoke_Polyhedra_Endcaps_v01_01.xml"/--> + + <!--muon detector--> + <include ref="../CRD_common_v01/Muon_Barrel_v01_04.xml"/> + <include ref="../CRD_common_v01/Muon_Endcap_v01_02.xml"/> + <include ref="../CRD_common_v01/ParaffinEndcap_v01_01.xml"/> + <!--include ref="../CRD_common_v01/ConcreteWall_v01_01.xml"/--> + + <fields> + <field name="InnerSolenoid" type="solenoid" + inner_field="0" + outer_field="0" + zmax="SolenoidCoil_half_length" + inner_radius="SolenoidCoil_center_radius" + outer_radius="Solenoid_outer_radius"> + </field> + <!-- remove anti magnetic field in order to extrapolate to muon detector more easily--> + <!--field name="OuterSolenoid" type="solenoid" + inner_field="0" + outer_field="Field_outer_nominal_value" + zmax="SolenoidCoil_half_length" + inner_radius="Solenoid_outer_radius" + outer_radius="Yoke_barrel_inner_radius"> + </field--> + </fields> + +</lccdd> diff --git a/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_simpleTPC.xml b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_simpleTPC.xml new file mode 100644 index 00000000..af967012 --- /dev/null +++ b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_simpleTPC.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd"> + <info name="TDR_o1_v01" + title="CepC reference detctor for TDR" + author="" + url="http://cepc.ihep.ac.cn" + status="developing" + version="v01"> + <comment>CepC reference detector simulation models used for TDR </comment> + </info> + + <includes> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/elements.xml"/> + <gdmlFile ref="../CRD_common_v02/materials.xml"/> + </includes> + + <define> + <constant name="world_size" value="10*m"/> + <constant name="world_x" value="world_size"/> + <constant name="world_y" value="world_size"/> + <constant name="world_z" value="world_size"/> + + <include ref="${DD4hepINSTALL}/DDDetectors/compact/detector_types.xml"/> + </define> + + <include ref="./TDR_Dimensions_v01_01.xml"/> + + <include ref="../CRD_common_v02/Beampipe_v01_07.xml"/> + <!--preliminary vertex and tracker, to update/--> + <!--include ref="../CRD_common_v02/VXD_StaggeredLadder_v02_01.xml"/--> + <include ref="../CRD_common_v02/VXD_Composite_v01_03.xml"/> + <!--include ref="../CRD_common_v02/FTD_SkewRing_v01_07.xml"/--> + <!--include ref="../CRD_common_v02/SIT_SimplePixel_v01_04.xml"/--> + <!--include ref="../CRD_common_v02/SIT_StaggeredStave_v02.xml"/--> + <include ref="../CRD_common_v02/ITK_StaggeredStave_v03_01.xml"/> + <include ref="../CRD_common_v02/ITK_EndCap_v01.xml"/> + <!--include ref="../CRD_common_v01/TPC_Simple_v10_02.xml"/--> + <!-- use 10 rows clustering version--> + <include ref="../CRD_common_v02/TPC_ModularEndcap_o1_v02_simplified.xml"/> + <!--include ref="../CRD_common_v01/SET_SimplePixel_v01_01.xml"/--> + <!--include ref="../CRD_common_v01/OTKBarrel_v01_01.xml"/--> + <include ref="../CRD_common_v01/OTKBarrel_v02.xml"/> + <!--include ref="../CRD_common_v01/OTKEndcap_v01_01.xml"/--> + <include ref="../CRD_common_v01/OTKEndcap_v02.xml"/> + + <include ref="../CRD_common_v01/Ecal_Crystal_Barrel_v02_02.xml"/> + <include ref="../CRD_common_v01/Ecal_Crystal_Endcap_v02_01.xml"/> + <include ref="../CRD_common_v01/SHcalGlass_Barrel_v05.xml"/> + <include ref="../CRD_common_v01/SHcalGlass_Endcaps_v01.xml"/> + + <!--Lumical to update--> + <include ref="../CRD_common_v01/Lumical_o1_v01.xml"/> + <!--preliminary Magnet, to update/--> + <include ref="../CRD_common_v02/Coil_Simple_v01_03.xml"/> + <!--preliminary Muon, obselete/--> + <!--include ref="../CRD_common_v02/Yoke_Polyhedra_Barrel_v01_01.xml"/> + <include ref="../CRD_common_v02/Yoke_Polyhedra_Endcaps_v01_01.xml"/--> + + <!--muon detector--> + <include ref="../CRD_common_v01/Muon_Barrel_v01_04.xml"/> + <include ref="../CRD_common_v01/Muon_Endcap_v01_02.xml"/> + <include ref="../CRD_common_v01/ParaffinEndcap_v01_01.xml"/> + <!--include ref="../CRD_common_v01/ConcreteWall_v01_01.xml"/--> + + <fields> + <field name="InnerSolenoid" type="solenoid" + inner_field="Field_nominal_value" + outer_field="0" + zmax="SolenoidCoil_half_length" + inner_radius="SolenoidCoil_center_radius" + outer_radius="Solenoid_outer_radius"> + </field> + <!-- remove anti magnetic field in order to extrapolate to muon detector more easily--> + <!--field name="OuterSolenoid" type="solenoid" + inner_field="0" + outer_field="Field_outer_nominal_value" + zmax="SolenoidCoil_half_length" + inner_radius="Solenoid_outer_radius" + outer_radius="Yoke_barrel_inner_radius"> + </field--> + </fields> + +</lccdd> diff --git a/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_wrap.xml b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_wrap.xml new file mode 100644 index 00000000..b0bb96fc --- /dev/null +++ b/Detector/DetCRD/compact/TDR_o1_v01/TDR_o1_v01_wrap.xml @@ -0,0 +1,85 @@ +<?xml version="1.0" encoding="UTF-8"?> +<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd"> + <info name="TDR_o1_v01" + title="CepC reference detctor for TDR" + author="" + url="http://cepc.ihep.ac.cn" + status="developing" + version="v01"> + <comment>CepC reference detector simulation models used for TDR </comment> + </info> + + <includes> + <gdmlFile ref="${DD4hepINSTALL}/DDDetectors/compact/elements.xml"/> + <gdmlFile ref="../CRD_common_v02/materials.xml"/> + </includes> + + <define> + <constant name="world_size" value="10*m"/> + <constant name="world_x" value="world_size"/> + <constant name="world_y" value="world_size"/> + <constant name="world_z" value="world_size"/> + + <include ref="${DD4hepINSTALL}/DDDetectors/compact/detector_types.xml"/> + </define> + + <include ref="./TDR_Dimensions_v01_01.xml"/> + + <include ref="../CRD_common_v02/Beampipe_v01_07.xml"/> + <!--preliminary vertex and tracker, to update/--> + <!--include ref="../CRD_common_v02/VXD_StaggeredLadder_v02_01.xml"/--> + <include ref="../CRD_common_v02/VXD_Composite_v01_03.xml"/> + <!--include ref="../CRD_common_v02/FTD_SkewRing_v01_07.xml"/--> + <!--include ref="../CRD_common_v02/SIT_SimplePixel_v01_04.xml"/--> + <!--include ref="../CRD_common_v02/SIT_StaggeredStave_v02.xml"/--> + <include ref="../CRD_common_v02/ITK_StaggeredStave_v03_01.xml"/> + <include ref="../CRD_common_v02/ITK_EndCap_v01.xml"/> + <!--include ref="../CRD_common_v01/TPC_Simple_v10_02.xml"/--> + <!-- use 10 rows clustering version--> + <include ref="../CRD_common_v02/TPC_ModularEndcap_o1_v02_wrap.xml"/> + <!--include ref="../CRD_common_v01/SET_SimplePixel_v01_01.xml"/--> + <!--include ref="../CRD_common_v01/OTKBarrel_v01_01.xml"/--> + <include ref="../CRD_common_v01/OTKBarrel_v02.xml"/> + <!--include ref="../CRD_common_v01/OTKEndcap_v01_01.xml"/--> + <include ref="../CRD_common_v01/OTKEndcap_v02.xml"/> + + <include ref="../CRD_common_v01/Ecal_Crystal_Barrel_v02_02.xml"/> + <include ref="../CRD_common_v01/Ecal_Crystal_Endcap_v02_01.xml"/> + <include ref="../CRD_common_v01/SHcalGlass_Barrel_v05.xml"/> + <include ref="../CRD_common_v01/SHcalGlass_Endcaps_v01.xml"/> + + <!--Lumical to update--> + <include ref="../CRD_common_v01/Lumical_o1_v01.xml"/> + <!--preliminary Magnet, to update/--> + <include ref="../CRD_common_v02/Coil_Simple_v01_03.xml"/> + <!--preliminary Muon, obselete/--> + <!--include ref="../CRD_common_v02/Yoke_Polyhedra_Barrel_v01_01.xml"/> + <include ref="../CRD_common_v02/Yoke_Polyhedra_Endcaps_v01_01.xml"/--> + + <!--muon detector--> + <include ref="../CRD_common_v01/Muon_Barrel_v01_04.xml"/> + <include ref="../CRD_common_v01/Muon_Endcap_v01_02.xml"/> + <include ref="../CRD_common_v01/ParaffinEndcap_v01_01.xml"/> + <!--include ref="../CRD_common_v01/ConcreteWall_v01_01.xml"/--> + + <fields> + <field name="InnerSolenoid" type="solenoid" + inner_field="Field_nominal_value" + outer_field="0" + zmax="SolenoidCoil_half_length" + inner_radius="SolenoidCoil_center_radius" + outer_radius="Solenoid_outer_radius"> + </field> + <!-- remove anti magnetic field in order to extrapolate to muon detector more easily--> + <!--field name="OuterSolenoid" type="solenoid" + inner_field="0" + outer_field="Field_outer_nominal_value" + zmax="SolenoidCoil_half_length" + inner_radius="Solenoid_outer_radius" + outer_radius="Yoke_barrel_inner_radius"> + </field--> + </fields> + +</lccdd> diff --git a/Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01_simplified.cpp b/Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01_simplified.cpp new file mode 100644 index 00000000..c469e68b --- /dev/null +++ b/Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01_simplified.cpp @@ -0,0 +1,557 @@ +/********************************************************************* + * Author : Lan-sx & origin author: F. Gaede, Desy + * Email : shexin@ihep.ac.cn + * Last modified : 2024-06-02 20:37 + * Filename : TPC_ModularEndcap_o1_v01.cpp + * Description : + * ******************************************************************/ + +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/DD4hepUnits.h" +#include "DD4hep/DetType.h" +//#include "./include/LcgeoExceptions.h" +//#include "./include/lcgeo.h" +#include "DDRec/Surface.h" +#include "DDRec/DetectorData.h" +#include "XML/Utilities.h" +//#include "XMLHandlerDB.h" + +#include <math.h> + +using namespace std; +using namespace dd4hep; +//using namespace lcgeo; + +using dd4hep::rec::Vector3D; +using dd4hep::rec::VolCylinder; +using dd4hep::rec::SurfaceType; +using dd4hep::rec::volSurfaceList; +using dd4hep::rec::VolPlane; +using dd4hep::rec::FixedPadSizeTPCData; +using dd4hep::rec::ConicalSupportData; + +/** Construction of TPC detector, ported from Mokka driver TPC10.cc + * Mokka History: + * - modified version of TPC driver by Ties Behnke + * - modified version of TPC02 as TPC03 with selectable chamber gas -- Adrian Vogel, 2005-06-09 + * - modified version of TPC03 as TPC04 with limit of step length -- Adrian Vogel, 2006-02-01 + * - introduced self-scalability, no superdriver needed anymore -- Adrian Vogel, 2006-03-11 + * - modified version of TPC04 as TPC05 in order to have full MC + * information both at entry and exit hits in the TPC , + * more realistic central electrode and endplate -- Predrag Krstonosic, 2006-07-12 + * - implemented new GEAR interface -- K. Harder, T. Pinto Jayawardena 2007-07-31 + * - TPC10 implemented readout within the Gas volume and layered inner and outer wall -- SJA -- 2010-11-19 + * + * @author: F.Gaede, DESY, Nov 2013 + * + * - Modular Endcap TPC Geo implemention for CEPC TDR TPC + * @author: X.She, IHEP, May 2024 + */ + +static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector sens) { + + + //------------------------------------------ + // See comments starting with '//**' for + // hints on porting issues + //------------------------------------------ + xml_det_t x_det = e; + string name = x_det.nameStr(); + + DetElement tpc( name, x_det.id() ) ; + + // --- create an envelope volume and position it into the world --------------------- + + Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector, e , tpc ) ; + + dd4hep::xml::setDetectorTypeFlag( e, tpc ) ; + + if( theDetector.buildType() == BUILD_ENVELOPE ) return tpc ; + + //----------------------------------------------------------------------------------- + + PlacedVolume pv; + + if (x_det.hasChild(_U(sensitive))) { + xml_dim_t sd_typ = x_det.child(_U(sensitive)); + sens.setType(sd_typ.typeStr()); + } + else { + sens.setType("tracker"); + } + + std::cout << " **Lan Lan building TPC_ModularEndcap_TDR_o1_v01 construction" << std::endl ; + + //###################################################################################################################################################################### + const double phi1 = 0.0 ; + const double phi2 = 2*M_PI ; + const double dzTotal = theDetector.constant<double>("TPC_half_length") * 2. ; + const double rInner = theDetector.constant<double>("TPC_inner_radius") ; + const double rOuter = theDetector.constant<double>("TPC_outer_radius") ; + const double drInnerWall = theDetector.constant<double>("TPC_dr_InnerWall"); + const double drOuterWall = theDetector.constant<double>("TPC_dr_OuterWall"); + const double drInnerServiceArea = theDetector.constant<double>("TPC_dr_InnerServiceArea"); + const double dz_Cathode = theDetector.constant<double>("TPC_dz_Cathode"); + const double dz_Endplate = theDetector.constant<double>("TPC_dz_Endplate"); + const double dz_Readout = theDetector.constant<double>("TPC_dz_Readout"); + const double tpcpadheight = theDetector.constant<double>("TPC_pad_height"); + const double tpcpadwidth = theDetector.constant<double>("TPC_pad_width"); + const int tpcnumberOfPadRows = theDetector.constant<int>("TPC_numberOfPadrows"); + + + std::cout<< "============ TPC_HoneyComb_TDR_o1_v01 mother Volume(Tube) (Dz,Ri,Ro) : (" << dzTotal/dd4hep::mm/2. << "\t" + << rInner/dd4hep::mm << "\t" + << rOuter/dd4hep::mm <<" )"<<std::endl; + Material materialT2Kgas = theDetector.material("T2KGas1"); + Material materialAir = theDetector.material("Air"); + Material materialAlframe = theDetector.material("TPC_Alframe"); + //-------------------------------------------------------------------------------------------------------// + //-------------------------------- TPC mother volume ----------------------------------------------------// + //------------ Volume for the whole TPC, Field Cage, Cathode, and Endplate and Sensitive ----------------// + + Tube tpc_motherSolid(rInner ,rOuter ,dzTotal/2.0 , phi1 , phi1+phi2 ); + Volume tpc_motherLog( "TPCLog", tpc_motherSolid, materialT2Kgas); + pv = envelope.placeVolume( tpc_motherLog ) ; + tpc.setVisAttributes(theDetector, "TPCMotherVis1" , tpc_motherLog ) ; + + double gasRegion = ((rOuter-drOuterWall)-(rInner+drInnerWall))/dd4hep::mm; + std::cout << "================================================================"<< std::endl; + std::cout << "TPC_HoneyComb_TDR_o1_v01: Total Gas material corresponds to " << ( ( gasRegion ) / (materialT2Kgas->GetMaterial()->GetRadLen() / dd4hep::mm ) * 100.0 ) + << "% of a radiation length." << std::endl; + std::cout << "================================================================"<< std::endl; + + //-------------------------------------------------------------------------------------------------------// + //Loop all sections + //-------------------------------------------------------------------------------------------------------// + + for(xml_coll_t si(x_det, Unicode("component"));si;++si) + { + xml_comp_t x_section(si); + std::string types = x_section.attr<std::string>(_Unicode(type)); + const std::string volName = x_section.nameStr(); + + //-------------------------------- inner/outer wall construction ----------------------------------------// + if(types == "TPCinnerWall" || types == "TPCouterWall") + { + double r_start = x_section.attr<double>(_Unicode(R_start)); + double r_end = x_section.attr<double>(_Unicode(R_end)); + double z_fulllength = x_section.attr<double>(_Unicode(Z_fulllength)); + + //Create Inner/Outer Wall mother logic volume + std::string volNameLog = volName + "Log"; + Tube WallSolid(r_start,r_end,z_fulllength/2., phi1 , phi1+phi2); + Volume WallLog(volNameLog,WallSolid,materialT2Kgas); + pv=tpc_motherLog.placeVolume(WallLog); + tpc.setVisAttributes(theDetector,"CyanVis",WallLog); + + Vector3D ocyl; + //SurfaceList data, same as TPC10(CEPCV4) + double dr_wall = r_end-r_start; + if(types == "TPCinnerWall") + ocyl.fill(r_start+0.5*dr_wall,0.,0.); + else + ocyl.fill(r_end-0.5*dr_wall,0.,0.); + + //std::cout<<"======> Vector3D cout : "<<ocyl.x()<<"\t"<<ocyl.y()<<"\t"<<ocyl.z()<<std::endl; + VolCylinder surfWall(WallLog,SurfaceType( SurfaceType::Helper ),0.5*dr_wall,0.5*dr_wall,ocyl); + volSurfaceList( tpc )->push_back( surfWall ); + + //Loop all layers of inner/outer wall + int ilayer =0; + double rCursor = r_start; + double fracRadLengthWall = 0.; + for(xml_coll_t li(x_section,_U(layer)); li;++li,++ilayer) + { + xml_comp_t x_layer(li); + + double thickness = x_layer.thickness(); + Material layerMaterial = theDetector.material( x_layer.materialStr() ); + char suffix[20]; + sprintf(suffix,"_%d",ilayer); + std::string layerName = volNameLog + suffix; + + Tube layerSolid(rCursor,rCursor+thickness,z_fulllength/2.,phi1,phi1+phi2); + Volume layerLog(layerName,layerSolid,layerMaterial); + //layerLog.setVisAttributes(theDetector,x_layer.visStr()); + pv=WallLog.placeVolume(layerLog); + + rCursor += thickness; + double layerRadLength = thickness/(layerMaterial->GetMaterial()->GetRadLen()); + fracRadLengthWall += layerRadLength; + + std::cout<<"-> "<<volName<<"layer"<<ilayer<<" : "<< thickness/dd4hep::mm << "mm \t Materials: "<<layerMaterial.name() + <<" X0= "<<layerMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<"mm \t" + <<layerRadLength<<" X0"<<std::endl; + } + + double drSumThickness = rCursor - r_start; + if(drSumThickness > (r_end-r_start)) + { + std::cout<<"Warning! sum_{i}layerThickness_{i} > drWall !\n"<<std::endl; + throw "$!!! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC Wall - check your xml file -component <TPCInnerWall/TPCOuterWall>"; + } + + std::cout << "================================================================"<< std::endl; + std::cout<<"=====>$ "<<volName<<" material corresponds to "<< int(fracRadLengthWall*1000)/10. << "% of a radiation length."<<std::endl; + std::cout<<"=====>$ "<<volName<<" effective X0= "<<std::setw(4)<< (r_end-r_start)/fracRadLengthWall <<" cm "<<std::endl; + std::cout<<"=====>$ Sum of layer thickness = "<< drSumThickness/dd4hep::mm <<" mm "<<" \t Wall thickness = "<<(r_end-r_start)/dd4hep::mm <<" mm "<<std::endl; + std::cout << "================================================================"<< std::endl; + } + //-------------------------------- TPCGrip construction ----------------------------------------// + if(types == "TPCGrip") + { + Material gripMaterial = theDetector.material(x_section.attr<std::string>(_Unicode(material))) ; + for(xml_coll_t li(x_section,_U(layer));li;++li) + { + xml_comp_t x_layer(li); + + //std::string volNameLog = x_layer.nameStr()+"Log"; + Tube gripSolid(x_layer.rmin(),x_layer.rmax(),x_layer.z_length()/2., phi1 , phi1+phi2); + Volume gripLog(x_layer.nameStr()+"Log",gripSolid,gripMaterial); + pv=tpc_motherLog.placeVolume(gripLog); + tpc.setVisAttributes(theDetector,x_layer.visStr(),gripLog); + std::cout << "================================================================"<< std::endl; + std::cout<<"=====>$ "<<x_layer.nameStr()<<" Constructed ! "<<std::endl; + std::cout << "================================================================"<< std::endl; + } + } + //-------------------------------- TPCCathode construction ----------------------------------------// + if(types == "TPCCathode") + { + for(xml_coll_t li(x_section,_U(layer));li;++li) + { + xml_comp_t x_layer(li); + Material cathodeMaterial = theDetector.material( x_layer.materialStr()); + + Tube cathodeSolid(x_layer.rmin(),x_layer.rmax(),x_layer.z_length()/2,phi1,phi1+phi2); + Volume cathodeLog(x_layer.nameStr()+"Log",cathodeSolid,cathodeMaterial); + + for(xml_coll_t pj(x_layer,_U(position));pj;++pj) + { + xml_dim_t x_pos(pj); + pv = tpc_motherLog.placeVolume(cathodeLog,Position(x_pos.x(),x_pos.y(),x_pos.z())); + tpc.setVisAttributes(theDetector, x_layer.visStr(),cathodeLog); + std::cout<<"============>Cathod Z Position: "<<x_pos.z() / dd4hep::mm <<" mm "<<std::endl; + } + } + } + //-------------------------------- TPC Sensitive Volume construction ----------------------------------------// + if(types == "TPCSensitiveVol") + { + //Material T2KgasMaterial = theDetector.material(x_section.attr<std::string>(_Unicode(material))) ; + std::cout<<"============>T2K gas RadLen= "<< materialT2Kgas->GetMaterial()->GetRadLen()/dd4hep::mm<<" mm"<<std::endl; + + xml_dim_t dimSD = x_section.dimensions(); + std::cout<<"============>rmin,rmax,dz "<< dimSD.rmin()<<"\t"<<dimSD.rmax()<<"\t"<<dimSD.z_length()<<std::endl; + + Tube sensitiveGasSolid(dimSD.rmin(),dimSD.rmax(),dimSD.z_length()/2.,phi1,phi1+phi2); + Volume sensitiveGasLog(volName+"Log",sensitiveGasSolid,materialT2Kgas); + + DetElement sensGasDEfwd(tpc, "tpc_senGas_fwd",x_det.id()); + DetElement sensGasDEbwd(tpc, "tpc_senGas_bwd",x_det.id()); + + pv = tpc_motherLog.placeVolume(sensitiveGasLog,Transform3D(RotationY(0.),Position(0,0,+(dz_Cathode/2+dimSD.z_length()/2.)))); + pv.addPhysVolID("side",+1); + sensGasDEfwd.setPlacement(pv); + + pv = tpc_motherLog.placeVolume(sensitiveGasLog,Transform3D(RotationY(pi),Position(0,0,-(dz_Cathode/2+dimSD.z_length()/2.)))); + pv.addPhysVolID("side",-1); + sensGasDEbwd.setPlacement(pv); + + tpc.setVisAttributes(theDetector, "gasVis", sensitiveGasLog); + + //Pad row doublets construction + xml_coll_t cc(x_section,_U(layer)); + xml_comp_t x_layer = cc; + int numberPadRows = x_layer.repeat(); + double padHeight = x_layer.thickness(); + std::cout<<"##################$$$$$$$$$$$$$$ Number of Pad Rows: > "<<numberPadRows<<"\t padHeight= "<<padHeight/dd4hep::mm<<" mm"<<std::endl; + + //Sensitive Volume construction : readout pad layers + // for(int ilayer=0; ilayer < numberPadRows; ++ilayer) + // { + // // create twice the number of rings as there are pads, producing an lower and upper part of the pad with the boundry between them the pad-ring centre + // const double inner_lowerlayer_radius = dimSD.rmin()+ (ilayer * (padHeight)); + // const double outer_lowerlayer_radius = inner_lowerlayer_radius + (padHeight/2.0); + + // const double inner_upperlayer_radius = outer_lowerlayer_radius ; + // const double outer_upperlayer_radius = inner_upperlayer_radius + (padHeight/2.0); + + // Tube lowerlayerSolid( inner_lowerlayer_radius, outer_lowerlayer_radius, dimSD.z_length() / 2.0, phi1, phi2); + // Tube upperlayerSolid( inner_upperlayer_radius, outer_upperlayer_radius, dimSD.z_length() / 2.0, phi1, phi2); + + // Volume lowerlayerLog( _toString( ilayer ,"TPC_lowerlayer_log_%02d") ,lowerlayerSolid, materialT2Kgas ); + // Volume upperlayerLog( _toString( ilayer ,"TPC_upperlayer_log_%02d") ,upperlayerSolid, materialT2Kgas ); + + // tpc.setVisAttributes(theDetector, "Invisible" , lowerlayerLog) ; + // tpc.setVisAttributes(theDetector, "Invisible" , upperlayerLog) ; + // //tpc.setVisAttributes(theDetector, "RedVis" , lowerlayerLog) ; + // //tpc.setVisAttributes(theDetector, "RedVis" , upperlayerLog) ; + + // DetElement layerDEfwd( sensGasDEfwd , _toString( ilayer, "tpc_row_fwd_%03d") , x_det.id() ); + // DetElement layerDEbwd( sensGasDEbwd , _toString( ilayer, "tpc_row_bwd_%03d") , x_det.id() ); + + // Vector3D o( inner_upperlayer_radius + 1e-10 , 0. , 0. ) ; + // // create an unbounded surface (i.e. an infinite cylinder) and assign it to the forward gaseous volume only + // VolCylinder surf( upperlayerLog , SurfaceType(SurfaceType::Sensitive, SurfaceType::Invisible, SurfaceType::Unbounded ) , (padHeight/2.0) , (padHeight/2.0) ,o ) ; + + // volSurfaceList( layerDEfwd )->push_back( surf ) ; + // // volSurfaceList( layerDEbwd )->push_back( surf ) ; + + // pv = sensitiveGasLog.placeVolume( lowerlayerLog ) ; + // pv.addPhysVolID("layer", ilayer ).addPhysVolID( "module", 0 ).addPhysVolID("sensor", 1 ) ; + + // pv = sensitiveGasLog.placeVolume( upperlayerLog ) ; + // pv.addPhysVolID("layer", ilayer ).addPhysVolID( "module", 0 ).addPhysVolID("sensor", 0 ) ; + // layerDEfwd.setPlacement( pv ) ; + // layerDEbwd.setPlacement( pv ) ; + + // lowerlayerLog.setSensitiveDetector(sens); + // upperlayerLog.setSensitiveDetector(sens); + // if (x_det.hasAttr(_U(limits))) { + // lowerlayerLog.setLimitSet(theDetector, x_det.limitsStr()); + // upperlayerLog.setLimitSet(theDetector, x_det.limitsStr()); + // } + // } + + } + //-------------------------------- TPC Endplate and readout construction ----------------------------------------// + if(types == "TPCEndplate") + { + xml_dim_t dimEndCap = x_section.dimensions(); + std::cout<<"============>(rmin,rmax,dz): "<< dimEndCap.rmin() / dd4hep::mm<<"mm " + << dimEndCap.rmax() / dd4hep::mm<<" mm " + << dimEndCap.z_length() / dd4hep::mm<< " mm" <<std::endl; + //Create endcap Log volume + Tube endcapSolid(dimEndCap.rmin(),dimEndCap.rmax(),dimEndCap.z_length()/2.,phi1,phi1+phi2); + Volume endcapLog(volName+"Log",endcapSolid,materialAir); + + DetElement endcapDEfwd(tpc, "tpc_endcap_fwd",x_det.id()); + DetElement endcapDEbwd(tpc, "tpc_endcap_bwd",x_det.id()); + + //Vectors for endplate plane + Vector3D u(0.,1.,0.); + Vector3D v(1.,0.,0.); + Vector3D n(0.,0.,1.); + + ////need to set the origin of the helper plane to be inside the material (otherwise it would pick up the vacuum at the origin) + double mid_r = 0.5*(rOuter + rInner); + Vector3D o(0., mid_r, 0.); + + VolPlane surf( endcapLog, SurfaceType( SurfaceType::Helper ), (dz_Endplate+dz_Readout)/2.,dz_Endplate/2.,u,v,n,o); + volSurfaceList(endcapDEfwd) -> push_back(surf); + volSurfaceList(endcapDEbwd) -> push_back(surf); + + pv = tpc_motherLog.placeVolume(endcapLog,Transform3D(RotationY(0.),Position(0,0,+(dzTotal/2.-dz_Endplate/2.)))); + endcapDEfwd.setPlacement(pv); + + pv = tpc_motherLog.placeVolume(endcapLog,Transform3D(RotationY(pi),Position(0,0,-(dzTotal/2.-dz_Endplate/2.)))); + endcapDEbwd.setPlacement(pv); + + tpc.setVisAttributes(theDetector, "transVis", endcapLog); + + //================================================================================================ + //Modular Endplate construction + //================================================================================================ + double dz_Endpaltelength = dimEndCap.z_length(); + double r_start = dimEndCap.rmin(); + double ds_reinforce = x_section.attr<double>(_Unicode(s_frame)); + double dz_Alframe = x_section.attr<double>(_Unicode(z_frame)); + double rCursor = r_start; + + //Loop all layers to construct frame-module + for(xml_coll_t ilayer(x_section,_U(layer)); ilayer; ++ilayer) + { + xml_comp_t x_layer(ilayer); + + const std::string layerName = x_layer.nameStr(); + const std::string layerType = x_layer.attr<std::string>(_Unicode(type)); + double layerThickness = x_layer.thickness(); + + double r_end = rCursor + layerThickness; + std::cout<<"===============>$ "<<layerName<<"\t"<<layerType + <<" thickness = "<<layerThickness / dd4hep::mm << "mm " + <<" inner radius = "<<rCursor / dd4hep::mm<<" mm" + <<" outer radius = "<<r_end /dd4hep::mm<<" mm" + <<std::endl; + + //-------------------------------------- + if(layerType == "Frame") + { + double phi_start = 0.; + double phi_end = 2*M_PI; + Tube ringSolid(rCursor, r_end, dz_Alframe/2., phi_start, phi_end) ; + Volume ringLog( layerName+"Log", ringSolid, materialAlframe) ; + pv = endcapLog.placeVolume( ringLog, Position(0., 0., -dz_Endpaltelength/2. + dz_Alframe/2.) ) ; + tpc.setVisAttributes(theDetector,"GrayVis",ringLog); + } + if(layerType == "Module") + { + int numberofModules = x_layer.repeat(); + double phi_start = x_layer.phi0_offset(); + double phiCursor = phi_start; + double phiModule = (2*M_PI*rCursor-numberofModules*ds_reinforce)/numberofModules/rCursor; + double phiReinforce = ds_reinforce/rCursor; + + //Construct each module + for(int k=0; k<numberofModules;++k) + { + Tube moduleSolid1(rCursor,r_end,dz_Endpaltelength/2.,phiCursor,phiCursor+phiModule); + std::string moduleLogName1 = layerName + _toString(k,"Log%00d"); + Volume moduleLog1(moduleLogName1,moduleSolid1,materialAir); + + double z_cursor = -dz_Endpaltelength/2.; + int m_sli = 0; + for(xml_coll_t sli(x_layer,_U(slice)); sli; ++sli,++m_sli) + { + xml_comp_t x_slice = sli; + double dz_modulepiece = sli.attr<double>(_Unicode(dz)); + std::string moduleSliceName = moduleLogName1 + _toString(m_sli,"slice%d"); + Material slice_mat = theDetector.material(x_slice.materialStr()); + + Tube moduleSliceSolid(rCursor,r_end,dz_modulepiece/2.,phiCursor,phiCursor+phiModule); + Volume moduleSliceLog(moduleSliceName,moduleSliceSolid,slice_mat); + + pv = moduleLog1.placeVolume(moduleSliceLog,Position(0.,0.,z_cursor+dz_modulepiece/2.)); + tpc.setVisAttributes(theDetector, "Invisible" , moduleSliceLog) ; + z_cursor += dz_modulepiece; + + if(z_cursor > dz_Endpaltelength/2.) + { + //std::cout<<" Warning ! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC Module- check your xml file - section <Endpalte>." <<std::endl; + throw " $!!! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC Module- check your xml file - component <Endpalte>."; + } + } + + pv = endcapLog.placeVolume(moduleLog1); + tpc.setVisAttributes(theDetector,"RedVis",moduleLog1); + + phiCursor = phiCursor+phiModule; + + //Construct the Al frame between each module + Tube moduleSolid2(rCursor,r_end,dz_Alframe/2.,phiCursor,phiCursor+phiReinforce); + std::string moduleLogName2 = layerName + _toString(k,"Log_rein%00d"); + Volume moduleLog2(moduleLogName2,moduleSolid2,materialAlframe); + pv = endcapLog.placeVolume(moduleLog2, Position(0., 0., -dz_Endpaltelength/2.+dz_Alframe/2.)); + tpc.setVisAttributes(theDetector,"GrayVis",moduleLog2); + + phiCursor = phiCursor+phiReinforce; + } + } + rCursor = r_end; + } + + double RadlenOfAl_Frame = materialAlframe->GetMaterial()->GetRadLen(); + std::cout << "================================================================"<< std::endl; + std::cout << "TPC_ModularEndcap_TDR_o1_v01: Endplate Al frame corresponds to " << (2. / RadlenOfAl_Frame*100)<< "% of a radiation length." << std::endl; + std::cout << "================================================================"<< std::endl; + } + //-------------------------------- TPCreadout construction ----------------------------------------// + if(types == "TPCreadout") + { + xml_dim_t dimReadout = x_section.dimensions(); + double dzReadout = dimReadout.z_length(); + Tube readoutSolid(dimReadout.rmin(),dimReadout.rmax(),dimReadout.z_length()/2.,phi1,phi1+phi2); + Volume readoutLog(volName+"Log",readoutSolid, materialT2Kgas); + + tpc.setVisAttributes(theDetector,"CyanVis",readoutLog); + + xml_dim_t posReadout = x_section.position(); + pv = tpc_motherLog.placeVolume(readoutLog,Transform3D(RotationY(0.),Position(0,0,posReadout.z()))); + pv = tpc_motherLog.placeVolume(readoutLog,Transform3D(RotationY(pi),Position(0,0,-posReadout.z()))); + + std::cout<<"=========ReadOut dim: "<< dimReadout.rmin() / dd4hep::mm<<" mm " + << dimReadout.rmax() / dd4hep::mm<<" mm " + << dzReadout / dd4hep::mm <<" mm "<<std::endl; + std::cout<<"=========ReadOut Z_pos: "<<posReadout.z() / dd4hep::mm << " mm "<<std::endl; + + int pieceCounter = 0; + double fracRadLengthReadout = 0; + double zCursor = -dzReadout/ 2; + + for(xml_coll_t li(x_section,_U(layer)); li;++li) + { + xml_comp_t x_layer( li ); + + const double dzPiece = x_layer.attr<double>(_Unicode(dz)); + Material pieceMaterial = theDetector.material( x_layer.materialStr() ); + Tube pieceSolid( dimReadout.rmin(),dimReadout.rmax(), dzPiece / 2, phi1, phi2); + Volume pieceLog ( _toString( pieceCounter ,"TPCReadoutPieceLog_%02d"), pieceSolid, pieceMaterial ) ; + + pieceLog.setVisAttributes(theDetector,x_layer.visStr()); + + pv = readoutLog.placeVolume( pieceLog , Position(0, 0, zCursor + dzPiece/2. ) ) ; + + ++pieceCounter; + fracRadLengthReadout += dzPiece / pieceMaterial->GetMaterial()->GetRadLen(); + zCursor += dzPiece; + + std::cout<<"==========> "<<dzPiece/dd4hep::mm<<" mm Material= "<<x_layer.materialStr()<<"\t" + <<"X0= "<<pieceMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<"\t" + <<dzPiece / pieceMaterial->GetMaterial()->GetRadLen() <<" X0"<< std::endl; + + if (zCursor > +dzReadout / 2) + { + //throw GeometryException( "TPC11: Overfull TPC readout - check your xml file - section <readout>." ) ; + //std::cout<<" TPC_ModularEndcap_TDR_o1_v01: Overfull TPC readout - check your xml file - component <TPCReadout>." <<std::endl; + throw " $!!! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC readout - check your xml file - component <TPCReadout>."; + } + } + std::cout << "================================================================"<< std::endl; + std::cout << "TPC_ModularEndcap_TDR_o1_v01: Readout material corresponds to " << int(fracRadLengthReadout * 1000) / 10.0 << "% of a radiation length." << std::endl; + std::cout << "================================================================"<< std::endl; + } + + } + + //TPC data + FixedPadSizeTPCData* tpcData = new FixedPadSizeTPCData(); + tpcData->zHalf = dzTotal/2.; + tpcData->rMin = rInner; + tpcData->rMax = rOuter; + tpcData->innerWallThickness = drInnerWall; + tpcData->outerWallThickness = drOuterWall; + tpcData->rMinReadout = rInner + drInnerWall + drInnerServiceArea; + tpcData->rMaxReadout = rInner + drInnerWall + drInnerServiceArea + tpcnumberOfPadRows*tpcpadheight; + tpcData->maxRow = tpcnumberOfPadRows; + tpcData->padHeight = tpcpadheight; + tpcData->padWidth = tpcpadwidth; + tpcData->driftLength = dzTotal/2.- dz_Endplate - dz_Readout - dz_Cathode/2.0; // SJA: cathode has to be added as the sensitive region does not start at 0.00 + tpcData->zMinReadout = dz_Cathode/2.0; + + ConicalSupportData* supportData = new ConicalSupportData; + + ConicalSupportData::Section section0; + section0.rInner = rInner + drInnerWall; + section0.rOuter = rOuter - drOuterWall; + section0.zPos = dzTotal/2. - dz_Endplate - dz_Readout; + + ConicalSupportData::Section section1; + section1.rInner = rInner + drInnerWall; + section1.rOuter = rOuter - drOuterWall; + section1.zPos = dzTotal/2. - dz_Endplate; + + ConicalSupportData::Section section2; + section2.rInner = rInner ; + section2.rOuter = rOuter ; + section2.zPos = dzTotal/2.; + + supportData->sections.push_back(section0); + supportData->sections.push_back(section1); + supportData->sections.push_back(section2); + + + tpc.addExtension< FixedPadSizeTPCData >(tpcData); + tpc.addExtension< ConicalSupportData >(supportData); + + //tpc.setVisAttributes( theDetector, x_det.visStr(), envelope ); + tpc.setVisAttributes( theDetector, "TPCMotherVis1", envelope ); + // if( tpc.isValid() ) + // tpc.setPlacement(pv); + std::cout << "================================================================"<< std::endl; + std::cout << "TPC_ModularEndcap_TDR_o1_v01 Constructed!"<< std::endl; + std::cout << "================================================================"<< std::endl; + + return tpc; +} +DECLARE_DETELEMENT(TPC_ModularEndcap_o1_v01_simplified,create_element) diff --git a/Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01_wrapvolume.cpp b/Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01_wrapvolume.cpp new file mode 100644 index 00000000..4702cee0 --- /dev/null +++ b/Detector/DetCRD/src/Tracker/TPC_ModularEndcap_o1_v01_wrapvolume.cpp @@ -0,0 +1,582 @@ +/********************************************************************* + * Author : Lan-sx & origin author: F. Gaede, Desy + * Email : shexin@ihep.ac.cn + * Last modified : 2024-06-02 20:37 + * Filename : TPC_ModularEndcap_o1_v01.cpp + * Description : + * ******************************************************************/ + +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/DD4hepUnits.h" +#include "DD4hep/DetType.h" +//#include "./include/LcgeoExceptions.h" +//#include "./include/lcgeo.h" +#include "DDRec/Surface.h" +#include "DDRec/DetectorData.h" +#include "XML/Utilities.h" +//#include "XMLHandlerDB.h" + +#include <math.h> + +using namespace std; +using namespace dd4hep; +//using namespace lcgeo; + +using dd4hep::rec::Vector3D; +using dd4hep::rec::VolCylinder; +using dd4hep::rec::SurfaceType; +using dd4hep::rec::volSurfaceList; +using dd4hep::rec::VolPlane; +using dd4hep::rec::FixedPadSizeTPCData; +using dd4hep::rec::ConicalSupportData; + +/** Construction of TPC detector, ported from Mokka driver TPC10.cc + * Mokka History: + * - modified version of TPC driver by Ties Behnke + * - modified version of TPC02 as TPC03 with selectable chamber gas -- Adrian Vogel, 2005-06-09 + * - modified version of TPC03 as TPC04 with limit of step length -- Adrian Vogel, 2006-02-01 + * - introduced self-scalability, no superdriver needed anymore -- Adrian Vogel, 2006-03-11 + * - modified version of TPC04 as TPC05 in order to have full MC + * information both at entry and exit hits in the TPC , + * more realistic central electrode and endplate -- Predrag Krstonosic, 2006-07-12 + * - implemented new GEAR interface -- K. Harder, T. Pinto Jayawardena 2007-07-31 + * - TPC10 implemented readout within the Gas volume and layered inner and outer wall -- SJA -- 2010-11-19 + * + * @author: F.Gaede, DESY, Nov 2013 + * + * - Modular Endcap TPC Geo implemention for CEPC TDR TPC + * @author: X.She, IHEP, May 2024 + */ + +static Ref_t create_element(Detector& theDetector, xml_h e, SensitiveDetector sens) { + + + //------------------------------------------ + // See comments starting with '//**' for + // hints on porting issues + //------------------------------------------ + xml_det_t x_det = e; + string name = x_det.nameStr(); + + DetElement tpc( name, x_det.id() ) ; + + // --- create an envelope volume and position it into the world --------------------- + + Volume envelope = dd4hep::xml::createPlacedEnvelope( theDetector, e , tpc ) ; + + dd4hep::xml::setDetectorTypeFlag( e, tpc ) ; + + if( theDetector.buildType() == BUILD_ENVELOPE ) return tpc ; + + //----------------------------------------------------------------------------------- + + PlacedVolume pv; + + if (x_det.hasChild(_U(sensitive))) { + xml_dim_t sd_typ = x_det.child(_U(sensitive)); + sens.setType(sd_typ.typeStr()); + } + else { + sens.setType("tracker"); + } + + std::cout << " **Lan Lan building TPC_ModularEndcap_TDR_o1_v01 construction" << std::endl ; + + //###################################################################################################################################################################### + const double phi1 = 0.0 ; + const double phi2 = 2*M_PI ; + const double dzTotal = theDetector.constant<double>("TPC_half_length") * 2. ; + const double rInner = theDetector.constant<double>("TPC_inner_radius") ; + const double rOuter = theDetector.constant<double>("TPC_outer_radius") ; + const double drInnerWall = theDetector.constant<double>("TPC_dr_InnerWall"); + const double drOuterWall = theDetector.constant<double>("TPC_dr_OuterWall"); + const double drInnerServiceArea = theDetector.constant<double>("TPC_dr_InnerServiceArea"); + const double dz_Cathode = theDetector.constant<double>("TPC_dz_Cathode"); + const double dz_Endplate = theDetector.constant<double>("TPC_dz_Endplate"); + const double dz_Readout = theDetector.constant<double>("TPC_dz_Readout"); + const double tpcpadheight = theDetector.constant<double>("TPC_pad_height"); + const double tpcpadwidth = theDetector.constant<double>("TPC_pad_width"); + const int tpcnumberOfPadRows = theDetector.constant<int>("TPC_numberOfPadrows"); + + + std::cout<< "============ TPC_HoneyComb_TDR_o1_v01 mother Volume(Tube) (Dz,Ri,Ro) : (" << dzTotal/dd4hep::mm/2. << "\t" + << rInner/dd4hep::mm << "\t" + << rOuter/dd4hep::mm <<" )"<<std::endl; + Material materialT2Kgas = theDetector.material("T2KGas1"); + Material materialAir = theDetector.material("Air"); + Material materialAlframe = theDetector.material("TPC_Alframe"); + //-------------------------------------------------------------------------------------------------------// + //-------------------------------- TPC mother volume ----------------------------------------------------// + //------------ Volume for the whole TPC, Field Cage, Cathode, and Endplate and Sensitive ----------------// + + Tube tpc_motherSolid(rInner ,rOuter ,dzTotal/2.0 , phi1 , phi1+phi2 ); + Volume tpc_motherLog( "TPCLog", tpc_motherSolid, materialT2Kgas); + pv = envelope.placeVolume( tpc_motherLog ) ; + tpc.setVisAttributes(theDetector, "TPCMotherVis1" , tpc_motherLog ) ; + + double gasRegion = ((rOuter-drOuterWall)-(rInner+drInnerWall))/dd4hep::mm; + std::cout << "================================================================"<< std::endl; + std::cout << "TPC_HoneyComb_TDR_o1_v01: Total Gas material corresponds to " << ( ( gasRegion ) / (materialT2Kgas->GetMaterial()->GetRadLen() / dd4hep::mm ) * 100.0 ) + << "% of a radiation length." << std::endl; + std::cout << "================================================================"<< std::endl; + + //-------------------------------------------------------------------------------------------------------// + //Loop all sections + //-------------------------------------------------------------------------------------------------------// + + for(xml_coll_t si(x_det, Unicode("component"));si;++si) + { + xml_comp_t x_section(si); + std::string types = x_section.attr<std::string>(_Unicode(type)); + const std::string volName = x_section.nameStr(); + + //-------------------------------- inner/outer wall construction ----------------------------------------// + if(types == "TPCinnerWall" || types == "TPCouterWall") + { + double r_start = x_section.attr<double>(_Unicode(R_start)); + double r_end = x_section.attr<double>(_Unicode(R_end)); + double z_fulllength = x_section.attr<double>(_Unicode(Z_fulllength)); + + //Create Inner/Outer Wall mother logic volume + std::string volNameLog = volName + "Log"; + Tube WallSolid(r_start,r_end,z_fulllength/2., phi1 , phi1+phi2); + Volume WallLog(volNameLog,WallSolid,materialT2Kgas); + pv=tpc_motherLog.placeVolume(WallLog); + tpc.setVisAttributes(theDetector,"CyanVis",WallLog); + + Vector3D ocyl; + //SurfaceList data, same as TPC10(CEPCV4) + double dr_wall = r_end-r_start; + if(types == "TPCinnerWall") + ocyl.fill(r_start+0.5*dr_wall,0.,0.); + else + ocyl.fill(r_end-0.5*dr_wall,0.,0.); + + //std::cout<<"======> Vector3D cout : "<<ocyl.x()<<"\t"<<ocyl.y()<<"\t"<<ocyl.z()<<std::endl; + VolCylinder surfWall(WallLog,SurfaceType( SurfaceType::Helper ),0.5*dr_wall,0.5*dr_wall,ocyl); + volSurfaceList( tpc )->push_back( surfWall ); + + //Loop all layers of inner/outer wall + int ilayer =0; + double rCursor = r_start; + double fracRadLengthWall = 0.; + for(xml_coll_t li(x_section,_U(layer)); li;++li,++ilayer) + { + xml_comp_t x_layer(li); + + double thickness = x_layer.thickness(); + Material layerMaterial = theDetector.material( x_layer.materialStr() ); + char suffix[20]; + sprintf(suffix,"_%d",ilayer); + std::string layerName = volNameLog + suffix; + + Tube layerSolid(rCursor,rCursor+thickness,z_fulllength/2.,phi1,phi1+phi2); + Volume layerLog(layerName,layerSolid,layerMaterial); + //layerLog.setVisAttributes(theDetector,x_layer.visStr()); + pv=WallLog.placeVolume(layerLog); + + rCursor += thickness; + double layerRadLength = thickness/(layerMaterial->GetMaterial()->GetRadLen()); + fracRadLengthWall += layerRadLength; + + std::cout<<"-> "<<volName<<"layer"<<ilayer<<" : "<< thickness/dd4hep::mm << "mm \t Materials: "<<layerMaterial.name() + <<" X0= "<<layerMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<"mm \t" + <<layerRadLength<<" X0"<<std::endl; + } + + double drSumThickness = rCursor - r_start; + if(drSumThickness > (r_end-r_start)) + { + std::cout<<"Warning! sum_{i}layerThickness_{i} > drWall !\n"<<std::endl; + throw "$!!! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC Wall - check your xml file -component <TPCInnerWall/TPCOuterWall>"; + } + + std::cout << "================================================================"<< std::endl; + std::cout<<"=====>$ "<<volName<<" material corresponds to "<< int(fracRadLengthWall*1000)/10. << "% of a radiation length."<<std::endl; + std::cout<<"=====>$ "<<volName<<" effective X0= "<<std::setw(4)<< (r_end-r_start)/fracRadLengthWall <<" cm "<<std::endl; + std::cout<<"=====>$ Sum of layer thickness = "<< drSumThickness/dd4hep::mm <<" mm "<<" \t Wall thickness = "<<(r_end-r_start)/dd4hep::mm <<" mm "<<std::endl; + std::cout << "================================================================"<< std::endl; + } + //-------------------------------- TPCGrip construction ----------------------------------------// + if(types == "TPCGrip") + { + Material gripMaterial = theDetector.material(x_section.attr<std::string>(_Unicode(material))) ; + for(xml_coll_t li(x_section,_U(layer));li;++li) + { + xml_comp_t x_layer(li); + + //std::string volNameLog = x_layer.nameStr()+"Log"; + Tube gripSolid(x_layer.rmin(),x_layer.rmax(),x_layer.z_length()/2., phi1 , phi1+phi2); + Volume gripLog(x_layer.nameStr()+"Log",gripSolid,gripMaterial); + pv=tpc_motherLog.placeVolume(gripLog); + tpc.setVisAttributes(theDetector,x_layer.visStr(),gripLog); + std::cout << "================================================================"<< std::endl; + std::cout<<"=====>$ "<<x_layer.nameStr()<<" Constructed ! "<<std::endl; + std::cout << "================================================================"<< std::endl; + } + } + //-------------------------------- TPCCathode construction ----------------------------------------// + if(types == "TPCCathode") + { + for(xml_coll_t li(x_section,_U(layer));li;++li) + { + xml_comp_t x_layer(li); + Material cathodeMaterial = theDetector.material( x_layer.materialStr()); + + Tube cathodeSolid(x_layer.rmin(),x_layer.rmax(),x_layer.z_length()/2,phi1,phi1+phi2); + Volume cathodeLog(x_layer.nameStr()+"Log",cathodeSolid,cathodeMaterial); + + for(xml_coll_t pj(x_layer,_U(position));pj;++pj) + { + xml_dim_t x_pos(pj); + pv = tpc_motherLog.placeVolume(cathodeLog,Position(x_pos.x(),x_pos.y(),x_pos.z())); + tpc.setVisAttributes(theDetector, x_layer.visStr(),cathodeLog); + std::cout<<"============>Cathod Z Position: "<<x_pos.z() / dd4hep::mm <<" mm "<<std::endl; + } + } + } + //-------------------------------- TPC Sensitive Volume construction ----------------------------------------// + if(types == "TPCSensitiveVol") + { + //Material T2KgasMaterial = theDetector.material(x_section.attr<std::string>(_Unicode(material))) ; + std::cout<<"============>T2K gas RadLen= "<< materialT2Kgas->GetMaterial()->GetRadLen()/dd4hep::mm<<" mm"<<std::endl; + + xml_dim_t dimSD = x_section.dimensions(); + std::cout<<"============>rmin,rmax,dz "<< dimSD.rmin()<<"\t"<<dimSD.rmax()<<"\t"<<dimSD.z_length()<<std::endl; + + Tube sensitiveGasSolid(dimSD.rmin(),dimSD.rmax(),dimSD.z_length()/2.,phi1,phi1+phi2); + Volume sensitiveGasLog(volName+"Log",sensitiveGasSolid,materialT2Kgas); + + DetElement sensGasDEfwd(tpc, "tpc_senGas_fwd",x_det.id()); + DetElement sensGasDEbwd(tpc, "tpc_senGas_bwd",x_det.id()); + + pv = tpc_motherLog.placeVolume(sensitiveGasLog,Transform3D(RotationY(0.),Position(0,0,+(dz_Cathode/2+dimSD.z_length()/2.)))); + pv.addPhysVolID("side",+1); + sensGasDEfwd.setPlacement(pv); + + pv = tpc_motherLog.placeVolume(sensitiveGasLog,Transform3D(RotationY(pi),Position(0,0,-(dz_Cathode/2+dimSD.z_length()/2.)))); + pv.addPhysVolID("side",-1); + sensGasDEbwd.setPlacement(pv); + + tpc.setVisAttributes(theDetector, "gasVis", sensitiveGasLog); + + //Pad row doublets construction + xml_coll_t cc(x_section,_U(layer)); + xml_comp_t x_layer = cc; + int numberPadRows = x_layer.repeat(); + double padHeight = x_layer.thickness(); + std::cout<<"##################$$$$$$$$$$$$$$ Number of Pad Rows: > "<<numberPadRows<<"\t padHeight= "<<padHeight/dd4hep::mm<<" mm"<<std::endl; + + const int layersPerGroup = 10; + std::vector<Volume> groupVolumes; + for (int grp = 0; grp < numberPadRows; grp += layersPerGroup) { + // Determine span for this group + const int count = std::min(layersPerGroup, numberPadRows - grp); + const double r_inner = dimSD.rmin() + grp * padHeight; + const double r_outer = r_inner + count * padHeight; + + Tube groupSolid(r_inner, r_outer, dimSD.z_length() / 2.0, phi1, + phi2); + Volume groupLog(_toString(grp / layersPerGroup, "TPC_group_%02d"), + groupSolid, materialT2Kgas); + + // Optionally set visualization + // tpc.setVisAttributes(theDetector, "BlueVisSemiTransparent", + // groupLog); + + // Place group under the sensitive gas mother volume + sensitiveGasLog.placeVolume(groupLog); + groupVolumes.push_back(groupLog); + } + + //Sensitive Volume construction : readout pad layers + for(int ilayer=0; ilayer < numberPadRows; ++ilayer) + { + int groupIndex = ilayer / layersPerGroup; + Volume &parentGroup = groupVolumes[groupIndex]; + + // create twice the number of rings as there are pads, producing an lower and upper part of the pad with the boundry between them the pad-ring centre + const double inner_lowerlayer_radius = dimSD.rmin()+ (ilayer * (padHeight)); + const double outer_lowerlayer_radius = inner_lowerlayer_radius + (padHeight/2.0); + + const double inner_upperlayer_radius = outer_lowerlayer_radius ; + const double outer_upperlayer_radius = inner_upperlayer_radius + (padHeight/2.0); + + Tube lowerlayerSolid( inner_lowerlayer_radius, outer_lowerlayer_radius, dimSD.z_length() / 2.0, phi1, phi2); + Tube upperlayerSolid( inner_upperlayer_radius, outer_upperlayer_radius, dimSD.z_length() / 2.0, phi1, phi2); + + Volume lowerlayerLog( _toString( ilayer ,"TPC_lowerlayer_log_%02d") ,lowerlayerSolid, materialT2Kgas ); + Volume upperlayerLog( _toString( ilayer ,"TPC_upperlayer_log_%02d") ,upperlayerSolid, materialT2Kgas ); + + tpc.setVisAttributes(theDetector, "Invisible" , lowerlayerLog) ; + tpc.setVisAttributes(theDetector, "Invisible" , upperlayerLog) ; + //tpc.setVisAttributes(theDetector, "RedVis" , lowerlayerLog) ; + //tpc.setVisAttributes(theDetector, "RedVis" , upperlayerLog) ; + + DetElement layerDEfwd( sensGasDEfwd , _toString( ilayer, "tpc_row_fwd_%03d") , x_det.id() ); + // DetElement layerDEbwd( sensGasDEbwd , _toString( ilayer, "tpc_row_bwd_%03d") , x_det.id() ); + + Vector3D o( inner_upperlayer_radius + 1e-10 , 0. , 0. ) ; + // create an unbounded surface (i.e. an infinite cylinder) and assign it to the forward gaseous volume only + VolCylinder surf( upperlayerLog , SurfaceType(SurfaceType::Sensitive, SurfaceType::Invisible, SurfaceType::Unbounded ) , (padHeight/2.0) , (padHeight/2.0) ,o ) ; + + volSurfaceList( layerDEfwd )->push_back( surf ) ; + // volSurfaceList( layerDEbwd )->push_back( surf ) ; + + pv = parentGroup.placeVolume( lowerlayerLog ) ; + pv.addPhysVolID("layer", ilayer ).addPhysVolID( "module", 0 ).addPhysVolID("sensor", 1 ) ; + + pv = parentGroup.placeVolume( upperlayerLog ) ; + pv.addPhysVolID("layer", ilayer ).addPhysVolID( "module", 0 ).addPhysVolID("sensor", 0 ) ; + layerDEfwd.setPlacement( pv ) ; + // layerDEbwd.setPlacement( pv ) ; + + lowerlayerLog.setSensitiveDetector(sens); + upperlayerLog.setSensitiveDetector(sens); + if (x_det.hasAttr(_U(limits))) { + lowerlayerLog.setLimitSet(theDetector, x_det.limitsStr()); + upperlayerLog.setLimitSet(theDetector, x_det.limitsStr()); + } + } + + } + //-------------------------------- TPC Endplate and readout construction ----------------------------------------// + if(types == "TPCEndplate") + { + xml_dim_t dimEndCap = x_section.dimensions(); + std::cout<<"============>(rmin,rmax,dz): "<< dimEndCap.rmin() / dd4hep::mm<<"mm " + << dimEndCap.rmax() / dd4hep::mm<<" mm " + << dimEndCap.z_length() / dd4hep::mm<< " mm" <<std::endl; + //Create endcap Log volume + Tube endcapSolid(dimEndCap.rmin(),dimEndCap.rmax(),dimEndCap.z_length()/2.,phi1,phi1+phi2); + Volume endcapLog(volName+"Log",endcapSolid,materialAir); + + DetElement endcapDEfwd(tpc, "tpc_endcap_fwd",x_det.id()); + DetElement endcapDEbwd(tpc, "tpc_endcap_bwd",x_det.id()); + + //Vectors for endplate plane + Vector3D u(0.,1.,0.); + Vector3D v(1.,0.,0.); + Vector3D n(0.,0.,1.); + + ////need to set the origin of the helper plane to be inside the material (otherwise it would pick up the vacuum at the origin) + double mid_r = 0.5*(rOuter + rInner); + Vector3D o(0., mid_r, 0.); + + VolPlane surf( endcapLog, SurfaceType( SurfaceType::Helper ), (dz_Endplate+dz_Readout)/2.,dz_Endplate/2.,u,v,n,o); + volSurfaceList(endcapDEfwd) -> push_back(surf); + volSurfaceList(endcapDEbwd) -> push_back(surf); + + pv = tpc_motherLog.placeVolume(endcapLog,Transform3D(RotationY(0.),Position(0,0,+(dzTotal/2.-dz_Endplate/2.)))); + endcapDEfwd.setPlacement(pv); + + pv = tpc_motherLog.placeVolume(endcapLog,Transform3D(RotationY(pi),Position(0,0,-(dzTotal/2.-dz_Endplate/2.)))); + endcapDEbwd.setPlacement(pv); + + tpc.setVisAttributes(theDetector, "transVis", endcapLog); + + //================================================================================================ + //Modular Endplate construction + //================================================================================================ + double dz_Endpaltelength = dimEndCap.z_length(); + double r_start = dimEndCap.rmin(); + double ds_reinforce = x_section.attr<double>(_Unicode(s_frame)); + double dz_Alframe = x_section.attr<double>(_Unicode(z_frame)); + double rCursor = r_start; + + //Loop all layers to construct frame-module + for(xml_coll_t ilayer(x_section,_U(layer)); ilayer; ++ilayer) + { + xml_comp_t x_layer(ilayer); + + const std::string layerName = x_layer.nameStr(); + const std::string layerType = x_layer.attr<std::string>(_Unicode(type)); + double layerThickness = x_layer.thickness(); + + double r_end = rCursor + layerThickness; + std::cout<<"===============>$ "<<layerName<<"\t"<<layerType + <<" thickness = "<<layerThickness / dd4hep::mm << "mm " + <<" inner radius = "<<rCursor / dd4hep::mm<<" mm" + <<" outer radius = "<<r_end /dd4hep::mm<<" mm" + <<std::endl; + + //-------------------------------------- + if(layerType == "Frame") + { + double phi_start = 0.; + double phi_end = 2*M_PI; + Tube ringSolid(rCursor, r_end, dz_Alframe/2., phi_start, phi_end) ; + Volume ringLog( layerName+"Log", ringSolid, materialAlframe) ; + pv = endcapLog.placeVolume( ringLog, Position(0., 0., -dz_Endpaltelength/2. + dz_Alframe/2.) ) ; + tpc.setVisAttributes(theDetector,"GrayVis",ringLog); + } + if(layerType == "Module") + { + int numberofModules = x_layer.repeat(); + double phi_start = x_layer.phi0_offset(); + double phiCursor = phi_start; + double phiModule = (2*M_PI*rCursor-numberofModules*ds_reinforce)/numberofModules/rCursor; + double phiReinforce = ds_reinforce/rCursor; + + //Construct each module + for(int k=0; k<numberofModules;++k) + { + Tube moduleSolid1(rCursor,r_end,dz_Endpaltelength/2.,phiCursor,phiCursor+phiModule); + std::string moduleLogName1 = layerName + _toString(k,"Log%00d"); + Volume moduleLog1(moduleLogName1,moduleSolid1,materialAir); + + double z_cursor = -dz_Endpaltelength/2.; + int m_sli = 0; + for(xml_coll_t sli(x_layer,_U(slice)); sli; ++sli,++m_sli) + { + xml_comp_t x_slice = sli; + double dz_modulepiece = sli.attr<double>(_Unicode(dz)); + std::string moduleSliceName = moduleLogName1 + _toString(m_sli,"slice%d"); + Material slice_mat = theDetector.material(x_slice.materialStr()); + + Tube moduleSliceSolid(rCursor,r_end,dz_modulepiece/2.,phiCursor,phiCursor+phiModule); + Volume moduleSliceLog(moduleSliceName,moduleSliceSolid,slice_mat); + + pv = moduleLog1.placeVolume(moduleSliceLog,Position(0.,0.,z_cursor+dz_modulepiece/2.)); + tpc.setVisAttributes(theDetector, "Invisible" , moduleSliceLog) ; + z_cursor += dz_modulepiece; + + if(z_cursor > dz_Endpaltelength/2.) + { + //std::cout<<" Warning ! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC Module- check your xml file - section <Endpalte>." <<std::endl; + throw " $!!! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC Module- check your xml file - component <Endpalte>."; + } + } + + pv = endcapLog.placeVolume(moduleLog1); + tpc.setVisAttributes(theDetector,"RedVis",moduleLog1); + + phiCursor = phiCursor+phiModule; + + //Construct the Al frame between each module + Tube moduleSolid2(rCursor,r_end,dz_Alframe/2.,phiCursor,phiCursor+phiReinforce); + std::string moduleLogName2 = layerName + _toString(k,"Log_rein%00d"); + Volume moduleLog2(moduleLogName2,moduleSolid2,materialAlframe); + pv = endcapLog.placeVolume(moduleLog2, Position(0., 0., -dz_Endpaltelength/2.+dz_Alframe/2.)); + tpc.setVisAttributes(theDetector,"GrayVis",moduleLog2); + + phiCursor = phiCursor+phiReinforce; + } + } + rCursor = r_end; + } + + double RadlenOfAl_Frame = materialAlframe->GetMaterial()->GetRadLen(); + std::cout << "================================================================"<< std::endl; + std::cout << "TPC_ModularEndcap_TDR_o1_v01: Endplate Al frame corresponds to " << (2. / RadlenOfAl_Frame*100)<< "% of a radiation length." << std::endl; + std::cout << "================================================================"<< std::endl; + } + //-------------------------------- TPCreadout construction ----------------------------------------// + if(types == "TPCreadout") + { + xml_dim_t dimReadout = x_section.dimensions(); + double dzReadout = dimReadout.z_length(); + Tube readoutSolid(dimReadout.rmin(),dimReadout.rmax(),dimReadout.z_length()/2.,phi1,phi1+phi2); + Volume readoutLog(volName+"Log",readoutSolid, materialT2Kgas); + + tpc.setVisAttributes(theDetector,"CyanVis",readoutLog); + + xml_dim_t posReadout = x_section.position(); + pv = tpc_motherLog.placeVolume(readoutLog,Transform3D(RotationY(0.),Position(0,0,posReadout.z()))); + pv = tpc_motherLog.placeVolume(readoutLog,Transform3D(RotationY(pi),Position(0,0,-posReadout.z()))); + + std::cout<<"=========ReadOut dim: "<< dimReadout.rmin() / dd4hep::mm<<" mm " + << dimReadout.rmax() / dd4hep::mm<<" mm " + << dzReadout / dd4hep::mm <<" mm "<<std::endl; + std::cout<<"=========ReadOut Z_pos: "<<posReadout.z() / dd4hep::mm << " mm "<<std::endl; + + int pieceCounter = 0; + double fracRadLengthReadout = 0; + double zCursor = -dzReadout/ 2; + + for(xml_coll_t li(x_section,_U(layer)); li;++li) + { + xml_comp_t x_layer( li ); + + const double dzPiece = x_layer.attr<double>(_Unicode(dz)); + Material pieceMaterial = theDetector.material( x_layer.materialStr() ); + Tube pieceSolid( dimReadout.rmin(),dimReadout.rmax(), dzPiece / 2, phi1, phi2); + Volume pieceLog ( _toString( pieceCounter ,"TPCReadoutPieceLog_%02d"), pieceSolid, pieceMaterial ) ; + + pieceLog.setVisAttributes(theDetector,x_layer.visStr()); + + pv = readoutLog.placeVolume( pieceLog , Position(0, 0, zCursor + dzPiece/2. ) ) ; + + ++pieceCounter; + fracRadLengthReadout += dzPiece / pieceMaterial->GetMaterial()->GetRadLen(); + zCursor += dzPiece; + + std::cout<<"==========> "<<dzPiece/dd4hep::mm<<" mm Material= "<<x_layer.materialStr()<<"\t" + <<"X0= "<<pieceMaterial->GetMaterial()->GetRadLen()/dd4hep::mm<<"\t" + <<dzPiece / pieceMaterial->GetMaterial()->GetRadLen() <<" X0"<< std::endl; + + if (zCursor > +dzReadout / 2) + { + //throw GeometryException( "TPC11: Overfull TPC readout - check your xml file - section <readout>." ) ; + //std::cout<<" TPC_ModularEndcap_TDR_o1_v01: Overfull TPC readout - check your xml file - component <TPCReadout>." <<std::endl; + throw " $!!! TPC_ModularEndcap_TDR_o1_v01: Overfull TPC readout - check your xml file - component <TPCReadout>."; + } + } + std::cout << "================================================================"<< std::endl; + std::cout << "TPC_ModularEndcap_TDR_o1_v01: Readout material corresponds to " << int(fracRadLengthReadout * 1000) / 10.0 << "% of a radiation length." << std::endl; + std::cout << "================================================================"<< std::endl; + } + + } + + //TPC data + FixedPadSizeTPCData* tpcData = new FixedPadSizeTPCData(); + tpcData->zHalf = dzTotal/2.; + tpcData->rMin = rInner; + tpcData->rMax = rOuter; + tpcData->innerWallThickness = drInnerWall; + tpcData->outerWallThickness = drOuterWall; + tpcData->rMinReadout = rInner + drInnerWall + drInnerServiceArea; + tpcData->rMaxReadout = rInner + drInnerWall + drInnerServiceArea + tpcnumberOfPadRows*tpcpadheight; + tpcData->maxRow = tpcnumberOfPadRows; + tpcData->padHeight = tpcpadheight; + tpcData->padWidth = tpcpadwidth; + tpcData->driftLength = dzTotal/2.- dz_Endplate - dz_Readout - dz_Cathode/2.0; // SJA: cathode has to be added as the sensitive region does not start at 0.00 + tpcData->zMinReadout = dz_Cathode/2.0; + + ConicalSupportData* supportData = new ConicalSupportData; + + ConicalSupportData::Section section0; + section0.rInner = rInner + drInnerWall; + section0.rOuter = rOuter - drOuterWall; + section0.zPos = dzTotal/2. - dz_Endplate - dz_Readout; + + ConicalSupportData::Section section1; + section1.rInner = rInner + drInnerWall; + section1.rOuter = rOuter - drOuterWall; + section1.zPos = dzTotal/2. - dz_Endplate; + + ConicalSupportData::Section section2; + section2.rInner = rInner ; + section2.rOuter = rOuter ; + section2.zPos = dzTotal/2.; + + supportData->sections.push_back(section0); + supportData->sections.push_back(section1); + supportData->sections.push_back(section2); + + + tpc.addExtension< FixedPadSizeTPCData >(tpcData); + tpc.addExtension< ConicalSupportData >(supportData); + + //tpc.setVisAttributes( theDetector, x_det.visStr(), envelope ); + tpc.setVisAttributes( theDetector, "TPCMotherVis1", envelope ); + // if( tpc.isValid() ) + // tpc.setPlacement(pv); + std::cout << "================================================================"<< std::endl; + std::cout << "TPC_ModularEndcap_TDR_o1_v01 Constructed!"<< std::endl; + std::cout << "================================================================"<< std::endl; + + return tpc; +} +DECLARE_DETELEMENT(TPC_ModularEndcap_o1_v01_wrapvolume,create_element) -- GitLab From bab6dd8399ccae5f50f38c1b0fed69716f1de681 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Mon, 23 Jun 2025 00:13:16 +0800 Subject: [PATCH 73/74] fix: always init track info --- Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp index 19046c54..ee4900df 100644 --- a/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/Edm4hepWriterAnaElemTool.cpp @@ -362,6 +362,13 @@ Edm4hepWriterAnaElemTool::PreUserTrackingAction(const G4Track* track) { int curtrkid = track->GetTrackID(); int curparid = track->GetParentID(); int pritrkid = curparid; + auto trackInfo = + static_cast<CommonUserTrackInfo *>(track->GetUserInformation()); + if (!trackInfo) { + // ä¸å½±å“,edm4heptool设置trackinfo是secondary,secondaryçš„preä¸ä¼šæ¯”primaryçš„postæ—© + trackInfo = new CommonUserTrackInfo(); + track->SetUserInformation(trackInfo); + } // if it is ancestor mode, then we need to check whether current track is associated // with MCParticle or not. -- GitLab From 4e12f99bb58f33bed209ea0b9642e78cf378dba7 Mon Sep 17 00:00:00 2001 From: Li Zhihao <lizhihao@ihep.ac.cn> Date: Wed, 23 Jul 2025 17:22:20 +0800 Subject: [PATCH 74/74] feat: add ecal entry info --- .../DetSimAna/src/ChronoAnaElemTool.cpp | 55 +++++++++++++++++-- Simulation/DetSimAna/src/ChronoAnaElemTool.h | 7 +++ 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp index 3481a186..2872f4c8 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.cpp @@ -105,12 +105,15 @@ StatusCode ChronoAnaElemTool::initNtuple() { .isSuccess(); suc &= m_ntuple->addItem("TrackNum", m_trackIdx, 0U, MAX_TRACK_NUM) .isSuccess(); - suc &= m_ntuple->addItem("TrackPx", m_trackIdx, m_trackPx); - suc &= m_ntuple->addItem("TrackPy", m_trackIdx, m_trackPy); - suc &= m_ntuple->addItem("TrackPz", m_trackIdx, m_trackPz); - suc &= m_ntuple->addItem("TrackX", m_trackIdx, m_trackX); - suc &= m_ntuple->addItem("TrackY", m_trackIdx, m_trackY); - suc &= m_ntuple->addItem("TrackZ", m_trackIdx, m_trackZ); + suc &= m_ntuple->addIndexedItem("TrackID", m_trackIdx, m_trackId); + suc &= m_ntuple->addIndexedItem("TrackParentID", m_trackIdx, + m_trackParentId); + suc &= m_ntuple->addIndexedItem("TrackPx", m_trackIdx, m_trackPx); + suc &= m_ntuple->addIndexedItem("TrackPy", m_trackIdx, m_trackPy); + suc &= m_ntuple->addIndexedItem("TrackPz", m_trackIdx, m_trackPz); + suc &= m_ntuple->addIndexedItem("TrackX", m_trackIdx, m_trackX); + suc &= m_ntuple->addIndexedItem("TrackY", m_trackIdx, m_trackY); + suc &= m_ntuple->addIndexedItem("TrackZ", m_trackIdx, m_trackZ); suc &= m_ntuple->addIndexedItem("TrackLengths", m_trackIdx, m_trackLength) .isSuccess(); suc &= m_ntuple->addIndexedItem("TrackTimes", m_trackIdx, m_trackTime) @@ -153,6 +156,24 @@ StatusCode ChronoAnaElemTool::initNtuple() { ->addIndexedItem("TrackSubdetSequence", m_trackIdx, MAX_SUBDET_SEQUENCE_NUM, m_trackSubdetSequence) .isSuccess(); + // ecal enter point + suc &= m_ntuple->addIndexedItem("EcalEntryPx", m_trackIdx, m_EcalEntryPx); + suc &= m_ntuple->addIndexedItem("EcalEntryPy", m_trackIdx, m_EcalEntryPy); + suc &= m_ntuple->addIndexedItem("EcalEntryPz", m_trackIdx, m_EcalEntryPz); + suc &= m_ntuple->addIndexedItem("EcalEntryX", m_trackIdx, m_EcalEntryX); + suc &= m_ntuple->addIndexedItem("EcalEntryY", m_trackIdx, m_EcalEntryY); + suc &= m_ntuple->addIndexedItem("EcalEntryZ", m_trackIdx, m_EcalEntryZ); + suc &= + m_ntuple->addIndexedItem("EcalEntryEnergy", m_trackIdx, m_EcalEntryE) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("EcalBarrelEntryTimes", m_trackIdx, + m_trackEcalBarrelEntryTimes) + .isSuccess(); + suc &= m_ntuple + ->addIndexedItem("EcalEndcapEntryTimes", m_trackIdx, + m_trackEcalEndcapEntryTimes) + .isSuccess(); } else { error() << "Cannot book N-tuple." << endmsg; return StatusCode::FAILURE; @@ -229,6 +250,8 @@ void ChronoAnaElemTool::PreUserTrackingAction(const G4Track *track) { trackInfo->SetChronoTrackIdx(chronoTrackIdx); const auto &mom = track->GetMomentum(); const auto &pos = track->GetPosition(); + m_trackId[chronoTrackIdx] = track->GetTrackID(); + m_trackParentId[chronoTrackIdx] = track->GetParentID(); m_trackPx[chronoTrackIdx] = mom.x(); m_trackPy[chronoTrackIdx] = mom.y(); m_trackPz[chronoTrackIdx] = mom.z(); @@ -310,6 +333,26 @@ void ChronoAnaElemTool::UserSteppingAction(const G4Step *step) { trackInfo->SetTrackLength(currentTrackLength); trackInfo->SetStepNum(currentStep); trackInfo->SetTrackSubdetChangeTime(stop); + // if changed into ECAL + if (newSubdet == EcalBarrelIndex || newSubdet == EcalEndcapIndex) { + auto track_idx = trackInfo->GetChronoTrackIdx(); + if ((m_trackEcalBarrelEntryTimes[track_idx] == 0) && + (m_trackEcalEndcapEntryTimes[track_idx] == 0)) { + auto entry_pos = step->GetPostStepPoint()->GetPosition(); + auto entry_mom = step->GetPostStepPoint()->GetMomentum(); + m_EcalEntryX[track_idx] = entry_pos.x(); + m_EcalEntryY[track_idx] = entry_pos.y(); + m_EcalEntryZ[track_idx] = entry_pos.z(); + m_EcalEntryPx[track_idx] = entry_mom.x(); + m_EcalEntryPy[track_idx] = entry_mom.y(); + m_EcalEntryPz[track_idx] = entry_mom.z(); + m_EcalEntryE[track_idx] = step->GetPostStepPoint()->GetTotalEnergy(); + } + auto &entryTimes = (newSubdet == EcalBarrelIndex) + ? m_trackEcalBarrelEntryTimes + : m_trackEcalEndcapEntryTimes; + entryTimes[track_idx]++; + } } } } diff --git a/Simulation/DetSimAna/src/ChronoAnaElemTool.h b/Simulation/DetSimAna/src/ChronoAnaElemTool.h index 1ae63488..7a402a9f 100644 --- a/Simulation/DetSimAna/src/ChronoAnaElemTool.h +++ b/Simulation/DetSimAna/src/ChronoAnaElemTool.h @@ -60,6 +60,8 @@ private: StatusCode initSubdetVolumes(); static constexpr uint8_t UnknownIndex = 0; static constexpr uint8_t PWorldIndex = 1; + static constexpr uint8_t EcalBarrelIndex = 13; + static constexpr uint8_t EcalEndcapIndex = 14; std::vector<std::string> m_subdetNames; std::unordered_map<G4LogicalVolume *, uint8_t> m_logicalVolumePtrToSubdetIdx; @@ -70,12 +72,17 @@ private: NanoClock::time_point m_track_start; NTuple::Item<uint> m_trackIdx; + NTuple::Array<int> m_trackId, m_trackParentId; NTuple::Array<double> m_trackPx, m_trackPy, m_trackPz; NTuple::Array<double> m_trackX, m_trackY, m_trackZ; NTuple::Array<double> m_trackLength, m_trackE, m_trackdE; NTuple::Array<int> m_trackPDGId, m_trackStepNum; NTuple::Array<time_t> m_trackTime; NTuple::Array<uint8_t> m_trackStartSubdet, m_trackEndSubdet; + // ECAL Enter point + NTuple::Array<double> m_EcalEntryPx, m_EcalEntryPy, m_EcalEntryPz, m_EcalEntryE; + NTuple::Array<double> m_EcalEntryX, m_EcalEntryY, m_EcalEntryZ; + NTuple::Array<int> m_trackEcalBarrelEntryTimes, m_trackEcalEndcapEntryTimes; static constexpr uint MAX_SUBDET_NUM = 27; NTuple::Matrix<time_t> m_trackTimePerSubdet; -- GitLab