From 9e9ebab4fe41a95c0dd1fc6b35e68964442e6120 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Tue, 24 Jun 2025 11:03:52 -0500 Subject: [PATCH 1/3] feat: add performance profiler as stepping action --- src/dd4pod/python/npsim.py | 4 + src/plugins/CMakeLists.txt | 1 + .../npdet/PerformanceProfileSteppingAction.h | 95 +++++++++++++++++++ .../src/PerformanceProfileSteppingAction.cxx | 5 + 4 files changed, 105 insertions(+) create mode 100644 src/plugins/include/npdet/PerformanceProfileSteppingAction.h create mode 100644 src/plugins/src/PerformanceProfileSteppingAction.cxx diff --git a/src/dd4pod/python/npsim.py b/src/dd4pod/python/npsim.py index ad3ea34..dfd4f5b 100755 --- a/src/dd4pod/python/npsim.py +++ b/src/dd4pod/python/npsim.py @@ -93,6 +93,10 @@ def setupCerenkov(kernel): } ] + RUNNER.action.step = { + "name": "PerformanceProfileSteppingAction" + } + try: sys.exit(RUNNER.run()) except NameError as e: diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index 6216894..a7a4de1 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -5,6 +5,7 @@ dd4hep_add_plugin(NPDetPlugins src/EICInteractionVertexBoost.cxx src/EICInteractionVertexSmear.cxx src/OpticalPhotonEfficiencyStackingAction.cxx + src/PerformanceProfileSteppingAction.cxx INCLUDES $ USES DD4hep::DDCore DD4hep::DDG4 ) diff --git a/src/plugins/include/npdet/PerformanceProfileSteppingAction.h b/src/plugins/include/npdet/PerformanceProfileSteppingAction.h new file mode 100644 index 0000000..686a859 --- /dev/null +++ b/src/plugins/include/npdet/PerformanceProfileSteppingAction.h @@ -0,0 +1,95 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +#ifndef PERFORMANCEPROFILESTEPPINGACTION_H +#define PERFORMANCEPROFILESTEPPINGACTION_H + +#include "DDG4/Geant4SteppingAction.h" +#include "G4Step.hh" + +#include +using namespace std::chrono_literals; + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit + namespace sim { + + class PerformanceProfileSteppingAction : public Geant4SteppingAction { + public: + /// Standard constructor with initializing arguments + PerformanceProfileSteppingAction(Geant4Context* c, const std::string& n) : Geant4SteppingAction(c, n) {}; + /// Default destructor + virtual ~PerformanceProfileSteppingAction() { + std::chrono::milliseconds total_duration = std::chrono::milliseconds::zero(); + for (auto& [track_id, duration] : m_duration) { + if (std::chrono::abs(duration) > std::chrono::nanoseconds(10ms)) { + auto p0 = m_prestep_position[track_id] / CLHEP::mm; + auto p1 = m_poststep_position[track_id] / CLHEP::mm; + auto E1 = m_pdg[track_id] == -22 ? m_poststep_energy[track_id] / CLHEP::eV + : m_poststep_energy[track_id] / CLHEP::MeV; + printout(INFO, name(), "track %d (%d): %ld ms (%f %f %f mm -> %f %f %f mm, %f (M?)eV)", track_id, + m_pdg[track_id], std::chrono::duration_cast(duration).count(), p0.x(), + p0.y(), p0.z(), p1.x(), p1.y(), p1.z(), E1); + } + total_duration += std::chrono::duration_cast(duration); + } + printout(INFO, name(), "total duration: %ld ms", total_duration); + }; + /// User stepping callback + void operator()(const G4Step* step, G4SteppingManager*) override { + auto* track = step->GetTrack(); + auto* particle = track->GetParticleDefinition(); + auto pdg = particle->GetPDGEncoding(); + auto track_id = track->GetTrackID(); + auto* prestep [[maybe_unused]] = step->GetPreStepPoint(); + auto prestep_position = prestep->GetPosition(); + auto* poststep [[maybe_unused]] = step->GetPostStepPoint(); + auto poststep_position = poststep->GetPosition(); + auto poststep_energy = poststep->GetTotalEnergy(); + auto firststep [[maybe_unused]] = step->IsFirstStepInVolume(); + auto laststep [[maybe_unused]] = step->IsLastStepInVolume(); + if (track_id == m_previous_track_id) { + m_duration[track_id] += (std::chrono::steady_clock::now() - m_previous_timepoint); + m_poststep_position[track_id] = poststep_position; + m_poststep_energy[track_id] = poststep_energy; + } else { + if (track_id == 0) { + m_duration.clear(); + m_pdg.clear(); + m_prestep_position.clear(); + m_poststep_position.clear(); + m_poststep_energy.clear(); + printout(INFO, name(), "new event"); + } + m_previous_track_id = track_id; + m_pdg[track_id] = pdg; + m_duration[track_id] = std::chrono::nanoseconds::zero(); + m_prestep_position[track_id] = prestep_position; + } + m_previous_timepoint = std::chrono::steady_clock::now(); + }; + + private: + std::map m_duration; + std::map m_pdg; + std::map m_prestep_position; + std::map m_poststep_position; + std::map m_poststep_energy; + G4int m_previous_track_id{0}; + std::chrono::time_point m_previous_timepoint; + }; + } // End namespace sim +} // End namespace dd4hep + +#endif // PERFORMANCEPROFILESTEPPINGACTION_H diff --git a/src/plugins/src/PerformanceProfileSteppingAction.cxx b/src/plugins/src/PerformanceProfileSteppingAction.cxx new file mode 100644 index 0000000..243128f --- /dev/null +++ b/src/plugins/src/PerformanceProfileSteppingAction.cxx @@ -0,0 +1,5 @@ +#include "DDG4/Factories.h" + +#include "npdet/PerformanceProfileSteppingAction.h" + +DECLARE_GEANT4ACTION(PerformanceProfileSteppingAction) From 52e612b29b6f95a56492e99d603e36f058f7cc17 Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Tue, 24 Jun 2025 18:42:33 -0500 Subject: [PATCH 2/3] feat: fill xy and zr histograms weighted with time --- src/plugins/CMakeLists.txt | 2 +- .../npdet/PerformanceProfileSteppingAction.h | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt index a7a4de1..fa1ec31 100644 --- a/src/plugins/CMakeLists.txt +++ b/src/plugins/CMakeLists.txt @@ -7,7 +7,7 @@ dd4hep_add_plugin(NPDetPlugins src/OpticalPhotonEfficiencyStackingAction.cxx src/PerformanceProfileSteppingAction.cxx INCLUDES $ - USES DD4hep::DDCore DD4hep::DDG4 + USES DD4hep::DDCore DD4hep::DDG4 ROOT::Core ) install(TARGETS NPDetPlugins diff --git a/src/plugins/include/npdet/PerformanceProfileSteppingAction.h b/src/plugins/include/npdet/PerformanceProfileSteppingAction.h index 686a859..c1c1044 100644 --- a/src/plugins/include/npdet/PerformanceProfileSteppingAction.h +++ b/src/plugins/include/npdet/PerformanceProfileSteppingAction.h @@ -15,9 +15,10 @@ #include "DDG4/Geant4SteppingAction.h" #include "G4Step.hh" +#include "TFile.h" +#include "TH2F.h" #include -using namespace std::chrono_literals; /// Namespace for the AIDA detector description toolkit namespace dd4hep { @@ -25,6 +26,8 @@ namespace dd4hep { /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit namespace sim { + using namespace std::chrono_literals; + class PerformanceProfileSteppingAction : public Geant4SteppingAction { public: /// Standard constructor with initializing arguments @@ -45,6 +48,10 @@ namespace dd4hep { total_duration += std::chrono::duration_cast(duration); } printout(INFO, name(), "total duration: %ld ms", total_duration); + TFile f("histos.root", "recreate"); + m_xy.Write(); + m_zr.Write(); + f.Close(); }; /// User stepping callback void operator()(const G4Step* step, G4SteppingManager*) override { @@ -63,6 +70,8 @@ namespace dd4hep { m_duration[track_id] += (std::chrono::steady_clock::now() - m_previous_timepoint); m_poststep_position[track_id] = poststep_position; m_poststep_energy[track_id] = poststep_energy; + m_xy.Fill(poststep_position.x(), poststep_position.y(), m_duration[track_id].count()); + m_zr.Fill(poststep_position.z(), std::hypot(poststep_position.x(), poststep_position.y()), m_duration[track_id].count()); } else { if (track_id == 0) { m_duration.clear(); @@ -88,6 +97,8 @@ namespace dd4hep { std::map m_poststep_energy; G4int m_previous_track_id{0}; std::chrono::time_point m_previous_timepoint; + TH2F m_xy{"m_xy", "xy", 100, -3.5*CLHEP::m, +3.5*CLHEP::m, 100, -3.5*CLHEP::m, +3.5*CLHEP::m}; + TH2F m_zr{"m_zr", "zr", 100, -3.5*CLHEP::m, +3.5*CLHEP::m, 100, 0., +7.0*CLHEP::m}; }; } // End namespace sim } // End namespace dd4hep From 700371ab3c8dbb788e45d583db9f1090bb67f84c Mon Sep 17 00:00:00 2001 From: Wouter Deconinck Date: Tue, 24 Jun 2025 19:50:34 -0500 Subject: [PATCH 3/3] feat: fill better xy and rz histograms --- .../npdet/PerformanceProfileSteppingAction.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/plugins/include/npdet/PerformanceProfileSteppingAction.h b/src/plugins/include/npdet/PerformanceProfileSteppingAction.h index c1c1044..8700c63 100644 --- a/src/plugins/include/npdet/PerformanceProfileSteppingAction.h +++ b/src/plugins/include/npdet/PerformanceProfileSteppingAction.h @@ -55,6 +55,9 @@ namespace dd4hep { }; /// User stepping callback void operator()(const G4Step* step, G4SteppingManager*) override { + std::chrono::nanoseconds step_duration = std::chrono::duration_cast(std::chrono::steady_clock::now() - m_previous_timepoint); + + // Get step info auto* track = step->GetTrack(); auto* particle = track->GetParticleDefinition(); auto pdg = particle->GetPDGEncoding(); @@ -66,13 +69,16 @@ namespace dd4hep { auto poststep_energy = poststep->GetTotalEnergy(); auto firststep [[maybe_unused]] = step->IsFirstStepInVolume(); auto laststep [[maybe_unused]] = step->IsLastStepInVolume(); + if (track_id == m_previous_track_id) { - m_duration[track_id] += (std::chrono::steady_clock::now() - m_previous_timepoint); + // Current track + m_duration[track_id] += step_duration; m_poststep_position[track_id] = poststep_position; m_poststep_energy[track_id] = poststep_energy; - m_xy.Fill(poststep_position.x(), poststep_position.y(), m_duration[track_id].count()); - m_zr.Fill(poststep_position.z(), std::hypot(poststep_position.x(), poststep_position.y()), m_duration[track_id].count()); + m_xy.Fill(poststep_position.x(), poststep_position.y(), step_duration.count()); + m_zr.Fill(poststep_position.z(), std::hypot(poststep_position.x(), poststep_position.y()), step_duration.count()); } else { + // New track if (track_id == 0) { m_duration.clear(); m_pdg.clear(); @@ -86,6 +92,7 @@ namespace dd4hep { m_duration[track_id] = std::chrono::nanoseconds::zero(); m_prestep_position[track_id] = prestep_position; } + m_previous_timepoint = std::chrono::steady_clock::now(); }; @@ -97,8 +104,8 @@ namespace dd4hep { std::map m_poststep_energy; G4int m_previous_track_id{0}; std::chrono::time_point m_previous_timepoint; - TH2F m_xy{"m_xy", "xy", 100, -3.5*CLHEP::m, +3.5*CLHEP::m, 100, -3.5*CLHEP::m, +3.5*CLHEP::m}; - TH2F m_zr{"m_zr", "zr", 100, -3.5*CLHEP::m, +3.5*CLHEP::m, 100, 0., +7.0*CLHEP::m}; + TH2F m_xy{"m_xy", "xy", 100, -3.*CLHEP::m, +3.*CLHEP::m, 100, -3.*CLHEP::m, +3.*CLHEP::m}; + TH2F m_zr{"m_zr", "zr", 100, -4.5*CLHEP::m, +5.5*CLHEP::m, 100, 0., +3.*CLHEP::m}; }; } // End namespace sim } // End namespace dd4hep