ATLAS Offline Software
ParticleSelectionAlg.icc
Go to the documentation of this file.
1 // Dear emacs, this is -*- c++ -*-
2 
3 /*
4  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 
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"
15 
16 
17 
18 template<class CONT, class AUXCONT>
19 StatusCode ParticleSelectionAlg::selectParticles(const xAOD::IParticleContainer* inContainer,
20  const std::vector<int>& resultVec) const
21 {
22  ATH_MSG_DEBUG ("selectParticlesStepTwo<CONT,AUXCONT>(...) " << name() << "...");
23 
24  // Get the type of particle that the current container CONT has
25  typedef typename CONT::base_value_type PART;
26 
27  // Create a new output container and its associated auxiliary container
28  CONT* outCont = nullptr;
29  ConstDataVector<CONT>* outContConst = nullptr;
30 
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() );
39  }
40  else {
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() );
45  }
46  }
47  else {
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() );
51  }
52  // ATH_MSG_VERBOSE("StoreGate dump: " << evtStore()->dump() );
53 
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;
58  if (m_doCutFlow){
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);
63  if (isSim){
64  eventWeight = static_cast<double>( evtInfo->mcEventWeight() );
65  ATH_MSG_VERBOSE("Got MC event weight of " << eventWeight );
66  }
67  }
68 
69 
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);
75 
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;
82 
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 ){
87  if (passEverything){
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); }
91  else {
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);
96  if (passEverything){
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);
102  }
103  }
104  } // Done doing detailed particle cut-flow for this tool
105  ATH_MSG_VERBOSE("AsgSelectionTools number " << toolIdx << " passed/failed: " << passEverything );
106  }
107  }
108 
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);
123  }
124  }
125 
126  // Now, if all cuts are passed, write out the current particle to the
127  // output container
128  if (passEverything){
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);
134  *newPart = *part;
135  }
136  else {
137  outContConst->push_back(part);
138  }
139  }
140 
141  } // End: Loop over input particles
142 
143  return StatusCode::SUCCESS;
144 }