From a2afbd540d5844bfbb83fb2b5e925d7072145af2 Mon Sep 17 00:00:00 2001 From: Markus Frank <Markus.Frank@cern.ch> Date: Wed, 22 Mar 2023 16:45:17 +0100 Subject: [PATCH] Allow users to add track user information to G4 tracks, which then moves to Geant4Particle for saving --- DDG4/include/DDG4/Geant4Handle.h | 4 +- DDG4/include/DDG4/Geant4Particle.h | 40 +++++-- DDG4/include/DDG4/Geant4ParticleInformation.h | 107 ++++++++++++++++++ DDG4/src/Geant4ParticleHandler.cpp | 12 +- examples/DDG4_MySensDet/src/MyTrackerHit.h | 18 +++ .../DDG4_MySensDet/src/MyTrackerSDAction.cpp | 13 ++- 6 files changed, 177 insertions(+), 17 deletions(-) create mode 100644 DDG4/include/DDG4/Geant4ParticleInformation.h diff --git a/DDG4/include/DDG4/Geant4Handle.h b/DDG4/include/DDG4/Geant4Handle.h index 9386354e6..1fb061774 100644 --- a/DDG4/include/DDG4/Geant4Handle.h +++ b/DDG4/include/DDG4/Geant4Handle.h @@ -14,11 +14,11 @@ #ifndef DDG4_GEANT4HANDLE_H #define DDG4_GEANT4HANDLE_H -// Framework include files +/// Framework include files #include "DD4hep/ComponentProperties.h" #include "DD4hep/Detector.h" -// C/C++ include files +/// C/C++ include files #include <string> #include <memory> diff --git a/DDG4/include/DDG4/Geant4Particle.h b/DDG4/include/DDG4/Geant4Particle.h index 2c3cb7171..06f714471 100644 --- a/DDG4/include/DDG4/Geant4Particle.h +++ b/DDG4/include/DDG4/Geant4Particle.h @@ -94,8 +94,6 @@ namespace dd4hep { G4PARTICLE_LAST_NOTHING = 1<<31 }; - - /// Data structure to store the MC particle information /** * \author M.Frank @@ -106,29 +104,47 @@ namespace dd4hep { public: typedef std::set<int> Particles; /// Reference counter - int ref = 0; //! not persistent - int id = 0; - int originalG4ID = 0; //! not persistent - int g4Parent = 0, reason = 0, mask = 0; - int steps = 0, secondaries = 0, pdgID = 0; - int status = 0, colorFlow[2] { 0, 0 }; + int ref { 0 }; //! not persistent + int id { 0 }; + int originalG4ID { 0 }; //! not persistent + int g4Parent { 0 }; + int reason { 0 }; + int mask { 0 }; + int steps { 0 }; + int secondaries { 0 }; + int pdgID { 0 }; + int status { 0 }; + int colorFlow[2] { 0, 0 }; unsigned short genStatus { 0 }; char charge { 0 }; char _spare[1] { 0 }; float spin[3] { 0E0,0E0,0E0 }; // 12 ints + 4 bytes + 3 floats should be aligned to 8 bytes.... + /// The starting vertex double vsx = 0E0, vsy = 0E0, vsz = 0E0; + /// The end vertex double vex = 0E0, vey = 0E0, vez = 0E0; + /// The track momentum at the start vertex double psx = 0E0, psy = 0E0, psz = 0E0; + /// The track momentum at the end vertex double pex = 0E0, pey = 0E0, pez = 0E0; - double mass = 0E0, time = 0E0, properTime = 0E0; - /// The list of daughters of this MC particle + /// Particle mass + double mass { 0E0 }; + /// Particle creation time + double time { 0E0 }; + /// Proper time + double properTime { 0E0 }; + /// The list of parents of this MC particle Particles parents; + /// The list of daughters of this MC particle Particles daughters; /// User data extension if required - dd4hep_ptr<ParticleExtension> extension; //! not persisten. ROOT cannot handle + dd4hep_ptr<ParticleExtension> extension { }; + /// Reference to the G4VProcess, which created this track const G4VProcess *process = 0; //! not persistent + + public: /// Default constructor Geant4Particle(); /// Constructor with ID initialization @@ -169,6 +185,7 @@ namespace dd4hep { protected: /// Particle pointer Geant4Particle* particle; + public: /// Default constructor Geant4ParticleHandle(Geant4Particle* part); @@ -325,6 +342,7 @@ namespace dd4hep { /// Map associating the G4Track identifiers with identifiers of existing MCParticles TrackEquivalents equivalentTracks; + public: /// Default constructor Geant4ParticleMap() {} /// Default destructor diff --git a/DDG4/include/DDG4/Geant4ParticleInformation.h b/DDG4/include/DDG4/Geant4ParticleInformation.h new file mode 100644 index 000000000..f4404ed34 --- /dev/null +++ b/DDG4/include/DDG4/Geant4ParticleInformation.h @@ -0,0 +1,107 @@ +//========================================================================== +// 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 DDG4_GEANT4PARTICLEINFORMATION_H +#define DDG4_GEANT4PARTICLEINFORMATION_H + +/// Framework include files +#include <DDG4/Geant4Particle.h> + +/// Geant4 include files +#include <G4VUserTrackInformation.hh> + +/// C/C++ include files +#include <string> +#include <memory> + + +/// Namespace for the AIDA detector description toolkit +namespace dd4hep { + + /// Namespace for the Geant4 based simulation part of the AIDA detector description toolkit + namespace sim { + + /// Wrapper to store user information in a G4Track. + /** Wrapper to store user information in a G4Track. + * The data of type ParticleExtension is moved from the G4Track to the + * Geant4Particle in the Geant4ParticleHandler if present. + * This automatically make the G4Track instance persistent as a + * Geant4Particle. + * Hence: Be careful to not assign the entity by default! + * + * The data in the subclass of ParticleExtension defined by the user + * requires a dictionary to be stored to ROOT. + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class Geant4ParticleInformation : public G4VUserTrackInformation { + /// Keep track of the user data + std::unique_ptr<ParticleExtension> extension; + + public: + /// Default Constructor + Geant4ParticleInformation() = default; + /// Initializing Constructor + template <typename EXTENSION_TYPE> + Geant4ParticleInformation(EXTENSION_TYPE* data); + /// Initializing Constructor + template <typename EXTENSION_TYPE> + Geant4ParticleInformation(std::unique_ptr<EXTENSION_TYPE>&& data); + /// Move constructor + Geant4ParticleInformation(Geant4ParticleInformation&& copy) = default; + /// Disable copy constructor + Geant4ParticleInformation(const Geant4ParticleInformation& copy) = delete; + /// Move assignemtn operator + Geant4ParticleInformation& operator=(Geant4ParticleInformation&& copy) = default; + /// Disable copy assignment + Geant4ParticleInformation& operator=(const Geant4ParticleInformation& copy) = delete; + /// Default destructor + virtual ~Geant4ParticleInformation() = default; + + /// Attach information + void set(ParticleExtension* data) { + this->extension.reset(data); + } + /// Attach information + template <typename EXTENSION_TYPE> void set(std::unique_ptr<EXTENSION_TYPE>&& data) { + this->extension = std::move(data); + } + template <typename EXTENSION_TYPE> EXTENSION_TYPE* get() { + return dynamic_cast<EXTENSION_TYPE*>(this->extension.get()); + } + ParticleExtension* get() { + return this->extension.get(); + } + ParticleExtension* release() { + return this->extension.release(); + } + }; + + /// Initializing Constructor + template <typename EXTENSION_TYPE> inline + Geant4ParticleInformation::Geant4ParticleInformation(std::unique_ptr<EXTENSION_TYPE>&& data) + : extension(std::move(data)) + { + } + + /// Initializing Constructor + template <typename EXTENSION_TYPE> inline + Geant4ParticleInformation::Geant4ParticleInformation(EXTENSION_TYPE* data) + : extension(data) + { + } + + } // End namespace sim +} // End namespace dd4hep +#endif /* DDG4_GEANT4PARTICLEINFORMATION_H */ diff --git a/DDG4/src/Geant4ParticleHandler.cpp b/DDG4/src/Geant4ParticleHandler.cpp index 79d4719ad..36e686e69 100644 --- a/DDG4/src/Geant4ParticleHandler.cpp +++ b/DDG4/src/Geant4ParticleHandler.cpp @@ -21,6 +21,7 @@ #include <DDG4/Geant4TrackingAction.h> #include <DDG4/Geant4SteppingAction.h> #include <DDG4/Geant4ParticleHandler.h> +#include <DDG4/Geant4ParticleInformation.h> #include <DDG4/Geant4UserParticleHandler.h> // Geant4 include files @@ -351,15 +352,18 @@ void Geant4ParticleHandler::end(const G4Track* track) { if ( m_userHandler ) { m_userHandler->end(track, m_currTrack); } - + // These are candidate tracks with a probability to be stored due to their properties: // - primary particle // - hits created // - secondaries // - above energy threshold // - to be kept due to creator process + // - to be kept due to user information of type 'Geant4ParticleInformation' stored in the G4Track // - if ( !mask.isNull() ) { + Geant4ParticleInformation* track_info = + dynamic_cast<Geant4ParticleInformation*>(track->GetUserInformation()); + if ( !mask.isNull() || track_info ) { m_equivalentTracks[g4_id] = g4_id; ParticleMap::iterator ip = m_particleMap.find(g4_id); if ( mask.isSet(G4PARTICLE_PRIMARY) ) { @@ -369,6 +373,10 @@ void Geant4ParticleHandler::end(const G4Track* track) { Particle* part = 0; if ( ip==m_particleMap.end() ) part = m_particleMap[g4_id] = new Particle(); else part = (*ip).second; + if ( track_info ) { + mask.set(G4PARTICLE_KEEP_USER); + part->extension.reset(track_info->release()); + } part->get_data(m_currTrack); } else { diff --git a/examples/DDG4_MySensDet/src/MyTrackerHit.h b/examples/DDG4_MySensDet/src/MyTrackerHit.h index 23d397077..18f7ad9e2 100644 --- a/examples/DDG4_MySensDet/src/MyTrackerHit.h +++ b/examples/DDG4_MySensDet/src/MyTrackerHit.h @@ -15,6 +15,7 @@ /// Framework include files #include "DDG4/Geant4Data.h" +#include "DDG4/Geant4Particle.h" namespace SomeExperiment { @@ -56,6 +57,21 @@ namespace SomeExperiment { void copyFrom(const MyTrackerHit& c); }; + /// User data to be attached to the output MC particle + /** + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class ParticleUserData : public dd4hep::sim::ParticleExtension { + public: + /// Some data item to be attached to the Geant4 particle object + double absolute_momentum { 0e0 }; + + public: + using dd4hep::sim::ParticleExtension::ParticleExtension; + }; + /// Helper to dump data file /** * Usage: @@ -84,7 +100,9 @@ namespace SomeExperiment { #pragma link C++ namespace dd4hep::sim; #pragma link C++ namespace SomeExperiment; #pragma link C++ class SomeExperiment::MyTrackerHit+; +#pragma link C++ class SomeExperiment::ParticleUserData+; #pragma link C++ class SomeExperiment::Dump; + #endif #endif // EXAMPLES_DDG4_MYSENSDET_SRC_MYTRACKERHIT_H diff --git a/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp b/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp index 7c34c2752..1d98b8edc 100644 --- a/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp +++ b/examples/DDG4_MySensDet/src/MyTrackerSDAction.cpp @@ -13,8 +13,9 @@ // Framework include files #include "MyTrackerHit.h" -#include "DDG4/Geant4SensDetAction.inl" -#include "DDG4/Factories.h" +#include <DDG4/Geant4SensDetAction.inl> +#include <DDG4/Geant4ParticleInformation.h> +#include <DDG4/Factories.h> namespace SomeExperiment { @@ -86,6 +87,14 @@ namespace dd4hep { // Do something with my personal data (can be also something more clever ;-): m_userData.integratedDeposit += contrib.deposit; ++m_userData.mumDeposits; + + /// Let's play with the Geant4TrackInformation + /// See issue https://github.com/AIDASoft/DD4hep/issues/1073 + if ( nullptr == h.track->GetUserInformation() ) { + auto data = std::make_unique<ParticleUserData>(); + data->absolute_momentum = h.track->GetMomentum().mag(); + h.track->SetUserInformation(new Geant4ParticleInformation(std::move(data))); + } return true; } -- GitLab