diff --git a/DDG4/src/Geant4ActionPhase.cpp b/DDG4/src/Geant4ActionPhase.cpp index 68d53e5af0365d00ea5a03d90dec181fdaaa90a4..78f42f9868e991e7e5d40368b2708c4e29032d69 100644 --- a/DDG4/src/Geant4ActionPhase.cpp +++ b/DDG4/src/Geant4ActionPhase.cpp @@ -96,6 +96,7 @@ class G4TouchableHistory; #include "DDG4/Geant4EventAction.h" #include "DDG4/Geant4TrackingAction.h" #include "DDG4/Geant4SteppingAction.h" +#include "DDG4/Geant4StackingAction.h" #include "DDG4/Geant4GeneratorAction.h" namespace dd4hep { namespace sim { @@ -103,6 +104,10 @@ namespace dd4hep { void Geant4ActionPhase::call() { this->execute(0); } + /// Callback in Begin stacking action + template <> void Geant4ActionPhase::call(G4StackManager* stackManager) { + this->execute((const void**) &stackManager); + } /// Callback in BeginRun/EndRun template <> void Geant4ActionPhase::call<const G4Run*>(const G4Run* run) { this->execute((const void**) &run); diff --git a/DDG4/src/Geant4Exec.cpp b/DDG4/src/Geant4Exec.cpp index bfad2896e754fc620b397f0f7f89d65e815dee37..949d6aa0860fd1869a49da4dd8584fdea3821275 100644 --- a/DDG4/src/Geant4Exec.cpp +++ b/DDG4/src/Geant4Exec.cpp @@ -250,12 +250,18 @@ namespace dd4hep { virtual ~Geant4UserStackingAction() { } /// New-stage callback - virtual void NewStage() final { - m_sequence->newStage(); + virtual void NewStage() override final { + m_sequence->newStage(stackManager); } /// Preparation callback - virtual void PrepareNewEvent() final { - m_sequence->prepare(); + virtual void PrepareNewEvent() override final { + m_sequence->prepare(stackManager); + } + virtual G4ClassificationOfNewTrack ClassifyNewTrack(const G4Track* track) override final { + auto ret = m_sequence->classifyNewTrack(stackManager, track); + if ( ret.type != NoTrackClassification ) + return ret.value; + return this->G4UserStackingAction::ClassifyNewTrack(track); } }; diff --git a/DDG4/src/Geant4StackingAction.cpp b/DDG4/src/Geant4StackingAction.cpp index b229d2487634ea82c6d6e6116a1a159323b4f2fa..985d951cb586a1b80fa8b4ad4e7de2aa9128de9c 100644 --- a/DDG4/src/Geant4StackingAction.cpp +++ b/DDG4/src/Geant4StackingAction.cpp @@ -38,6 +38,13 @@ Geant4StackingAction::~Geant4StackingAction() { InstanceCount::decrement(this); } +/// Classify new track: The first call in the sequence returning non-null pointer wins! +TrackClassification +Geant4StackingAction::classifyNewTrack(G4StackManager* /* manager */, + const G4Track* /* track */) { + return TrackClassification(); +} + /// Standard constructor Geant4SharedStackingAction::Geant4SharedStackingAction(Geant4Context* ctxt, const string& nam) : Geant4StackingAction(ctxt, nam), m_action(0) @@ -68,25 +75,38 @@ void Geant4SharedStackingAction::use(Geant4StackingAction* action) { } /// Begin-of-stacking callback -void Geant4SharedStackingAction::newStage() { +void Geant4SharedStackingAction::newStage(G4StackManager* stackManager) { if ( m_action ) { G4AutoLock protection_lock(&action_mutex); { ContextSwap swap(m_action,context()); - m_action->newStage(); + m_action->newStage(stackManager); } } } /// End-of-stacking callback -void Geant4SharedStackingAction::prepare() { +void Geant4SharedStackingAction::prepare(G4StackManager* stackManager) { if ( m_action ) { G4AutoLock protection_lock(&action_mutex); { ContextSwap swap(m_action,context()); - m_action->prepare(); + m_action->prepare(stackManager); } } } +/// Classify new track with delegation +TrackClassification +Geant4SharedStackingAction::classifyNewTrack(G4StackManager* stackManager, + const G4Track* track) { + if ( m_action ) { + G4AutoLock protection_lock(&action_mutex); { + ContextSwap swap(m_action,context()); + return m_action->classifyNewTrack(stackManager, track); + } + } + return {}; +} + /// Standard constructor Geant4StackingActionSequence::Geant4StackingActionSequence(Geant4Context* ctxt, const string& nam) : Geant4Action(ctxt, nam) { @@ -130,13 +150,26 @@ Geant4StackingAction* Geant4StackingActionSequence::get(const string& nam) const } /// Pre-track action callback -void Geant4StackingActionSequence::newStage() { - m_actors(&Geant4StackingAction::newStage); - m_newStage(); +void Geant4StackingActionSequence::newStage(G4StackManager* stackManager) { + m_actors(&Geant4StackingAction::newStage, stackManager); + m_newStage(stackManager); } /// Post-track action callback -void Geant4StackingActionSequence::prepare() { - m_actors(&Geant4StackingAction::prepare); - m_prepare(); +void Geant4StackingActionSequence::prepare(G4StackManager* stackManager) { + m_actors(&Geant4StackingAction::prepare, stackManager); + m_prepare(stackManager); +} + +/// Classify new track: The first call in the sequence returning non-null pointer wins! +TrackClassification +Geant4StackingActionSequence::classifyNewTrack(G4StackManager* stackManager, + const G4Track* track) { + for( auto a : m_actors ) { + auto ret = a->classifyNewTrack(stackManager, track); + if ( ret.type != NoTrackClassification ) { + return ret; + } + } + return {}; } diff --git a/examples/DDG4/scripts/TestStacking.py b/examples/DDG4/scripts/TestStacking.py new file mode 100644 index 0000000000000000000000000000000000000000..c2f4bde092548000557642e8b7c8a92fbbd00873 --- /dev/null +++ b/examples/DDG4/scripts/TestStacking.py @@ -0,0 +1,109 @@ +# ========================================================================== +# 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. +# +# ========================================================================== +# +from __future__ import absolute_import, unicode_literals +import logging +# +logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) +logger = logging.getLogger(__name__) +# +# +""" + + dd4hep simulation example setup using the python configuration + + @author M.Frank + @version 1.0 + +""" + + +def run(): + import os + import DDG4 + from DDG4 import OutputLevel as Output + from g4units import keV + + args = DDG4.CommandLine() + install_dir = os.environ['DD4hepExamplesINSTALL'] + if args.help: + import sys + logger.info(""" + python <dir>/Channeling.py -option [-option] + -geometry <geometry file name> File is expected in the examples + install area: + """ + install_dir + """ + -vis Enable visualization + -macro Pass G4 macro file to UI executive + -batch Run in batch mode for unit testing + -events <number> Run geant4 for specified number of events + (batch mode only) + """) + sys.exit(0) + + kernel = DDG4.Kernel() + kernel.loadGeometry(str("file:" + install_dir + "/examples/DDG4/compact/Channeling.xml")) + + DDG4.importConstants(kernel.detectorDescription(), debug=False) + geant4 = DDG4.Geant4(kernel, tracker='Geant4TrackerCombineAction') + geant4.printDetectors() + # Configure UI + if args.macro: + ui = geant4.setupCshUI(macro=args.macro, vis=args.vis) + else: + ui = geant4.setupCshUI(vis=args.vis) + + if args.batch: + ui.Commands = ['/run/beamOn ' + str(args.events), '/ddg4/UI/terminate'] + + # Configure field + geant4.setupTrackingField(prt=True) + # Configure Event actions + prt = DDG4.EventAction(kernel, 'Geant4ParticlePrint/ParticlePrint') + prt.OutputLevel = Output.DEBUG + prt.OutputType = 3 # Print both: table and tree + kernel.eventAction().adopt(prt) + + generator_output_level = Output.INFO + + # Configure G4 geometry setup + seq, act = geant4.addDetectorConstruction("Geant4DetectorGeometryConstruction/ConstructGeo") + act.DebugMaterials = True + act.DebugElements = False + act.DebugVolumes = True + act.DebugShapes = True + act.DebugSurfaces = True + + # Setup particle gun + gun = geant4.setupGun("Gun", particle='gamma', energy=5 * keV, multiplicity=1) + gun.OutputLevel = generator_output_level + + geant4.setupTracker('ChannelingDevice') + + # Instantiate the stacking action + stacking = DDG4.StackingAction(kernel, 'TestStackingAction/MyStacker') + kernel.stackingAction().add(stacking) + + # Now build the physics list: + phys = geant4.setupPhysics('QGSP_BERT') + ph = DDG4.PhysicsList(kernel, 'Channeling') + ph.addPhysicsConstructor(str('Geant4ChannelingPhysics')) + ph.enableUI() + phys.adopt(ph) + phys.dump() + + phys.dump() + + geant4.execute() + + +if __name__ == "__main__": + run() diff --git a/examples/DDG4/src/TestStackingAction.cpp b/examples/DDG4/src/TestStackingAction.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d819ae52e6c547c80c303eac6a666787efab85c6 --- /dev/null +++ b/examples/DDG4/src/TestStackingAction.cpp @@ -0,0 +1,70 @@ +//========================================================================== +// 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 +// +//========================================================================== + +// Framework include files +#include "DDG4/Geant4StackingAction.h" + +/// 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 to measure the energy of escaping tracks + /** Class to measure the energy of escaping tracks of a detector using Geant 4 + * Measure escaping energy.... + * + * \author M.Frank + * \version 1.0 + * \ingroup DD4HEP_SIMULATION + */ + class TestStackingAction : public Geant4StackingAction { + std::size_t m_calls_newStage { 0UL }; + std::size_t m_calls_prepare { 0UL }; + std::size_t m_calls_classify { 0UL }; + + public: + /// Standard constructor + TestStackingAction(Geant4Context* context, const std::string& nam) + : Geant4StackingAction(context, nam) + { + } + /// Default destructor + virtual ~TestStackingAction() { + info("+++ Calls newStage: %ld prepare: %ld classifyNewTrack: %ld", + m_calls_newStage, m_calls_prepare, m_calls_classify); + } + /// New-stage callback + virtual void newStage(G4StackManager* stackManager) override final { + info("+++ [%ld] Calling newStage. StackManager: %p", m_calls_newStage, (void*)stackManager); + ++m_calls_newStage; + } + /// Preparation callback + virtual void prepare(G4StackManager* stackManager) override final { + info("+++ [%ld] Calling prepare. StackManager: %p", m_calls_prepare, (void*)stackManager); + ++m_calls_prepare; + } + /// Return TrackClassification with enum G4ClassificationOfNewTrack or NoTrackClassification + virtual TrackClassification + classifyNewTrack(G4StackManager* stackManager, const G4Track* track) override final { + info("+++ [%ld] Calling classifyNewTrack. StackManager: %p Track: %p", + m_calls_classify, (void*)stackManager, (void*)track); + ++m_calls_classify; + return { fKill }; + } + }; + } // End namespace sim +} // End namespace dd4hep + +#include "DDG4/Factories.h" +DECLARE_GEANT4ACTION_NS(dd4hep::sim,TestStackingAction)