diff --git a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx index e6d3326e85f99602098527c13550e626c368d7b1..648b819cc25f43378135568ea81dd082bf41fd3c 100644 --- a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx +++ b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.cxx @@ -5,11 +5,6 @@ #include "AthenaKernel/errorcheck.h" #include "AthLinks/ElementLink.h" -#define private public -# include "GeneratorObjects/McEventCollection.h" -#undef private -#include "GeneratorObjects/xAODTruthParticleLink.h" - #include "GaudiKernel/MsgStream.h" #include "GaudiKernel/DataSvc.h" #include "GaudiKernel/PhysicalConstants.h" @@ -46,30 +41,22 @@ namespace xAODMaker { xAODTruthCnvAlg::xAODTruthCnvAlg( const string& name, ISvcLocator* svcLoc ) : AthAlgorithm( name, svcLoc ), m_metaStore( "MetaDataStore", name ), m_inputMetaStore( "StoreGateSvc/InputMetaDataStore",name) { - declareProperty("AODContainerName", m_aodContainerName="GEN_AOD" ); - declareProperty("xAODTruthEventContainerName", m_xaodTruthEventContainerName="TruthEvents" ); - declareProperty("xAODTruthPileupEventContainerName", m_xaodTruthPUEventContainerName="TruthPileupEvents" ); - /// @todo TruthParticle -> TruthParticles - declareProperty("xAODTruthParticleContainerName", m_xaodTruthParticleContainerName="TruthParticles" ); - /// @todo TruthVertex -> TruthVertices - declareProperty("xAODTruthVertexContainerName", m_xaodTruthVertexContainerName="TruthVertices" ); - declareProperty("TruthLinks", m_truthLinkContainerName="xAODTruthLinks" ); declareProperty( "WriteAllPileUpTruth", m_doAllPileUp = false); declareProperty( "WriteInTimePileUpTruth", m_doInTimePileUp = false); declareProperty( "MetaObjectName", m_metaName = "TruthMetaData" ); declareProperty( "MetaDataStore", m_metaStore ); - declareProperty( "ForceRerun", m_forceRerun = false); + declareProperty( "OnlyRedoLinks", m_onlyRedoLinks = false); declareProperty( "WriteTruthMetaData", m_writeMetaData = true); } StatusCode xAODTruthCnvAlg::initialize() { ATH_MSG_DEBUG("Initializing; package version: " << PACKAGE_VERSION ); - ATH_MSG_DEBUG("AODContainerName = " << m_aodContainerName ); - ATH_MSG_DEBUG("xAOD TruthEventContainer name = " << m_xaodTruthEventContainerName ); - ATH_MSG_DEBUG("xAOD TruthPileupEventContainer name = " << m_xaodTruthPUEventContainerName ); - ATH_MSG_DEBUG("xAOD TruthParticleContainer name = " << m_xaodTruthParticleContainerName ); - ATH_MSG_DEBUG("xAOD TruthVertexContainer name = " << m_xaodTruthVertexContainerName ); + ATH_MSG_DEBUG("AODContainerName = " << m_aodContainerKey.key() ); + ATH_MSG_DEBUG("xAOD TruthEventContainer name = " << m_xaodTruthEventContainerKey.key() ); + ATH_MSG_DEBUG("xAOD TruthPileupEventContainer name = " << m_xaodTruthPUEventContainerKey.key()); + ATH_MSG_DEBUG("xAOD TruthParticleContainer name = " << m_xaodTruthParticleContainerKey.key() ); + ATH_MSG_DEBUG("xAOD TruthVertexContainer name = " << m_xaodTruthVertexContainerKey.key() ); if (m_doAllPileUp && m_doInTimePileUp) { ATH_MSG_FATAL( "Contradictory xAOD truth pile-up setting: all pile-up AND in-time alone requested simultaneously. Check settings." ); return StatusCode::FAILURE; @@ -77,6 +64,8 @@ namespace xAODMaker { if (m_doAllPileUp) ATH_MSG_INFO( "All pile-up truth (including out-of-time) will be written" ); if (m_doInTimePileUp) ATH_MSG_INFO( "In-time pile-up truth (but not out-of-time) will be written" ); if (!m_doAllPileUp && !m_doInTimePileUp) ATH_MSG_INFO( "No pile-up truth will be written" ); + + if (m_onlyRedoLinks) ATH_MSG_INFO( "Will only redo links, not full xAOD Truth." ); if (m_writeMetaData) { CHECK( m_metaStore.retrieve() ); @@ -90,70 +79,70 @@ namespace xAODMaker { CHECK( m_metaStore->record( m_tmd, m_metaName ) ); } + // initialize handles + ATH_CHECK(m_truthLinkContainerKey.initialize()); + + // if only redoing links + ATH_CHECK(m_linksOnlyTruthEventContainerKey.initialize(m_onlyRedoLinks)); + + // only if doing full truth + ATH_CHECK(m_aodContainerKey.initialize(!m_onlyRedoLinks)); + ATH_CHECK(m_xaodTruthEventContainerKey.initialize(!m_onlyRedoLinks)); + ATH_CHECK(m_xaodTruthPUEventContainerKey.initialize(!m_onlyRedoLinks && + (m_doAllPileUp || m_doInTimePileUp))); + ATH_CHECK(m_xaodTruthParticleContainerKey.initialize(!m_onlyRedoLinks)); + ATH_CHECK(m_xaodTruthVertexContainerKey.initialize(!m_onlyRedoLinks)); + return StatusCode::SUCCESS; } StatusCode xAODTruthCnvAlg::execute() { + SG::WriteHandle<xAODTruthParticleLinkVector> truthLinkVec(m_truthLinkContainerKey); + ATH_CHECK(truthLinkVec.record(std::make_unique<xAODTruthParticleLinkVector>())); - // If the containers already exist then assume that nothing needs to be done - /// @todo Should this check be AND rather than OR? But pileup might be missing. - if ((evtStore()->contains< xAOD::TruthEventContainer >(m_xaodTruthEventContainerName) || - evtStore()->contains< xAOD::TruthPileupEventContainer >(m_xaodTruthPUEventContainerName) || - evtStore()->contains< xAOD::TruthParticleContainer >(m_xaodTruthParticleContainerName) || - evtStore()->contains< xAOD::TruthVertexContainer >(m_xaodTruthVertexContainerName)) && - !m_forceRerun) { - ATH_MSG_WARNING("xAOD Truth seems to be already available in the event"); - return StatusCode::SUCCESS; - } - - xAODTruthParticleLinkVector* truthLinkVec = new xAODTruthParticleLinkVector(); - CHECK( evtStore()->record( truthLinkVec, m_truthLinkContainerName ) ); - - if (evtStore()->contains<McEventCollection>(m_aodContainerName)) { - - // Retrieve the HepMC truth: - const McEventCollection* mcColl = 0; - CHECK( evtStore()->retrieve( mcColl, m_aodContainerName ) ); - ATH_MSG_DEBUG( "Retrieved HepMC with key: " << m_aodContainerName ); + if (!m_onlyRedoLinks) { + // Retrieve the HepMC truth: + SG::ReadHandle<McEventCollection> mcColl(m_aodContainerKey); + // validity check is only really needed for serial running. Remove when MT is only way. + if (!mcColl.isValid()) { + ATH_MSG_ERROR("Could not retrieve HepMC with key:" << m_aodContainerKey.key()); + return StatusCode::FAILURE; + } else { + ATH_MSG_DEBUG( "Retrieved HepMC with key: " << m_aodContainerKey.key() ); + } + // ************************************************************** // Create the xAOD containers and their auxiliary stores: // ************************************************************** // Signal event - xAOD::TruthEventContainer* xTruthEventContainer = new xAOD::TruthEventContainer(); - CHECK( evtStore()->record( xTruthEventContainer, m_xaodTruthEventContainerName ) ); - xAOD::TruthEventAuxContainer* xTruthEventAuxContainer = new xAOD::TruthEventAuxContainer(); - CHECK( evtStore()->record( xTruthEventAuxContainer, m_xaodTruthEventContainerName + "Aux." ) ); - xTruthEventContainer->setStore( xTruthEventAuxContainer ); - ATH_MSG_DEBUG( "Recorded TruthEventContainer with key: " << m_xaodTruthEventContainerName ); + SG::WriteHandle<xAOD::TruthEventContainer> xTruthEventContainer(m_xaodTruthEventContainerKey); + ATH_CHECK(xTruthEventContainer.record(std::make_unique<xAOD::TruthEventContainer>(), + std::make_unique<xAOD::TruthEventAuxContainer>())); + ATH_MSG_DEBUG( "Recorded TruthEventContainer with key: " << m_xaodTruthEventContainerKey.key() ); + // Pile-up events - xAOD::TruthPileupEventContainer* xTruthPileupEventContainer = 0; - xAOD::TruthPileupEventAuxContainer* xTruthPileupEventAuxContainer = 0; + SG::WriteHandle<xAOD::TruthPileupEventContainer> xTruthPileupEventContainer; if (m_doAllPileUp || m_doInTimePileUp) { - xTruthPileupEventContainer = new xAOD::TruthPileupEventContainer(); - CHECK( evtStore()->record( xTruthPileupEventContainer, m_xaodTruthPUEventContainerName ) ); - xTruthPileupEventAuxContainer = new xAOD::TruthPileupEventAuxContainer(); - CHECK( evtStore()->record( xTruthPileupEventAuxContainer, m_xaodTruthPUEventContainerName + "Aux." ) ); - xTruthPileupEventContainer->setStore( xTruthPileupEventAuxContainer ); - ATH_MSG_DEBUG( "Recorded TruthPileupEventContainer with key: " << m_xaodTruthPUEventContainerName ); + xTruthPileupEventContainer = SG::WriteHandle<xAOD::TruthPileupEventContainer>(m_xaodTruthPUEventContainerKey); + ATH_CHECK(xTruthPileupEventContainer.record(std::make_unique<xAOD::TruthPileupEventContainer>(), + std::make_unique<xAOD::TruthPileupEventAuxContainer>())); + ATH_MSG_DEBUG( "Recorded TruthPileupEventContainer with key: " << m_xaodTruthPUEventContainerKey.key() ); } + // Particles - xAOD::TruthParticleContainer* xTruthParticleContainer = new xAOD::TruthParticleContainer(); - CHECK( evtStore()->record( xTruthParticleContainer, m_xaodTruthParticleContainerName ) ); - xAOD::TruthParticleAuxContainer* xTruthParticleAuxContainer = new xAOD::TruthParticleAuxContainer(); - CHECK( evtStore()->record( xTruthParticleAuxContainer, m_xaodTruthParticleContainerName + "Aux." ) ); - xTruthParticleContainer->setStore( xTruthParticleAuxContainer ); - ATH_MSG_DEBUG( "Recorded TruthParticleContainer with key: " << m_xaodTruthParticleContainerName ); + SG::WriteHandle<xAOD::TruthParticleContainer> xTruthParticleContainer(m_xaodTruthParticleContainerKey); + ATH_CHECK(xTruthParticleContainer.record(std::make_unique<xAOD::TruthParticleContainer>(), + std::make_unique<xAOD::TruthParticleAuxContainer>())); + ATH_MSG_DEBUG( "Recorded TruthParticleContainer with key: " << m_xaodTruthParticleContainerKey.key() ); // Vertices - xAOD::TruthVertexContainer* xTruthVertexContainer = new xAOD::TruthVertexContainer(); - CHECK( evtStore()->record( xTruthVertexContainer, m_xaodTruthVertexContainerName ) ); - xAOD::TruthVertexAuxContainer* xTruthVertexAuxContainer = new xAOD::TruthVertexAuxContainer(); - CHECK( evtStore()->record( xTruthVertexAuxContainer, m_xaodTruthVertexContainerName + "Aux." ) ); - xTruthVertexContainer->setStore( xTruthVertexAuxContainer ); - ATH_MSG_DEBUG( "Recorded TruthVertexContainer with key: " << m_xaodTruthVertexContainerName ); - + SG::WriteHandle<xAOD::TruthVertexContainer> xTruthVertexContainer(m_xaodTruthVertexContainerKey); + ATH_CHECK(xTruthVertexContainer.record(std::make_unique<xAOD::TruthVertexContainer>(), + std::make_unique<xAOD::TruthVertexAuxContainer>())); + ATH_MSG_DEBUG( "Recorded TruthVertexContainer with key: " << m_xaodTruthVertexContainerKey.key() ); + // *********************************************************************************** // Create the xAOD objects // This consists of three parts: @@ -387,33 +376,33 @@ namespace xAODMaker { } // end of loop over McEventCollection - } else { - - ATH_MSG_INFO("McEventCollection with name " << m_aodContainerName << " not found"); - - // Retrieve the xAOD Truth and recreate the TruthLinks - if ( !evtStore()->contains<xAOD::TruthEventContainer>(m_xaodTruthEventContainerName) ) { - ATH_MSG_WARNING("TruthEventContainer " << m_xaodTruthEventContainerName << " not found"); - return StatusCode::SUCCESS; - } - const xAOD::TruthEventContainer* xTruthEventContainer = 0; - CHECK( evtStore()->retrieve( xTruthEventContainer, m_xaodTruthEventContainerName ) ); - - // Loop over events and particles - for (const xAOD::TruthEvent* evt : *xTruthEventContainer) { - for (const auto& par : evt->truthParticleLinks()) { - if ( !par.isValid() ) { - // This can happen if particles have been thinned. - ATH_MSG_VERBOSE("Found invalid particle element link in TruthEvent"); //< @todo Use HepMC evt number? - continue; - } - // Create link between HepMC and xAOD truth - //truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*par)->barcode(), evt->eventNumber()), par)); - /// @todo AB: Truth particle links should only be made to the signal event... hence the 0. Right? - truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*par)->barcode(), 0), par)); - } - } + } else { // m_onlyRedoLinks + SG::ReadHandle<xAOD::TruthEventContainer> xTruthEventContainer(m_linksOnlyTruthEventContainerKey); + // validity check is only really needed for serial running. Remove when MT is only way. + if (!xTruthEventContainer.isValid()) { + ATH_MSG_ERROR("Could not retrieve xAOD::TruthEventContainer with key:" << + m_linksOnlyTruthEventContainerKey.key()); + return StatusCode::FAILURE; + } else { + ATH_MSG_DEBUG( "Retrieved for reading xAOD::TruthEventContainer key: " << + m_linksOnlyTruthEventContainerKey.key()); + } + // Loop over events and particles + for (const xAOD::TruthEvent* evt : *xTruthEventContainer) { + for (const auto& par : evt->truthParticleLinks()) { + if ( !par.isValid() ) { + // This can happen if particles have been thinned. + ATH_MSG_VERBOSE("Found invalid particle element link in TruthEvent"); //< @todo Use HepMC evt number? + continue; + } + // Create link between HepMC and xAOD truth + //truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*par)->barcode(), evt->eventNumber()), par)); + /// @todo AB: Truth particle links should only be made to the signal event... hence the 0. Right? + truthLinkVec->push_back(new xAODTruthParticleLink(HepMcParticleLink((*par)->barcode(), 0), par)); + } + } + } std::stable_sort(truthLinkVec->begin(), truthLinkVec->end(), SortTruthParticleLink()); diff --git a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h index 14448f519becf5cbd737704febdac8b31b1eb8f1..9c5a1d1ef830e8ea8f87660e39821d98c644ae9a 100644 --- a/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h +++ b/Event/xAOD/xAODTruthCnv/src/xAODTruthCnvAlg.h @@ -7,10 +7,24 @@ #include "AthenaBaseComps/AthAlgorithm.h" +// The lines below I don't like. We should fix them when we update the +// the metadata to handles (ATLASRECTS-4162). +#define private public +# include "GeneratorObjects/McEventCollection.h" +#undef private + +#include "GeneratorObjects/xAODTruthParticleLink.h" + #include "xAODTruth/TruthEvent.h" #include "xAODTruth/TruthPileupEvent.h" #include "xAODTruth/TruthMetaDataContainer.h" +#include "xAODTruth/TruthEventContainer.h" +#include "xAODTruth/TruthPileupEventContainer.h" +#include "xAODTruth/TruthParticleContainerFwd.h" +#include "xAODTruth/TruthVertexContainerFwd.h" #include "StoreGate/StoreGateSvc.h" +#include "StoreGate/ReadHandleKey.h" +#include "StoreGate/WriteHandleKey.h" #include <unordered_set> @@ -58,14 +72,25 @@ namespace xAODMaker { static void fillParticle(xAOD::TruthParticle *tp, const HepMC::GenParticle *gp); /// The key of the input AOD truth container - std::string m_aodContainerName; - + SG::ReadHandleKey<McEventCollection> m_aodContainerKey{ + this, "AODContainerName", "GEN_AOD", "The input McEvenCollection"}; + /// The key for the output xAOD truth containers - std::string m_xaodTruthEventContainerName; - std::string m_xaodTruthPUEventContainerName; - std::string m_xaodTruthParticleContainerName; - std::string m_xaodTruthVertexContainerName; - std::string m_truthLinkContainerName; + SG::WriteHandleKey<xAOD::TruthEventContainer> m_xaodTruthEventContainerKey{ + this, "xAODTruthEventContainerName", "TruthEvents", "Output TruthEvents container"}; + SG::WriteHandleKey<xAOD::TruthPileupEventContainer> m_xaodTruthPUEventContainerKey{ + this, "xAODTruthPileupEventContainerName", "TruthPileupEvents", "Output TruthPileupEvents container"}; + SG::WriteHandleKey<xAOD::TruthParticleContainer> m_xaodTruthParticleContainerKey{ + this, "xAODTruthParticleContainerName", "TruthParticles", "Output TruthParticles container"}; + SG::WriteHandleKey<xAOD::TruthVertexContainer> m_xaodTruthVertexContainerKey{ + this, "xAODTruthVertexContainerName", "TruthVertices", "Output TruthVertices container"}; + SG::WriteHandleKey<xAODTruthParticleLinkVector> m_truthLinkContainerKey{ + this, "TruthLinks", "xAODTruthLinks", "Output xAODTruthLinks container"}; + + // if only redoing links + SG::ReadHandleKey<xAOD::TruthEventContainer> m_linksOnlyTruthEventContainerKey{ + this, "linksOnlyTruthEventContainerName", "TruthEvents", "Input TruthEvents container"}; + /// Pile-up options bool m_doAllPileUp; bool m_doInTimePileUp; @@ -80,8 +105,8 @@ namespace xAODMaker { /// Set for tracking the mc channels for which we already added meta data std::unordered_set<uint32_t> m_existingMetaDataChan; - /// a flag to force rerunning (useful for rerunning on ESDs) - bool m_forceRerun; + // to only redo links + bool m_onlyRedoLinks; /// option to disable writing of metadata (e.g. if running a filter on xAOD in generators) bool m_writeMetaData; diff --git a/PhysicsAnalysis/TruthParticleID/McParticleAlgs/share/TruthParticleBuilder_jobOptions.py b/PhysicsAnalysis/TruthParticleID/McParticleAlgs/share/TruthParticleBuilder_jobOptions.py index bb189f7129546eb72f8083ae8665151770222040..144c1b8de663cea957d94b5596b7d6b5cbc32db6 100755 --- a/PhysicsAnalysis/TruthParticleID/McParticleAlgs/share/TruthParticleBuilder_jobOptions.py +++ b/PhysicsAnalysis/TruthParticleID/McParticleAlgs/share/TruthParticleBuilder_jobOptions.py @@ -26,13 +26,14 @@ from McParticleAlgs.JobOptCfg import McAodBuilder,createMcAodBuilder,PileUpClass # If we're reprocessing, we may have TruthEvents but not xAODTruthLinks. # Remake the links here if needed. +# JM: In the future, this would not work. If TrutheEvents exists, it should +# be renamed out of the way. Force rerun is effectivly always true. # This needs to come before the McAodBuilder below; otherwise, # xAODTruthCnvAlg will also try to rebuild TruthEvents. if (objKeyStore.isInInput( "xAOD::TruthEventContainer", "TruthEvents" ) and - not objKeyStore.isInInput( "xAODTrigParticleLinkVector", "xAODTruthLinks" ) ): + not objKeyStore.isInInput( "xAODTruthParticleLinkVector", "xAODTruthLinks" ) ): from xAODTruthCnv.xAODTruthCnvConf import xAODMaker__xAODTruthCnvAlg - job += xAODMaker__xAODTruthCnvAlg("GEN_AOD2xAOD", - ForceRerun = True) + job += xAODMaker__xAODTruthCnvAlg("GEN_AOD2xAOD_links", OnlyRedoLinks = True) if (objKeyStore.isInInput( "McEventCollection", "TruthEvent" ) and not objKeyStore.isInInput( "McEventCollection", "GEN_AOD" )): diff --git a/Reconstruction/VKalVrt/VrtSecInclusive/share/VrtSecInclusive_DV_ESD_postInclude.py b/Reconstruction/VKalVrt/VrtSecInclusive/share/VrtSecInclusive_DV_ESD_postInclude.py index 746f1e4201c6e632e6a3e4b10f1a4a539900e809..8dae9d81436b59b2c1baa1e48052844ee1486a08 100644 --- a/Reconstruction/VKalVrt/VrtSecInclusive/share/VrtSecInclusive_DV_ESD_postInclude.py +++ b/Reconstruction/VKalVrt/VrtSecInclusive/share/VrtSecInclusive_DV_ESD_postInclude.py @@ -10,9 +10,11 @@ from AthenaCommon.AppMgr import ServiceMgr as svcMgr StoreGateSvc=svcMgr.StoreGateSvc StoreGateSvc.AllowOverwrite=True -# force the truth conversion to rerun, discussed in https://its.cern.ch/jira/browse/ATLASRECTS-2062 -if not globalflags.DataSource() == 'data': - topSequence.GEN_AOD2xAOD.ForceRerun=True +# (JM) In release 22 ForceRerun is effectively always true. The configuration +# should add the alg if it needs to run, not if it doesn't +# # force the truth conversion to rerun, discussed in https://its.cern.ch/jira/browse/ATLASRECTS-2062 +# if not globalflags.DataSource() == 'data': +# topSequence.GEN_AOD2xAOD.ForceRerun=True # include options include("VrtSecInclusive/VrtSecInclusive_DV_postInclude.py")