1 // Dear emacs, this is -*- c++ -*-
4 Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
8 #include "xAODBase/IParticle.h"
9 #include "xAODCore/AuxContainerBase.h"
10 #include "AthContainers/ConstDataVector.h"
11 #include "xAODEventInfo/EventInfo.h"
12 #include "xAODCutFlow/CutBookkeeperContainer.h"
13 #include "PATCore/AcceptInfo.h"
14 #include "PATCore/AcceptData.h"
18 template<class CONT, class AUXCONT>
19 StatusCode ParticleSelectionAlg::selectParticles(const xAOD::IParticleContainer* inContainer,
20 const std::vector<int>& resultVec) const
22 ATH_MSG_DEBUG ("selectParticlesStepTwo<CONT,AUXCONT>(...) " << name() << "...");
24 // Get the type of particle that the current container CONT has
25 typedef typename CONT::base_value_type PART;
27 // Create a new output container and its associated auxiliary container
28 CONT* outCont = nullptr;
29 ConstDataVector<CONT>* outContConst = nullptr;
31 if ( m_outOwnPolicy == SG::OWN_ELEMENTS ) {
32 outCont = new CONT( m_outOwnPolicy );
33 ATH_CHECK( evtStore()->record ( outCont, m_outCollKey.value() ) );
34 if ( m_writeSplitAux.value() ) {
35 xAOD::AuxContainerBase* outAuxContainer = new xAOD::AuxContainerBase();
36 ATH_CHECK( evtStore()->record( outAuxContainer, m_outCollKey.value() + "Aux." ) );
37 outCont->setStore( outAuxContainer );
38 ATH_MSG_VERBOSE("Recorded xAOD::AuxContainerBase for container: " << m_outCollKey.value() );
41 AUXCONT* outAuxContainer = new AUXCONT();
42 ATH_CHECK( evtStore()->record( outAuxContainer, m_outCollKey.value() + "Aux." ) );
43 outCont->setStore( outAuxContainer );
44 ATH_MSG_VERBOSE("Recorded AuxContainer for container: " << m_outCollKey.value() );
48 outContConst = new ConstDataVector<CONT>( m_outOwnPolicy );
49 ATH_CHECK( evtStore()->record ( outContConst, m_outCollKey.value() ) );
50 ATH_MSG_VERBOSE("Recorded ConstDataVector for container: " << m_outCollKey.value() );
52 // ATH_MSG_VERBOSE("StoreGate dump: " << evtStore()->dump() );
54 // Get the CutBookkeeperContainer, if cut-flow bookkeeping was requested
55 double eventWeight = 1.0;
56 xAOD::CutBookkeeperContainer* cutBKCont = nullptr;
57 const xAOD::EventInfo* evtInfo = nullptr;
59 ATH_CHECK( outputMetaStore()->retrieve(cutBKCont, m_cutBKCName.value() ) );
60 // Also, get the event info as we need to get the MC-weight for this event
61 ATH_CHECK( evtStore()->retrieve( evtInfo, m_evtInfoName.value() ));
62 const bool isSim = evtInfo->eventType(xAOD::EventInfo::EventType::IS_SIMULATION);
64 eventWeight = static_cast<double>( evtInfo->mcEventWeight() );
65 ATH_MSG_VERBOSE("Got MC event weight of " << eventWeight );
70 // Now, loop over the input container and check which particles to write out
71 ATH_MSG_DEBUG("Input container has size " << inContainer->size() );
72 for ( std::size_t i=0; i<inContainer->size(); ++i ) {
73 const xAOD::IParticle* partBase = inContainer->at(i);
74 const PART* part = static_cast<const PART*>(partBase);
76 // ================================
77 // Apply the selection tools
78 // ================================
79 // The default object pass value. As soon as one cut is not passed, then
80 // the remainder of the cuts will not even be tried
81 bool passEverything = true;
83 //------------- for the AsgSelectionTools --------------
84 // Loop over all selection tools
85 ATH_MSG_VERBOSE("Loop over all selection tools");
86 for ( std::size_t toolIdx=0; toolIdx < m_selTools.size(); ++toolIdx ){
88 ATH_MSG_VERBOSE("Now going to try AsgSelectionTools number " << toolIdx );
89 const asg::AcceptData acceptData = m_selTools[toolIdx]->accept(part);
90 if (!m_doCutFlow){ passEverything &= static_cast<bool>(acceptData); }
92 const std::size_t cbkStartIdx = m_selToolIdxOffset[toolIdx];
93 const unsigned int nCuts = acceptData.getNCuts();
94 for ( unsigned int iCut=0; iCut<nCuts; ++iCut ){
95 passEverything &= acceptData.getCutResult(iCut);
97 const std::size_t currentCBKIdx = cbkStartIdx + iCut;
98 xAOD::CutBookkeeper* cutBK = cutBKCont->at(currentCBKIdx);
99 cutBK->addNAcceptedEvents(1);
100 cutBK->addSumOfEventWeights(eventWeight);
101 cutBK->addSumOfEventWeightsSquared(eventWeight*eventWeight);
104 } // Done doing detailed particle cut-flow for this tool
105 ATH_MSG_VERBOSE("AsgSelectionTools number " << toolIdx << " passed/failed: " << passEverything );
109 //------------- for the ExpressionParsing in this algorithm --------------
110 ATH_MSG_VERBOSE("Looking at expression parser result: " << passEverything);
111 if ( passEverything && !(resultVec.empty()) ){
112 // If this particle is not accepted by the expression parser, go to the next one
113 ATH_MSG_VERBOSE("Now going to try expression '" << m_selection.value() << "'" );
114 passEverything &= static_cast<bool>(resultVec.at(i));
115 ATH_MSG_VERBOSE("Expression '" << m_selection.value() << "' passed/failed: " << passEverything
116 << ", particle index=" << part->index() <<", pt=" << 0.001*(part->pt()) << " GeV, eta="
117 << part->eta() << ", phi=" << part->phi() );
118 if (passEverything && m_doCutFlow){
119 xAOD::CutBookkeeper* cutBK = cutBKCont->at(m_idxSelParster);
120 cutBK->addNAcceptedEvents(1);
121 cutBK->addSumOfEventWeights(eventWeight);
122 cutBK->addSumOfEventWeightsSquared(eventWeight*eventWeight);
126 // Now, if all cuts are passed, write out the current particle to the
129 ATH_MSG_VERBOSE("Going to fill output container with particle with pt=" << 0.001*(part->pt())
130 << " GeV, eta=" << part->eta() );
131 if ( m_outOwnPolicy == SG::OWN_ELEMENTS ) {
132 PART* newPart = new PART();
133 outCont->push_back(newPart);
137 outContConst->push_back(part);
141 } // End: Loop over input particles
143 return StatusCode::SUCCESS;