diff --git a/Simulation/BeamEffects/python/BeamEffectsConfig.py b/Simulation/BeamEffects/python/BeamEffectsConfig.py index 4a3fe434693076137e10a142346704c538940d5c..237f1a6750a667fe8431f0d4ab48b7a943e45a2a 100644 --- a/Simulation/BeamEffects/python/BeamEffectsConfig.py +++ b/Simulation/BeamEffects/python/BeamEffectsConfig.py @@ -79,6 +79,11 @@ def getCrabKissingVertexPositioner(name="CrabKissingVertexPositioner", **kwargs) def getGenEventValidityChecker(name="GenEventValidityChecker", **kwargs): return CfgMgr.Simulation__GenEventValidityChecker(name, **kwargs) +def getZeroLifetimePositioner(name="ZeroLifetimePositioner", **kwargs): + kwargs.setdefault('ApplyPatch', True) + kwargs.setdefault('RemovePatch', True) + return CfgMgr.Simulation__ZeroLifetimePositioner(name, **kwargs) + def getGenEventVertexPositioner(name="GenEventVertexPositioner", **kwargs): from G4AtlasApps.SimFlags import simFlags readVtxPosFromFile = simFlags.VertexOverrideFile.statusOn or simFlags.VertexOverrideEventFile.statusOn diff --git a/Simulation/BeamEffects/python/BeamEffectsConfigDb.py b/Simulation/BeamEffects/python/BeamEffectsConfigDb.py index 303491bc82692e7260bb698e421ae0b265531f9d..5ccdb068257976b2baf338fe4cdf465c02cd7096 100644 --- a/Simulation/BeamEffects/python/BeamEffectsConfigDb.py +++ b/Simulation/BeamEffects/python/BeamEffectsConfigDb.py @@ -8,6 +8,7 @@ addTool("BeamEffects.BeamEffectsConfig.getLongBeamspotVertexPositioner", "L addTool("BeamEffects.BeamEffectsConfig.getCrabKissingVertexPositioner", "CrabKissingVertexPositioner") ## GenEvent Manipulators addTool("BeamEffects.BeamEffectsConfig.getGenEventValidityChecker", "GenEventValidityChecker") +addTool("BeamEffects.BeamEffectsConfig.getZeroLifetimePositioner", "ZeroLifetimePositioner") addTool("BeamEffects.BeamEffectsConfig.getGenEventVertexPositioner", "GenEventVertexPositioner") addTool("BeamEffects.BeamEffectsConfig.getGenEventBeamEffectBooster", "GenEventBeamEffectBooster") addTool("BeamEffects.BeamEffectsConfig.getGenEventRotator", "GenEventRotator") diff --git a/Simulation/BeamEffects/src/ZeroLifetimePositioner.cxx b/Simulation/BeamEffects/src/ZeroLifetimePositioner.cxx new file mode 100644 index 0000000000000000000000000000000000000000..7833a05bfffc3d95a2ac74202381100525c1c953 --- /dev/null +++ b/Simulation/BeamEffects/src/ZeroLifetimePositioner.cxx @@ -0,0 +1,120 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +// class header include +#include "ZeroLifetimePositioner.h" + +// HepMC includes +#include "HepMC/GenEvent.h" + +// CLHEP includes +#include "CLHEP/Vector/LorentzVector.h" + +#include <limits> +#include <algorithm> + +/** Constructor **/ +Simulation::ZeroLifetimePositioner::ZeroLifetimePositioner( const std::string& name, + ISvcLocator* pSvcLocator ) + : base_class(name, pSvcLocator) +{ + declareProperty("ApplyPatch", m_applyPatch, ""); + declareProperty("RemovePatch", m_removePatch, ""); + declareProperty("PDGCodesToCheck", m_pdgCodesToCheck, ""); +} + + +/** Athena algtool's Hooks */ +StatusCode Simulation::ZeroLifetimePositioner::initialize() +{ + ATH_MSG_VERBOSE("Initializing ..."); + for(auto& pdgcode : m_pdgCodesToCheck) { + pdgcode = std::abs(pdgcode); + ATH_MSG_DEBUG("Will look for verices where " << pdgcode << + " oscillates into -" << pdgcode << " (and vice versa)."); + } + return StatusCode::SUCCESS; +} + + +/** Athena algtool's Hooks */ +StatusCode Simulation::ZeroLifetimePositioner::finalize() +{ + ATH_MSG_VERBOSE("Finalizing ..."); + return StatusCode::SUCCESS; +} + + +StatusCode Simulation::ZeroLifetimePositioner::applyWorkaround(HepMC::GenEvent& ge) const +{ + ATH_MSG_DEBUG("applyWorkaround"); + return this->manipulate(ge, m_applyPatch, false); +} + + +StatusCode Simulation::ZeroLifetimePositioner::removeWorkaround(HepMC::GenEvent& ge) const +{ + ATH_MSG_DEBUG("removeWorkaround"); + return this->manipulate(ge, false, m_removePatch); +} + + +/** modifies (displaces) the given GenEvent */ +StatusCode Simulation::ZeroLifetimePositioner::manipulate(HepMC::GenEvent& ge, bool applyPatch, bool removePatch) const +{ + // loop over the vertices in the event + HepMC::GenEvent::vertex_iterator vtxIt = ge.vertices_begin(); + const HepMC::GenEvent::vertex_iterator vtxItEnd = ge.vertices_end(); + const auto pdgCodesBegin = m_pdgCodesToCheck.begin(); + const auto pdgCodesEnd = m_pdgCodesToCheck.end(); + for (; vtxIt != vtxItEnd; ++vtxIt) { + // quick access: + HepMC::GenVertex *curVtx = (*vtxIt); + if (curVtx->particles_in_size()!=1 || curVtx->particles_out_size()!=1) { continue; } + const int pdgIn=(*(curVtx->particles_in_const_begin()))->pdg_id(); + const int pdgOut=(*(curVtx->particles_out_const_begin()))->pdg_id(); + if (pdgIn!=-pdgOut || + std::find(pdgCodesBegin, pdgCodesEnd, std::abs(pdgIn))== pdgCodesEnd) { + continue; + } + HepMC::GenVertex* nextVtx = (*(curVtx->particles_out_const_begin()))->end_vertex(); + if(!nextVtx) { continue; } + ATH_MSG_DEBUG("Found a vertex to correct with incoming PDG code = " << pdgIn); + ATH_MSG_VERBOSE("Next Vertex:"); + if (ATH_UNLIKELY(this->msgLvl (MSG::VERBOSE))) { + nextVtx->print(); + } + const HepMC::FourVector &nextVec = nextVtx->position(); + const CLHEP::HepLorentzVector nextPos( nextVec.x(), nextVec.y(), nextVec.z(), nextVec.t() ); + ATH_MSG_VERBOSE("Current Vertex:"); + if (ATH_UNLIKELY(this->msgLvl (MSG::VERBOSE))) { + curVtx->print(); + } + if (applyPatch) { + HepMC::GenVertex* prevVtx = (*(curVtx->particles_in_const_begin()))->production_vertex(); + ATH_MSG_VERBOSE("Previous Vertex:"); + if (ATH_UNLIKELY(this->msgLvl (MSG::VERBOSE))) { + prevVtx->print(); + } + const HepMC::FourVector &prevVec = prevVtx->position(); + const CLHEP::HepLorentzVector prevPos( prevVec.x(), prevVec.y(), prevVec.z(), prevVec.t() ); + CLHEP::HepLorentzVector newPos = 0.5*(prevPos+nextPos); + curVtx->set_position(newPos); + ATH_MSG_DEBUG("Revised current Vertex"); + if (ATH_UNLIKELY(this->msgLvl (MSG::VERBOSE))) { + curVtx->print(); + } + } + if (removePatch) { + CLHEP::HepLorentzVector newPos = nextPos; + curVtx->set_position(newPos); + ATH_MSG_DEBUG("Revised current Vertex"); + if (ATH_UNLIKELY(this->msgLvl (MSG::VERBOSE))) { + curVtx->print(); + } + } + } + + return StatusCode::SUCCESS; +} diff --git a/Simulation/BeamEffects/src/ZeroLifetimePositioner.h b/Simulation/BeamEffects/src/ZeroLifetimePositioner.h new file mode 100644 index 0000000000000000000000000000000000000000..cb99d37579e799bb2d45f6bba24b77f2b14e1d37 --- /dev/null +++ b/Simulation/BeamEffects/src/ZeroLifetimePositioner.h @@ -0,0 +1,50 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +/////////////////////////////////////////////////////////////////// +// ZeroLifetimePositioner.h, (c) ATLAS Detector software +/////////////////////////////////////////////////////////////////// + +#ifndef BEAMEFFECTS_ZEROLIFETIMEPOSITIONER_H +#define BEAMEFFECTS_ZEROLIFETIMEPOSITIONER_H 1 + +// FrameWork includes +#include "GaudiKernel/ToolHandle.h" +#include "AthenaBaseComps/AthService.h" +#include "HepMC_Interfaces/IZeroLifetimePatcher.h" +#include <vector> + +namespace Simulation { + + /** @class ZeroLifetimePositioner + + This tool works around the issue of zero-lifetime particles in Geant4. + + */ + class ZeroLifetimePositioner : public extends<AthService, Simulation::IZeroLifetimePatcher> { + + public: + /** Constructor with parameters */ + ZeroLifetimePositioner( const std::string& name, ISvcLocator* pSvcLocator ); + + /** Athena algtool's Hooks */ + StatusCode initialize() override final; + StatusCode finalize() override final; + + /** Applies the workaround for zero-lifetime particles to the GenEvent */ + virtual StatusCode applyWorkaround(HepMC::GenEvent& ge) const override final; + + /** Removes the workaround for zero-lifetime particles from the GenEvent */ + virtual StatusCode removeWorkaround(HepMC::GenEvent& ge) const override final; + + private: + StatusCode manipulate(HepMC::GenEvent& ge, bool applyPatch, bool removePatch) const; + bool m_applyPatch{false}; + bool m_removePatch{false}; + std::vector<int> m_pdgCodesToCheck{511}; + }; + +} + +#endif //> !BEAMEFFECTS_ZEROLIFETIMEPOSITIONER_H diff --git a/Simulation/BeamEffects/src/components/BeamEffects_entries.cxx b/Simulation/BeamEffects/src/components/BeamEffects_entries.cxx index 1b960765bbaa445596280032a31d7c328906b7d7..019e319d30a7fe193567daefc1d21d6b14e951ea 100644 --- a/Simulation/BeamEffects/src/components/BeamEffects_entries.cxx +++ b/Simulation/BeamEffects/src/components/BeamEffects_entries.cxx @@ -1,4 +1,5 @@ #include "../GenEventValidityChecker.h" +#include "../ZeroLifetimePositioner.h" #include "../GenEventVertexPositioner.h" #include "../VertexBeamCondPositioner.h" #include "../LongBeamspotVertexPositioner.h" @@ -7,6 +8,7 @@ #include "../GenEventBeamEffectBooster.h" #include "../GenEventRotator.h" #include "../BeamEffectsAlg.h" +DECLARE_COMPONENT( Simulation::ZeroLifetimePositioner ) DECLARE_COMPONENT( Simulation::GenEventValidityChecker ) DECLARE_COMPONENT( Simulation::GenEventVertexPositioner ) DECLARE_COMPONENT( Simulation::VertexBeamCondPositioner ) diff --git a/Simulation/ISF/ISF_Config/python/ISF_MainConfig.py b/Simulation/ISF/ISF_Config/python/ISF_MainConfig.py index 491be34fbd81ccb6188a0419040da31165fa1724..b54968a2e9375af5700b97e25b836ba7d6410ece 100644 --- a/Simulation/ISF/ISF_Config/python/ISF_MainConfig.py +++ b/Simulation/ISF/ISF_Config/python/ISF_MainConfig.py @@ -282,6 +282,7 @@ def getKernel_FullG4_LongLived(name="ISF_Kernel_FullG4_LongLived", **kwargs): kwargs.setdefault("MSSimulationSelectors" , [ 'ISF_DefaultLongLivedGeant4Selector' ] ) kwargs.setdefault("CavernSimulationSelectors" , [ 'ISF_DefaultParticleKillerSelector' ] ) kwargs.setdefault("InputConverter" , 'ISF_LongLivedInputConverter' ) + kwargs.setdefault("QuasiStablePatcher" , 'ZeroLifetimePositioner') return getKernel_GenericG4Only(name, **kwargs) ############## Simulator: FullG4MT_longLived ############### diff --git a/Simulation/ISF/ISF_Config/test/test_FullG4_Sim_tf_configuration.py b/Simulation/ISF/ISF_Config/test/test_FullG4_Sim_tf_configuration.py index 99b8da866a5fd659c3f8e8c136a146e9f19c2abd..eb67c644ec2b1a13789ac8c02c53b8b8ab03fb09 100755 --- a/Simulation/ISF/ISF_Config/test/test_FullG4_Sim_tf_configuration.py +++ b/Simulation/ISF/ISF_Config/test/test_FullG4_Sim_tf_configuration.py @@ -150,7 +150,7 @@ class TestFullG4(unittest.TestCase): def test___SimKernel_ListOfSetProperties(self): - expected_list = ['BeamPipeSimulationSelectors', 'CaloSimulationSelectors', 'CavernSimulationSelectors', 'DetStore', 'DoCPUMonitoring', 'DoMemoryMonitoring', 'EventFilterTools', 'EvtStore', 'ExtraInputs', 'ExtraOutputs', 'IDSimulationSelectors', 'InputConverter', 'InputHardScatterCollection', 'MSSimulationSelectors', 'MemoryMonitoringTool', 'NeededResources', 'OutputHardScatterTruthCollection', 'ParticleBroker', 'TruthRecordService'] + expected_list = ['BeamPipeSimulationSelectors', 'CaloSimulationSelectors', 'CavernSimulationSelectors', 'DetStore', 'DoCPUMonitoring', 'DoMemoryMonitoring', 'EventFilterTools', 'EvtStore', 'ExtraInputs', 'ExtraOutputs', 'IDSimulationSelectors', 'InputConverter', 'InputHardScatterCollection', 'MSSimulationSelectors', 'MemoryMonitoringTool', 'NeededResources', 'OutputHardScatterTruthCollection', 'ParticleBroker', 'QuasiStablePatcher', 'TruthRecordService'] simkernel = self._job_config_dict['ISF_Kernel_FullG4'] actual_list = simkernel.keys() expected_property_value_sorted = sorted(expected_list) diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/CMakeLists.txt b/Simulation/ISF/ISF_Core/ISF_Algorithms/CMakeLists.txt index 10a753b0132836c519028e886685941108db40d9..ec6902ffea88b0390c37f29e8e09eae1f638376e 100644 --- a/Simulation/ISF/ISF_Core/ISF_Algorithms/CMakeLists.txt +++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/CMakeLists.txt @@ -19,6 +19,7 @@ atlas_depends_on_subdirs( TileCalorimeter/TileSimEvent MuonSpectrometer/MuonSimEvent Generators/GeneratorObjects + Simulation/Interfaces/HepMC_Interfaces Simulation/ISF/ISF_Core/ISF_Event Simulation/ISF/ISF_Core/ISF_Interfaces Tools/PmbCxxUtils diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.cxx b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.cxx index c101a89fb33e6856f1ff21d8381629e1661177f6..fe67e031f7fd199e47b3a0d4bc1def96f78be37a 100644 --- a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.cxx +++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ // ISF_Algs includes @@ -42,6 +42,7 @@ ISF::SimKernel::SimKernel( const std::string& name, ISvcLocator* pSvcLocator ) : m_inputConverter("",name), m_particleBroker("ISF_ParticleBroker", name), m_truthRecordSvc("ISF_TruthRecordSvc", name), + m_qspatcher("", name), m_doMemMon(true), m_memMon("MemMonitoringTool"), m_memUsageEvts(1000), @@ -85,6 +86,8 @@ ISF::SimKernel::SimKernel( const std::string& name, ISvcLocator* pSvcLocator ) : declareProperty("CaloSimulationSelectors" , m_simSelectors[AtlasDetDescr::fAtlasCalo] ); declareProperty("MSSimulationSelectors" , m_simSelectors[AtlasDetDescr::fAtlasMS] ); declareProperty("CavernSimulationSelectors" , m_simSelectors[AtlasDetDescr::fAtlasCavern] ); + // Quasi-stable particle sim + declareProperty("QuasiStablePatcher", m_qspatcher); // event filter declareProperty("EventFilterTools" , m_eventFilters ); // tuning parameters @@ -138,6 +141,10 @@ StatusCode ISF::SimKernel::initialize() ATH_CHECK ( initSimSvcs(m_simSelectors[geoID]) ); } + if(!m_qspatcher.empty()) { + ATH_CHECK(m_qspatcher.retrieve()); + } + // initialize all the EventFilterTools ATH_CHECK ( m_eventFilters.retrieve() ); ATH_MSG_INFO( "The following Event Filters are defined:"); @@ -439,6 +446,13 @@ StatusCode ISF::SimKernel::execute() return StatusCode::FAILURE; } + // Step 4a: Remove QS patch if required + if(!m_qspatcher.empty()) { + for (const auto& currentGenEvent : *m_outputHardScatterTruth ) { + ATH_CHECK(m_qspatcher->removeWorkaround(*currentGenEvent)); + } + } + // Step 5: Check Any Filters ToolHandleArray<IEventFilterTool>::iterator eventFilter(m_eventFilters.begin()); const ToolHandleArray<IEventFilterTool>::iterator endOfEventFilters(m_eventFilters.end()); @@ -489,6 +503,12 @@ StatusCode ISF::SimKernel::prepareInput(SG::ReadHandle<McEventCollection>& input // create copy outputTruth = CxxUtils::make_unique<McEventCollection>(*inputTruth); + // Apply QS patch if required + if(!m_qspatcher.empty()) { + for (const auto& currentGenEvent : *outputTruth ) { + ATH_CHECK(m_qspatcher->applyWorkaround(*currentGenEvent)); + } + } ATH_CHECK( m_inputConverter->convert(*outputTruth, simParticles, HepMcParticleLink::find_enumFromKey(outputTruth.name())) ); return StatusCode::SUCCESS; diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.h b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.h index 3854d8a831eed2b80957c69528d8876dfa7db078..c69bc315dfad026560e493b99dd73592ae9ffbae 100644 --- a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.h +++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernel.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ #ifndef ISF_ALGS_SIMKERNEL_H @@ -25,6 +25,7 @@ // McEventCollection #include "GeneratorObjects/McEventCollection.h" +#include "HepMC_Interfaces/IZeroLifetimePatcher.h" // forward declarations namespace PMonUtils { @@ -103,6 +104,9 @@ namespace ISF { /** The Simulation Selector Chains */ ToolHandleArray<ISimulationSelector> m_simSelectors[AtlasDetDescr::fNumAtlasRegions]; + /** Quasi-Stable Particle Simulation Patcher */ + ServiceHandle<Simulation::IZeroLifetimePatcher> m_qspatcher; + /** The Event Filters */ ToolHandleArray<IEventFilterTool> m_eventFilters; diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx index ff5f2eade0c8c64e03b55e6594f65d6e4f446df4..f260f7507f37508a5b90011a3c0a82ca379b2fc9 100644 --- a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx +++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ /** @@ -25,6 +25,7 @@ ISF::SimKernelMT::SimKernelMT( const std::string& name, ISvcLocator* pSvcLocator m_inputEvgenKey(), m_outputTruthKey(), m_inputConverter("", name), + m_qspatcher("", name), m_simulationTools(), // FIXME make private m_particleKillerTool(""), // FIXME make private m_geoIDSvc("", name), @@ -39,6 +40,8 @@ ISF::SimKernelMT::SimKernelMT( const std::string& name, ISvcLocator* pSvcLocator declareProperty("InputConverter", m_inputConverter, "Input McEventCollection->ISFParticleContainer conversion service."); + // Quasi-stable particle sim + declareProperty("QuasiStablePatcher", m_qspatcher); // routing tools declareProperty("BeamPipeSimulationSelectors", m_simSelectors[AtlasDetDescr::fAtlasForward] ); @@ -123,6 +126,10 @@ StatusCode ISF::SimKernelMT::initialize() { ATH_CHECK( m_inputConverter.retrieve() ); + if(!m_qspatcher.empty()) { + ATH_CHECK(m_qspatcher.retrieve()); + } + ATH_CHECK( m_geoIDSvc.retrieve() ); return StatusCode::SUCCESS; @@ -147,7 +154,14 @@ StatusCode ISF::SimKernelMT::execute() { // copy input Evgen collection to output Truth collection SG::WriteHandle<McEventCollection> outputTruth(m_outputTruthKey); - outputTruth = CxxUtils::make_unique<McEventCollection>(*inputEvgen); + outputTruth = std::make_unique<McEventCollection>(*inputEvgen); + + // Apply QS patch if required + if(!m_qspatcher.empty()) { + for (const auto& currentGenEvent : *outputTruth ) { + ATH_CHECK(m_qspatcher->applyWorkaround(*currentGenEvent)); + } + } // read and convert input ISFParticleContainer simParticles; // particles for ISF simulation @@ -208,6 +222,13 @@ StatusCode ISF::SimKernelMT::execute() { } } + // Remove QS patch if required + if(!m_qspatcher.empty()) { + for (const auto& currentGenEvent : *outputTruth ) { + ATH_CHECK(m_qspatcher->removeWorkaround(*currentGenEvent)); + } + } + return StatusCode::SUCCESS; } diff --git a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h index 371391711844858421b11a614569da6390121d97..5ffabeec76d180d4aefe8b3cb591f595449901e9 100644 --- a/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h +++ b/Simulation/ISF/ISF_Core/ISF_Algorithms/src/SimKernelMT.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ /** @@ -23,6 +23,7 @@ // McEventCollection #include "GeneratorObjects/McEventCollection.h" +#include "HepMC_Interfaces/IZeroLifetimePatcher.h" // Framework includes #include "AthenaBaseComps/AthAlgorithm.h" @@ -86,6 +87,9 @@ private: /// Input converter service (from Generator->ISF particle types) ServiceHandle<IInputConverter> m_inputConverter; + /// Quasi-Stable Particle Simulation Patcher + ServiceHandle<Simulation::IZeroLifetimePatcher> m_qspatcher; + /// Simulation Tools ToolHandleArray<ISimulatorTool> m_simulationTools; diff --git a/Simulation/Interfaces/HepMC_Interfaces/HepMC_Interfaces/IZeroLifetimePatcher.h b/Simulation/Interfaces/HepMC_Interfaces/HepMC_Interfaces/IZeroLifetimePatcher.h new file mode 100644 index 0000000000000000000000000000000000000000..85d8416be6c6f250cf69522eab05cecf80ff8ac8 --- /dev/null +++ b/Simulation/Interfaces/HepMC_Interfaces/HepMC_Interfaces/IZeroLifetimePatcher.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef HEPMC_INTERFACES_IZEROLIFETIMEPATCHER_H +#define HEPMC_INTERFACES_IZEROLIFETIMEPATCHER_H 1 + +// Gaudi +// framework includes +#include "GaudiKernel/IInterface.h" +#include "GaudiKernel/StatusCode.h" + +namespace HepMC { + class GenEvent; +} + +namespace Simulation { + + /** + @class IZeroLifetimePatcher + + Interface for a service which works around the issue of zero-lifetime particles in Geant4. + + */ + + class IZeroLifetimePatcher : virtual public IInterface { + public: + + /** Virtual destructor */ + virtual ~IZeroLifetimePatcher(){} + + /// Creates the InterfaceID and interfaceID() method + DeclareInterfaceID(IZeroLifetimePatcher, 1, 0); + + /** Applies the workaround for zero-lifetime particles to the GenEvent */ + virtual StatusCode applyWorkaround(HepMC::GenEvent& ge) const = 0; + + /** Removes the workaround for zero-lifetime particles from the GenEvent */ + virtual StatusCode removeWorkaround(HepMC::GenEvent& ge) const = 0; + + }; + +} // end of namespace + +#endif // HEPMC_INTERFACES_IZEROLIFETIMEPATCHER_H