diff --git a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/python/ThinGeantTruth.py b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/python/ThinGeantTruth.py index f58f8441155c8cce24b869aa7bfc1e3ced5c6b46..411b5271edeb3d47fde267bbd337da04ba2a75fc 100644 --- a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/python/ThinGeantTruth.py +++ b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/python/ThinGeantTruth.py @@ -14,7 +14,6 @@ class ThinGeantTruth(Configured): from ThinningUtils.ThinningUtilsConf import ThinGeantTruthAlg theGeantTruthThinner = ThinGeantTruthAlg( "ThinGeantTruthAlg", - ThinGeantTruth = True, StreamName = 'StreamAOD' ) print (theGeantTruthThinner) diff --git a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ReducePileUpEventInfoAlg.cxx b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ReducePileUpEventInfoAlg.cxx index f0a93ad31b25644a133be46dc874eaa4bfc070e7..81bfd620dfc3025ac6bf8087a22a198ef696c9da 100644 --- a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ReducePileUpEventInfoAlg.cxx +++ b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ReducePileUpEventInfoAlg.cxx @@ -82,7 +82,7 @@ StatusCode ReducePileUpEventInfoAlg::execute() if ( evtStore()->contains< PileUpEventInfo >( "" ) ) { // Get the EventInfo object - const PileUpEventInfo* oldEventInfo(NULL); + const PileUpEventInfo* oldEventInfo(nullptr); ATH_CHECK( evtStore()->retrieve( oldEventInfo ) ); // Create a new EventInfo object and register it into StoreGate diff --git a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinGeantTruthAlg.cxx b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinGeantTruthAlg.cxx index c893c4860e6368dd93502d91bb55e55226d97c22..af6339e8ee9ee8a41fcace75e6ceed84017fc692 100644 --- a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinGeantTruthAlg.cxx +++ b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinGeantTruthAlg.cxx @@ -11,9 +11,9 @@ // can't be dropped earlier in the simulation chain. // Not intended for use in derivations! // - Keep all truth particles with barcode <200 000 -// - Keep all truth particles associated with reco photons, electrons +// - Keep all truth particles associated with reco photons, electrons // and muons, and their ancestors. -// - Drop any vertices that, after the above thinning, have neither +// - Drop any vertices that, after the above thinning, have neither // incoming nor outgoing particles // Unlike other algs in this package, no tool is used to select the // objects for thinning - everything is done in this one class. @@ -22,166 +22,145 @@ // EventUtils includes #include "ThinGeantTruthAlg.h" -#include "xAODTruth/xAODTruthHelpers.h" #include "MCTruthClassifier/MCTruthClassifierDefs.h" +#include "xAODTruth/xAODTruthHelpers.h" // STL includes -#include <algorithm> +#include <algorithm> // FrameWork includes -#include "StoreGate/ThinningHandle.h" #include "Gaudi/Property.h" +#include "StoreGate/ThinningHandle.h" -//Standard includes +// Standard includes #include <cstdlib> -/////////////////////////////////////////////////////////////////// -// Public methods: -/////////////////////////////////////////////////////////////////// - -// Constructors -//////////////// -ThinGeantTruthAlg::ThinGeantTruthAlg( const std::string& name, - ISvcLocator* pSvcLocator ) : -::AthAlgorithm( name, pSvcLocator ), -m_doThinning(true), -m_geantOffset(200000), -m_longlived{310,3122,3222,3112,3322,3312}, -m_nEventsProcessed{0}, -m_nParticlesProcessed{0}, -m_nVerticesProcessed{0}, -m_nParticlesThinned{0}, -m_nVerticesThinned{0} -{ - - declareProperty("ThinGeantTruth", m_doThinning, - "Should the Geant truth thinning be run?"); - declareProperty("GeantBarcodeOffset", m_geantOffset, - "Barcode offset for Geant particles"); - declareProperty("LongLivedParticleList", m_longlived, - "List of long lifetime particles which are likely to be decayed by Geant but whose children must be kept"); - -} - -// Destructor -/////////////// -ThinGeantTruthAlg::~ThinGeantTruthAlg() -{} - -// Athena Algorithm's Hooks -//////////////////////////// -StatusCode ThinGeantTruthAlg::initialize() +StatusCode +ThinGeantTruthAlg::initialize() { - ATH_MSG_DEBUG ("Initializing " << name() << "..."); - - // Print out the used configuration - ATH_MSG_DEBUG ( " using = " << m_streamName ); - - // Is truth thinning required? - if (!m_doThinning) { - ATH_MSG_INFO("Geant truth thinning not required"); - } else { - ATH_MSG_INFO("Geant truth will be thinned"); - } - - if (m_doThinning && m_streamName.empty()) { - ATH_MSG_ERROR ("StreamName property was not initialized."); - return StatusCode::FAILURE; - } - - ATH_CHECK(m_truthParticlesKey.initialize(m_streamName, m_doThinning)); - ATH_CHECK(m_truthVerticesKey.initialize(m_streamName, m_doThinning)); - ATH_CHECK(m_electronsKey.initialize(m_doThinning)); - ATH_CHECK(m_photonsKey.initialize(m_doThinning)); - ATH_CHECK(m_muonsKey.initialize(m_doThinning)); - ATH_CHECK(m_egammaTruthKey.initialize(m_doThinning)); - - // Initialize the counters to zero - ATH_MSG_DEBUG ( "==> done with initialize " << name() << "..." ); - return StatusCode::SUCCESS; + if (m_streamName.empty()) { + ATH_MSG_ERROR("StreamName property was not initialized."); + return StatusCode::FAILURE; + } + + ATH_CHECK(m_truthParticlesKey.initialize(m_streamName)); + ATH_CHECK(m_truthVerticesKey.initialize(m_streamName)); + ATH_CHECK(m_electronsKey.initialize(m_keepEGamma)); + ATH_CHECK(m_photonsKey.initialize(m_keepEGamma)); + ATH_CHECK(m_muonsKey.initialize(m_keepMuons)); + ATH_CHECK(m_egammaTruthKey.initialize(m_keepEGamma)); + + return StatusCode::SUCCESS; } - -StatusCode ThinGeantTruthAlg::finalize() +StatusCode +ThinGeantTruthAlg::finalize() { - ATH_MSG_DEBUG ("Finalizing " << name() << "..."); - ATH_MSG_INFO("Processed " << m_nEventsProcessed << " events containing " << m_nParticlesProcessed - << " truth particles and " << m_nVerticesProcessed << " truth vertices "); - ATH_MSG_INFO("Removed " << m_nParticlesThinned << " Geant truth particles and " - << m_nVerticesThinned << " corresponding truth vertices "); - return StatusCode::SUCCESS; + ATH_MSG_INFO("Processed " << m_nEventsProcessed << " events containing " + << m_nParticlesProcessed << " truth particles and " + << m_nVerticesProcessed << " truth vertices "); + ATH_MSG_INFO("Removed " << m_nParticlesThinned + << " Geant truth particles and " << m_nVerticesThinned + << " corresponding truth vertices "); + return StatusCode::SUCCESS; } -StatusCode ThinGeantTruthAlg::execute() +StatusCode +ThinGeantTruthAlg::execute(const EventContext& ctx) const { - // Increase the event counter - ++m_nEventsProcessed; - - // Is truth thinning required? - if (!m_doThinning) { - return StatusCode::SUCCESS; - } - - // Retrieve truth and vertex containers - SG::ThinningHandle<xAOD::TruthParticleContainer> truthParticles(m_truthParticlesKey); - SG::ThinningHandle<xAOD::TruthVertexContainer> truthVertices(m_truthVerticesKey); - if(!truthParticles.isValid()){ - ATH_MSG_FATAL("No TruthParticleContainer with key "+m_truthParticlesKey.key()+" found."); - return StatusCode::FAILURE; - } - if(!truthVertices.isValid()){ - ATH_MSG_FATAL("No TruthVertexContainer with key "+m_truthVerticesKey.key()+" found."); - return StatusCode::FAILURE; - } - - SG::ReadHandle<xAOD::MuonContainer> muons(m_muonsKey); + // Increase the event counter + ++m_nEventsProcessed; + + // Retrieve truth and vertex containers + SG::ThinningHandle<xAOD::TruthParticleContainer> truthParticles( + m_truthParticlesKey, ctx); + SG::ThinningHandle<xAOD::TruthVertexContainer> truthVertices( + m_truthVerticesKey, ctx); + if (!truthParticles.isValid()) { + ATH_MSG_FATAL("No TruthParticleContainer with key " + + m_truthParticlesKey.key() + " found."); + return StatusCode::FAILURE; + } + if (!truthVertices.isValid()) { + ATH_MSG_FATAL("No TruthVertexContainer with key " + + m_truthVerticesKey.key() + " found."); + return StatusCode::FAILURE; + } + + // Loop over photons, electrons and muons and get the associated truth + // particles Retain the associated index number + std::vector<int> recoParticleTruthIndices; + std::vector<int> egammaTruthIndices{}; + + // Muons + if (m_keepMuons) { + SG::ReadHandle<xAOD::MuonContainer> muons(m_muonsKey, ctx); // Retrieve muons, electrons and photons - if(!muons.isValid()){ - ATH_MSG_WARNING("No muon container with key "+m_muonsKey.key()+" found."); - } - SG::ReadHandle<xAOD::ElectronContainer> electrons(m_electronsKey); - if(!electrons.isValid()){ - ATH_MSG_WARNING("No electron container with key "+m_electronsKey.key()+" found."); - } - SG::ReadHandle<xAOD::PhotonContainer> photons(m_photonsKey); - if(!photons.isValid()){ - ATH_MSG_WARNING("No photon container with key "+m_photonsKey.key()+" found."); + if (!muons.isValid()) { + ATH_MSG_WARNING("No muon container with key " + m_muonsKey.key() + + " found."); } - - // Loop over photons, electrons and muons and get the associated truth particles - // Retain the associated index number - std::vector<int> recoParticleTruthIndices; for (const xAOD::Muon* muon : *muons) { - const xAOD::TruthParticle* truthMuon = xAOD::TruthHelpers::getTruthParticle(*muon); - if (truthMuon) {recoParticleTruthIndices.push_back(truthMuon->index());} + const xAOD::TruthParticle* truthMuon = + xAOD::TruthHelpers::getTruthParticle(*muon); + if (truthMuon) { + recoParticleTruthIndices.push_back(truthMuon->index()); + } + } + } + + // Electrons and photons + if (m_keepEGamma) { + + // Electrons + SG::ReadHandle<xAOD::ElectronContainer> electrons(m_electronsKey, ctx); + if (!electrons.isValid()) { + ATH_MSG_WARNING("No electron container with key " + m_electronsKey.key() + + " found."); } for (const xAOD::Electron* electron : *electrons) { - const xAOD::TruthParticle* truthElectron = xAOD::TruthHelpers::getTruthParticle(*electron); - if (truthElectron) {recoParticleTruthIndices.push_back(truthElectron->index());} + const xAOD::TruthParticle* truthElectron = + xAOD::TruthHelpers::getTruthParticle(*electron); + if (truthElectron) { + recoParticleTruthIndices.push_back(truthElectron->index()); + } + } + + // Photons + SG::ReadHandle<xAOD::PhotonContainer> photons(m_photonsKey, ctx); + if (!photons.isValid()) { + ATH_MSG_WARNING("No photon container with key " + m_photonsKey.key() + + " found."); } + for (const xAOD::Photon* photon : *photons) { - const xAOD::TruthParticle* truthPhoton = xAOD::TruthHelpers::getTruthParticle(*photon); - if (truthPhoton) {recoParticleTruthIndices.push_back(truthPhoton->index());} - } - - //Set up the indices for the egamma Truth Particles to keep - SG::ReadHandle<xAOD::TruthParticleContainer> egammaTruthParticles(m_egammaTruthKey); - if(!egammaTruthParticles.isValid()){ - ATH_MSG_WARNING("No e-gamma truth container with key "+m_egammaTruthKey.key()+" found."); + const xAOD::TruthParticle* truthPhoton = + xAOD::TruthHelpers::getTruthParticle(*photon); + if (truthPhoton) { + recoParticleTruthIndices.push_back(truthPhoton->index()); + } + } + + // egamma Truth Particles + SG::ReadHandle<xAOD::TruthParticleContainer> egammaTruthParticles( + m_egammaTruthKey, ctx); + if (!egammaTruthParticles.isValid()) { + ATH_MSG_WARNING("No e-gamma truth container with key " + + m_egammaTruthKey.key() + " found."); } - std::vector<int> egammaTruthIndices{}; for (const xAOD::TruthParticle* egTruthParticle : *egammaTruthParticles) { static const SG::AuxElement::ConstAccessor<int> accType("truthType"); - if(!accType.isAvailable(*egTruthParticle) || - accType(*egTruthParticle)!=MCTruthPartClassifier::IsoElectron || - std::abs(egTruthParticle->eta()) > 2.525){ + if (!accType.isAvailable(*egTruthParticle) || + accType(*egTruthParticle) != MCTruthPartClassifier::IsoElectron || + std::abs(egTruthParticle->eta()) > 2.525) { continue; - } - //Only central isolated true electrons - typedef ElementLink<xAOD::TruthParticleContainer> TruthLink_t; - static const SG::AuxElement::ConstAccessor<TruthLink_t> linkToTruth("truthParticleLink"); + } + // Only central isolated true electrons + using TruthLink_t = ElementLink<xAOD::TruthParticleContainer>; + static const SG::AuxElement::ConstAccessor<TruthLink_t> linkToTruth( + "truthParticleLink"); if (!linkToTruth.isAvailable(*egTruthParticle)) { continue; } @@ -189,193 +168,223 @@ StatusCode ThinGeantTruthAlg::execute() const TruthLink_t& truthegamma = linkToTruth(*egTruthParticle); if (!truthegamma.isValid()) { continue; - } - egammaTruthIndices.push_back( (*truthegamma)->index()); + } + egammaTruthIndices.push_back((*truthegamma)->index()); } - // Set up masks - - std::vector<bool> particleMask, vertexMask; - int nTruthParticles = truthParticles->size(); - int nTruthVertices = truthVertices->size(); - m_nParticlesProcessed += nTruthParticles; - m_nVerticesProcessed += nTruthVertices; - particleMask.assign(nTruthParticles,false); - vertexMask.assign(nTruthVertices,false); - - // Vector of pairs keeping track of how many incoming/outgoing particles each vertex has - std::vector<std::pair<int, int> > vertexLinksCounts; - for (auto vertex : *truthVertices) { - std::pair<int , int> tmpPair; - tmpPair.first = vertex->nIncomingParticles(); - tmpPair.second = vertex->nOutgoingParticles(); - vertexLinksCounts.push_back(tmpPair); + } + + // Set up masks + + std::vector<bool> particleMask, vertexMask; + int nTruthParticles = truthParticles->size(); + int nTruthVertices = truthVertices->size(); + m_nParticlesProcessed += nTruthParticles; + m_nVerticesProcessed += nTruthVertices; + particleMask.assign(nTruthParticles, false); + vertexMask.assign(nTruthVertices, false); + + // Vector of pairs keeping track of how many incoming/outgoing particles each + // vertex has + std::vector<std::pair<int, int>> vertexLinksCounts; + for (const auto *vertex : *truthVertices) { + std::pair<int, int> tmpPair; + tmpPair.first = vertex->nIncomingParticles(); + tmpPair.second = vertex->nOutgoingParticles(); + vertexLinksCounts.push_back(tmpPair); + } + + // Loop over truth particles and update mask + std::unordered_set<int> encounteredBarcodes; // for loop protection + for (int i = 0; i < nTruthParticles; ++i) { + encounteredBarcodes.clear(); + const xAOD::TruthParticle* particle = (*truthParticles)[i]; + // Retain status 1 BSM particles and descendants + if (isStatus1BSMParticle(particle)) { + descendants(particle, particleMask, encounteredBarcodes); + encounteredBarcodes.clear(); } - - // Loop over truth particles and update mask - std::unordered_set<int> encounteredBarcodes; // for loop protection - for (int i=0; i<nTruthParticles; ++i) { - encounteredBarcodes.clear(); - const xAOD::TruthParticle* particle = (*truthParticles)[i]; - // Retain status 1 BSM particles and descendants - if (isStatus1BSMParticle(particle)) { - descendants(particle,particleMask,encounteredBarcodes); - encounteredBarcodes.clear(); + // Retain children of longer-lived generator particles + if (particle->status() == 1) { + int pdgId = abs(particle->pdgId()); + if (std::find(m_longlived.begin(), m_longlived.end(), pdgId) != + m_longlived.end()) { + const xAOD::TruthVertex* decayVtx(nullptr); + if (particle->hasDecayVtx()) { + decayVtx = particle->decayVtx(); } - // Retain children of longer-lived generator particles - if (particle->status()==1) { - int pdgId = abs(particle->pdgId()); - if ( std::find(m_longlived.begin(), m_longlived.end(), pdgId) != m_longlived.end() ) { - const xAOD::TruthVertex* decayVtx(0); - if (particle->hasDecayVtx()) {decayVtx = particle->decayVtx();} - int nChildren = 0; - if (decayVtx) nChildren = decayVtx->nOutgoingParticles(); - for (int i=0; i<nChildren; ++i) { - particleMask[decayVtx->outgoingParticle(i)->index()] = true; - } - } - } - - // Retain particles and their descendants/ancestors associated with the reconstructed objects - if ( std::find(recoParticleTruthIndices.begin(), recoParticleTruthIndices.end(), i) != recoParticleTruthIndices.end() ) { - if (abs(particle->barcode()) > m_geantOffset) { // only need to do this for Geant particles since non-Geant are kept anyway - ancestors(particle,particleMask,encounteredBarcodes); - encounteredBarcodes.clear(); - descendants(particle,particleMask,encounteredBarcodes); - encounteredBarcodes.clear(); - } - } - - // Retain particles and their descendants associated with the egamma Truth Particles - if ( std::find(egammaTruthIndices.begin(), egammaTruthIndices.end(), i) != egammaTruthIndices.end() ) { - descendants(particle,particleMask,encounteredBarcodes); - encounteredBarcodes.clear(); + int nChildren = 0; + if (decayVtx) + nChildren = decayVtx->nOutgoingParticles(); + for (int i = 0; i < nChildren; ++i) { + particleMask[decayVtx->outgoingParticle(i)->index()] = true; } + } + } - if (abs(particle->barcode()) < m_geantOffset) { - particleMask[i] = true; - } + // Retain particles and their descendants/ancestors associated with the + // reconstructed objects + if (std::find(recoParticleTruthIndices.begin(), + recoParticleTruthIndices.end(), + i) != recoParticleTruthIndices.end()) { + if (abs(particle->barcode()) > + m_geantOffset) { // only need to do this for Geant particles since + // non-Geant are kept anyway + ancestors(particle, particleMask, encounteredBarcodes); + encounteredBarcodes.clear(); + descendants(particle, particleMask, encounteredBarcodes); + encounteredBarcodes.clear(); + } } - // Loop over the mask and update vertex association counters - for (int i=0; i<nTruthParticles; ++i) { - if (particleMask[i] == false) { - ++m_nParticlesThinned; - const xAOD::TruthParticle* particle = (*truthParticles)[i]; - if (particle->hasProdVtx()) { - auto prodVertex = particle->prodVtx(); - --vertexLinksCounts[prodVertex->index()].second; - } - if (particle->hasDecayVtx()) { - auto decayVertex = particle->decayVtx(); - --vertexLinksCounts[decayVertex->index()].first; - } - } - } - - // Loop over truth vertices and update mask - // Those for which all incoming and outgoing particles are to be thinned, will be thinned as well - for (int i=0; i<nTruthVertices; ++i) { - if (vertexLinksCounts[i].first!=0 || vertexLinksCounts[i].second!=0) { - vertexMask[i] = true; - } else {++m_nVerticesThinned;} + // Retain particles and their descendants associated with the egamma Truth + // Particles + if (std::find(egammaTruthIndices.begin(), egammaTruthIndices.end(), i) != + egammaTruthIndices.end()) { + descendants(particle, particleMask, encounteredBarcodes); + encounteredBarcodes.clear(); } - // Apply masks to thinning - truthParticles.keep (particleMask); - truthVertices.keep (vertexMask); - - return StatusCode::SUCCESS; -} + if (abs(particle->barcode()) < m_geantOffset) { + particleMask[i] = true; + } + } + + // Loop over the mask and update vertex association counters + for (int i = 0; i < nTruthParticles; ++i) { + if (!particleMask[i]) { + ++m_nParticlesThinned; + const xAOD::TruthParticle* particle = (*truthParticles)[i]; + if (particle->hasProdVtx()) { + const auto *prodVertex = particle->prodVtx(); + --vertexLinksCounts[prodVertex->index()].second; + } + if (particle->hasDecayVtx()) { + const auto *decayVertex = particle->decayVtx(); + --vertexLinksCounts[decayVertex->index()].first; + } + } + } + + // Loop over truth vertices and update mask + // Those for which all incoming and outgoing particles are to be thinned, will + // be thinned as well + for (int i = 0; i < nTruthVertices; ++i) { + if (vertexLinksCounts[i].first != 0 || vertexLinksCounts[i].second != 0) { + vertexMask[i] = true; + } else { + ++m_nVerticesThinned; + } + } + // Apply masks to thinning + truthParticles.keep(particleMask); + truthVertices.keep(vertexMask); + return StatusCode::SUCCESS; +} // Inline methods // // ============================== -// ancestors +// ancestors // ============================== // Updates particle mask such that particle and all ancestors are retained -void ThinGeantTruthAlg::ancestors(const xAOD::TruthParticle* pHead, - std::vector<bool> &particleMask, - std::unordered_set<int> &encounteredBarcodes ) { - - // Check that this barcode hasn't been seen before (e.g. we are in a loop) - std::unordered_set<int>::const_iterator found = encounteredBarcodes.find(pHead->barcode()); - if (found!=encounteredBarcodes.end()) return; - encounteredBarcodes.insert(pHead->barcode()); - - // Save particle position in the mask - int headIndex = pHead->index(); - particleMask[headIndex] = true; - - // Get the production vertex - const xAOD::TruthVertex* prodVtx(0); - if (pHead->hasProdVtx()) {prodVtx = pHead->prodVtx();} - else {return;} - - // Get children particles and self-call - int nParents = prodVtx->nIncomingParticles(); - for (int i=0; i<nParents; ++i) ancestors(prodVtx->incomingParticle(i),particleMask,encounteredBarcodes); +void +ThinGeantTruthAlg::ancestors(const xAOD::TruthParticle* pHead, + std::vector<bool>& particleMask, + std::unordered_set<int>& encounteredBarcodes) const +{ + + // Check that this barcode hasn't been seen before (e.g. we are in a loop) + std::unordered_set<int>::const_iterator found = + encounteredBarcodes.find(pHead->barcode()); + if (found != encounteredBarcodes.end()) return; -} + encounteredBarcodes.insert(pHead->barcode()); + // Save particle position in the mask + int headIndex = pHead->index(); + particleMask[headIndex] = true; + + // Get the production vertex + const xAOD::TruthVertex* prodVtx(nullptr); + if (pHead->hasProdVtx()) { + prodVtx = pHead->prodVtx(); + } else { + return; + } + + // Get children particles and self-call + int nParents = prodVtx->nIncomingParticles(); + for (int i = 0; i < nParents; ++i) + ancestors(prodVtx->incomingParticle(i), particleMask, encounteredBarcodes); +} // ============================== -// descendants +// descendants // ============================== // Updates particle mask such that particle and all descendants are retained -void ThinGeantTruthAlg::descendants(const xAOD::TruthParticle* pHead, - std::vector<bool> &particleMask, - std::unordered_set<int> &encounteredBarcodes ) { - // Check that this barcode hasn't been seen before (e.g. we are in a loop) - std::unordered_set<int>::const_iterator found = encounteredBarcodes.find(pHead->barcode()); - if (found!=encounteredBarcodes.end()) return; - encounteredBarcodes.insert(pHead->barcode()); - - // Save the particle position in the mask - int headIndex = pHead->index(); - particleMask[headIndex] = true; - - // Get the decay vertex - const xAOD::TruthVertex* decayVtx(0); - if (pHead->hasDecayVtx()) {decayVtx = pHead->decayVtx();} - else {return;} - - // Get children particles and self-call - int nChildren = decayVtx->nOutgoingParticles(); - for (int i=0; i<nChildren; ++i) { - descendants(decayVtx->outgoingParticle(i),particleMask,encounteredBarcodes); - } - +void +ThinGeantTruthAlg::descendants( + const xAOD::TruthParticle* pHead, + std::vector<bool>& particleMask, + std::unordered_set<int>& encounteredBarcodes) const +{ + // Check that this barcode hasn't been seen before (e.g. we are in a loop) + std::unordered_set<int>::const_iterator found = + encounteredBarcodes.find(pHead->barcode()); + if (found != encounteredBarcodes.end()) return; -} + encounteredBarcodes.insert(pHead->barcode()); + + // Save the particle position in the mask + int headIndex = pHead->index(); + particleMask[headIndex] = true; + + // Get the decay vertex + const xAOD::TruthVertex* decayVtx(nullptr); + if (pHead->hasDecayVtx()) { + decayVtx = pHead->decayVtx(); + } else { + return; + } + + // Get children particles and self-call + int nChildren = decayVtx->nOutgoingParticles(); + for (int i = 0; i < nChildren; ++i) { + descendants( + decayVtx->outgoingParticle(i), particleMask, encounteredBarcodes); + } + + } // ============================== -// isStatus1BSMParticle +// isStatus1BSMParticle // ============================== // Returns true if a particle is BSM and stable +bool +ThinGeantTruthAlg::isStatus1BSMParticle(const xAOD::TruthParticle* part) +{ -bool ThinGeantTruthAlg::isStatus1BSMParticle(const xAOD::TruthParticle* part) const{ - - int pdg = part->pdgId(); - bool status1 = (part->status()==1); - bool isBSM(false); - - if ( (31<abs(pdg) && abs(pdg)<38) || // BSM Higgs / W' / Z' / etc - abs(pdg)==39 || - abs(pdg)==41 || - abs(pdg)==42 || - abs(pdg)== 7 || // 4th gen beauty - abs(pdg)== 8 || // 4th gen top - (600 < abs(pdg) && abs(pdg) < 607) || // scalar leptoquarks - (1000000<abs(pdg) && abs(pdg)<2000000) || // left-handed SUSY (including R-Hadrons) - (2000000<abs(pdg) && abs(pdg)<3000000) || // right-handed SUSY (including R-Hadrons) - abs(pdg)==6000005 || // X5/3 - abs(pdg)==6000006 || // T2/3 - abs(pdg)==6000007 || // B-1/3 - abs(pdg)==6000008 || // Y-4/3 - ( (abs(pdg)>=10000100) && (abs(pdg)<=10001000) ) // multi-charged - ) isBSM = true; - - if (status1 && isBSM) {return true;} else {return false;} - + int pdg = part->pdgId(); + bool status1 = (part->status() == 1); + bool isBSM(false); + + if ((31 < abs(pdg) && abs(pdg) < 38) || // BSM Higgs / W' / Z' / etc + abs(pdg) == 39 || abs(pdg) == 41 || abs(pdg) == 42 || + abs(pdg) == 7 || // 4th gen beauty + abs(pdg) == 8 || // 4th gen top + (600 < abs(pdg) && abs(pdg) < 607) || // scalar leptoquarks + (1000000 < abs(pdg) && + abs(pdg) < 2000000) || // left-handed SUSY (including R-Hadrons) + (2000000 < abs(pdg) && + abs(pdg) < 3000000) || // right-handed SUSY (including R-Hadrons) + abs(pdg) == 6000005 || // X5/3 + abs(pdg) == 6000006 || // T2/3 + abs(pdg) == 6000007 || // B-1/3 + abs(pdg) == 6000008 || // Y-4/3 + ((abs(pdg) >= 10000100) && (abs(pdg) <= 10001000)) // multi-charged + ) + isBSM = true; + + return status1 && isBSM; } diff --git a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinGeantTruthAlg.h b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinGeantTruthAlg.h index 3bcfeb52738fa94979e2558472bd0435d8e5a211..7a29fb73ea691efad6fb0e20ee251ffe88e73200 100644 --- a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinGeantTruthAlg.h +++ b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinGeantTruthAlg.h @@ -4,7 +4,6 @@ Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration */ - #ifndef THINNINGUTILS_ThinGeantTruthAlg_H #define THINNINGUTILS_ThinGeantTruthAlg_H 1 @@ -12,107 +11,103 @@ @class ThinGeantTruthAlg */ - // STL includes +#include <atomic> #include <string> // FrameWork includes -#include "GaudiKernel/ToolHandle.h" +#include "AthenaBaseComps/AthReentrantAlgorithm.h" #include "GaudiKernel/ServiceHandle.h" -#include "AthenaBaseComps/AthAlgorithm.h" +#include "GaudiKernel/ToolHandle.h" #include "StoreGate/ThinningHandleKey.h" -#include "xAODTruth/TruthParticleContainer.h" -#include "xAODTruth/TruthVertexContainer.h" -#include "xAODMuon/MuonContainer.h" #include "xAODEgamma/ElectronContainer.h" #include "xAODEgamma/PhotonContainer.h" -#include "xAODEgamma/PhotonContainer.h" -# +#include "xAODMuon/MuonContainer.h" +#include "xAODTruth/TruthParticleContainer.h" +#include "xAODTruth/TruthVertexContainer.h" -class ThinGeantTruthAlg - : public ::AthAlgorithm +class ThinGeantTruthAlg : public AthReentrantAlgorithm { public: - - /// Constructor with parameters: - ThinGeantTruthAlg( const std::string& name, ISvcLocator* pSvcLocator ); - - /// Destructor: - virtual ~ThinGeantTruthAlg(); - - /// Athena algorithm's initalize hook - virtual StatusCode initialize(); - - /// Athena algorithm's execute hook - virtual StatusCode execute(); - - /// Athena algorithm's finalize hook - virtual StatusCode finalize(); - - /// Inline method - void ancestors(const xAOD::TruthParticle*, - std::vector<bool> &, - std::unordered_set<int> & ); - void descendants(const xAOD::TruthParticle*, - std::vector<bool> &, - std::unordered_set<int> & ); - bool isStatus1BSMParticle(const xAOD::TruthParticle*) const; - - -private: - - /// Should the thinning run? - bool m_doThinning; - - /// Geant barcode - int m_geantOffset; - - /// Geant-decayed longer lived particles - std::vector<int> m_longlived; - - StringProperty m_streamName - { this, "StreamName", "", "Stream for which thinning is to be done." }; - - SG::ThinningHandleKey<xAOD::TruthParticleContainer> m_truthParticlesKey {this, - "TruthParticlesKey", - "TruthParticles", - "Name of the input Truth Particle container"}; - - - SG::ThinningHandleKey<xAOD::TruthVertexContainer> m_truthVerticesKey{this, - "TruthVerticesKey", - "TruthVertices", - "Name of the input Truth Vertices container"}; - - - SG::ReadHandleKey<xAOD::ElectronContainer> m_electronsKey {this, - "ElectronsKey", - "Electrons", - "Name of the input electron container"}; - - SG::ReadHandleKey<xAOD::PhotonContainer> m_photonsKey {this, - "PhotonsKey", - "Photons", - "Name of the input photon container"}; - - SG::ReadHandleKey<xAOD::MuonContainer> m_muonsKey {this, - "MuonsKey", - "Muons", - "Name of the input muon container"}; - - SG::ReadHandleKey<xAOD::TruthParticleContainer> m_egammaTruthKey {this, - "EGammaTruthKey", - "egammaTruthParticles", - "Name of the input egammaTruth container"}; - - /// Counters - unsigned long m_nEventsProcessed; - unsigned long m_nParticlesProcessed; - unsigned long m_nVerticesProcessed; - unsigned long m_nParticlesThinned; - unsigned long m_nVerticesThinned; + using AthReentrantAlgorithm::AthReentrantAlgorithm; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + virtual StatusCode execute(const EventContext& ctx) const override final; + + /// Inline method + void ancestors(const xAOD::TruthParticle*, + std::vector<bool>&, + std::unordered_set<int>&) const; + void descendants(const xAOD::TruthParticle*, + std::vector<bool>&, + std::unordered_set<int>&) const; + static bool isStatus1BSMParticle(const xAOD::TruthParticle*) ; +private: + StringProperty m_streamName{ this, + "StreamName", + "", + "Stream for which thinning is to be done." }; + + Gaudi::Property<int> m_geantOffset{ this, + "GeantBarcodeOffset", + 200000, + "Barcode offset for Geant particles" }; + Gaudi::Property<bool> m_keepMuons{ this, "keepMuons", true }; + Gaudi::Property<bool> m_keepEGamma{ this, "keepEGamma", true }; + + Gaudi::Property<std::vector<int>> m_longlived{ + this, + "LongLivedParticleList", + { 310, 3122, 3222, 3112, 3322, 3312 }, + "List of long lifetime particles which are likely to be decayed by " + "Geant but whose children must be kept" + }; + + SG::ThinningHandleKey<xAOD::TruthParticleContainer> m_truthParticlesKey{ + this, + "TruthParticlesKey", + "TruthParticles", + "Name of the input Truth Particle container" + }; + + SG::ThinningHandleKey<xAOD::TruthVertexContainer> m_truthVerticesKey{ + this, + "TruthVerticesKey", + "TruthVertices", + "Name of the input Truth Vertices container" + }; + + SG::ReadHandleKey<xAOD::ElectronContainer> m_electronsKey{ + this, + "ElectronsKey", + "Electrons", + "Name of the input electron container" + }; + + SG::ReadHandleKey<xAOD::PhotonContainer> m_photonsKey{ + this, + "PhotonsKey", + "Photons", + "Name of the input photon container" + }; + + SG::ReadHandleKey<xAOD::MuonContainer> + m_muonsKey{ this, "MuonsKey", "Muons", "Name of the input muon container" }; + + SG::ReadHandleKey<xAOD::TruthParticleContainer> m_egammaTruthKey{ + this, + "EGammaTruthKey", + "egammaTruthParticles", + "Name of the input egammaTruth container" + }; + + /// Counters + mutable std::atomic<unsigned long> m_nEventsProcessed{}; + mutable std::atomic<unsigned long> m_nParticlesProcessed{}; + mutable std::atomic<unsigned long> m_nVerticesProcessed{}; + mutable std::atomic<unsigned long> m_nParticlesThinned{}; + mutable std::atomic<unsigned long> m_nVerticesThinned{}; }; - #endif //> !THINNINGUTILS_ThinGeantTruthAlg_H diff --git a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinInDetForwardTrackParticlesAlg.cxx b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinInDetForwardTrackParticlesAlg.cxx index 91fbbd3694b9c9138cf02001b56ed681d04559b7..a42450c25af05928dd007803f01a46ec7634f997 100644 --- a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinInDetForwardTrackParticlesAlg.cxx +++ b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinInDetForwardTrackParticlesAlg.cxx @@ -125,7 +125,7 @@ StatusCode ThinInDetForwardTrackParticlesAlg::execute() // Loop over the muons. Identify which are SiliconAssociatedForwardMuon. // Get their associated inner detector track. Find that track in the InDetForwardTrackParticles. // Set the mask element. - for (auto muon : *muons) { + for (const auto *muon : *muons) { if (muon->muonType()==xAOD::Muon::SiliconAssociatedForwardMuon) { ++m_nSiFwdMuons; const xAOD::TrackParticle* muTrk(nullptr); @@ -139,7 +139,7 @@ StatusCode ThinInDetForwardTrackParticlesAlg::execute() // Increment counters for (unsigned int i=0; i<nTracks; ++i) { - if (trackMask[i]==false) ++m_nTracksThinned; + if (!trackMask[i]) ++m_nTracksThinned; } // Apply masks to thinning service diff --git a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinInDetForwardTrackParticlesAlg.h b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinInDetForwardTrackParticlesAlg.h index 798a148a3e281baa5bef2afa288e346992eddea5..d2c8893283e5dda5a3b80fb3a3523de90c097892 100644 --- a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinInDetForwardTrackParticlesAlg.h +++ b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinInDetForwardTrackParticlesAlg.h @@ -64,9 +64,9 @@ private: unsigned long m_nEventsProcessed; unsigned long m_nTracksProcessed; unsigned long m_nTracksThinned; - unsigned long m_nMuons; - unsigned long m_nSiFwdMuons; - unsigned long m_nSiFwdAssoc; + unsigned long m_nMuons = 0UL; + unsigned long m_nSiFwdMuons = 0UL; + unsigned long m_nSiFwdAssoc = 0UL; }; diff --git a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinTrkTrackAlg.cxx b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinTrkTrackAlg.cxx index f9837b499e8d6f850aad040a76b1012fac086112..0cc645cf22ed0505def3a8214145b956e8c9dae2 100644 --- a/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinTrkTrackAlg.cxx +++ b/PhysicsAnalysis/AnalysisCommon/ThinningUtils/src/ThinTrkTrackAlg.cxx @@ -89,7 +89,7 @@ ThinTrkTrackAlg::doEGamma(const EventContext& ctx) const SG::ReadHandle<xAOD::ElectronContainer> electrons(m_electronsKey, ctx); // Loop over electrons - for (auto el : *electrons) { + for (const auto *el : *electrons) { if (el->pt() < m_minptElectrons) { continue; } @@ -114,7 +114,7 @@ ThinTrkTrackAlg::doEGamma(const EventContext& ctx) const SG::ReadHandle<xAOD::PhotonContainer> photons(m_photonsKey, ctx); // Loop over photons - for (auto ph : *photons) { + for (const auto *ph : *photons) { if (ph->pt() < m_minptPhotons) { continue; } @@ -164,7 +164,7 @@ ThinTrkTrackAlg::doMuons(const EventContext& ctx) const // Loop over muons size_t kept(0); - for (auto mu : *muons) { + for (const auto *mu : *muons) { if (mu->pt() < m_minptMuons) { continue; }