ATLAS Offline Software
ParticleRemoverAlg.icc
Go to the documentation of this file.
1 // Dear emacs, this is -*- c++ -*-
2 
3 /*
4  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 
8 #include "xAODBase/IParticle.h"
9 #include "AthContainers/AuxTypeRegistry.h"
10 #include "AthContainersInterfaces/IAuxTypeVectorFactory.h"
11 #include "xAODCore/AuxContainerBase.h"
12 #include "xAODCore/ShallowCopy.h"
13 #include "AthContainers/ConstDataVector.h"
14 
15 
16 template<class CONT>
17 StatusCode ParticleRemoverAlg::removeParticles( const std::vector<bool>& keepParticleVec )
18 {
19  ATH_MSG_DEBUG ("removeParticles(...) " << name() << "...");
20 
21  // Get the type of particle that the current container CONT has
22  typedef typename CONT::base_value_type PART;
23 
24  // First, get the size of the current input container
25  const std::size_t inContSize = m_inContList[0]->size();
26 
27  // Create a new output container and its associated auxiliary container
28  CONT* outCont = new CONT(SG::OWN_ELEMENTS);
29  outCont->reserve(inContSize);
30  ATH_CHECK( evtStore()->record ( outCont, m_outContNameList.at(0) ) );
31  xAOD::AuxContainerBase* outAuxContainer = new xAOD::AuxContainerBase();
32  outAuxContainer->reserve(inContSize);
33  ATH_CHECK( evtStore()->record( outAuxContainer, m_outContNameList.at(0) + "Aux." ) );
34  outCont->setStore( outAuxContainer );
35  m_outContList.push_back(outCont);
36 
37  // Create a vector for the original indices of the input particles in their container
38  std::vector< std::size_t > inPartIdxList;
39  inPartIdxList.reserve(inContSize);
40  // Also, create a map from the old index to the new one using a vector with
41  // the same size as the old input containers has.
42  std::vector<int> oldToNewIndex;
43  oldToNewIndex.reserve(inContSize);
44 
45  // Now, copy the elements that we want to keep from the input container to the
46  // output container.
47  for ( std::size_t i=0; i<inContSize; ++i ){
48  if ( keepParticleVec[i] == false ){
49  oldToNewIndex.push_back(-1);
50  continue; // we don't want to keep this particle
51  }
52  const xAOD::IParticle* inPart = m_inContList[0]->at(i);
53  const std::size_t inPartIdx = inPart->index();
54  // Now, copy over the input particle to the output particle
55  // (use a pre-processor macro for this repeated task)
56  PART* outPart = new PART();
57  outCont->push_back(outPart);
58  *outPart = *(static_cast<const PART*>(inPart));
59  // Store also the orignial index for this particle
60  inPartIdxList.push_back(inPartIdx);
61  oldToNewIndex.push_back( inPartIdxList.size() - 1 );
62  }
63 
64  // Get the size of the output container
65  const std::size_t outContSize = outCont->size();
66 
67  // Get the global registry for all aux data:
68  SG::AuxTypeRegistry& reg = SG::AuxTypeRegistry::instance();
69 
70 
71  // Now, do also the selection for all shallow copy containers, i.e., create
72  // new ones for the outCont that we just created and copy the values
73  // from the original input shallow copy containers over to these new ones
74  for ( std::size_t contIdx=1; contIdx<m_outContNameList.size(); ++contIdx ) {
75  // Get the original electron shallow copy container
76  const auto* originalShallowCopyCont = m_inContList.at(contIdx);
77  ATH_MSG_VERBOSE("Got input ShallowCopyContainer with name: " << m_inContNameList.at(contIdx));
78 
79  // Create the current shallow copy container and record it to StoreGate
80  auto outContShallowCopy = xAOD::shallowCopyContainer( *outCont );
81  ATH_CHECK( evtStore()->record( outContShallowCopy.first, m_outContNameList.at(contIdx) ) );
82  ATH_CHECK( evtStore()->record( outContShallowCopy.second, m_outContNameList.at(contIdx) + "Aux." ) );
83  ATH_MSG_VERBOSE("Recorded new output ShallowCopyContainer with name: " << m_outContNameList.at(contIdx));
84 
85  // Also add the output shallow copy to the list of output containers
86  m_outContList.push_back(outContShallowCopy.first);
87 
88  // Copy the variables that are stored in the input ShallowCopyContainer
89  // locally (i.e., NOT only present in the master container, but where the
90  // variable lives in the ShallowCopyContainer) from there
91  // If the input had size zero, we are done
92  if ( originalShallowCopyCont->size() == 0 ) {
93  ATH_MSG_VERBOSE("Input ShallowCopy container has size zero... we are done");
94  continue;
95  }
96 
97  // Get the auxIDs, i.e., the identifiers from the input ShallowCopyContainer
98  const xAOD::ShallowAuxContainer* originalShallowCopyAuxCont
99  = dynamic_cast<const xAOD::ShallowAuxContainer*>(originalShallowCopyCont->getStore());
100  if ( !originalShallowCopyAuxCont ) {
101  ATH_MSG_ERROR("We don't seem to have a ShallowAuxContainer");
102  return StatusCode::FAILURE;
103  }
104  const SG::IAuxStore* auxStore = originalShallowCopyAuxCont->getStore();
105  if (!auxStore) {
106  ATH_MSG_FATAL("Could not get the aux store of the original ShallowCopyContainer");
107  return StatusCode::FAILURE;
108  }
109  const SG::auxid_set_t& auxIDs = auxStore->getAuxIDs();
110  ATH_MSG_DEBUG("We have " << auxIDs.size() << " variables to copy over for this ShallowCopyContainer");
111 
112  // Iterate over all auxIDs and copy each one over
113  for ( auto auxid : auxIDs ) {
114  ATH_MSG_VERBOSE("We are now at auxID=" << auxid );
115 
116  // Get the type of this variable:
117  const std::type_info* type = reg.getType( auxid );
118  if ( ! type ) {
119  ATH_MSG_FATAL("Could not get the type of auxid: " << auxid );
120  return StatusCode::FAILURE;
121  }
122  ATH_MSG_VERBOSE("Got the type with name: " << type->name() );
123 
124  // First let's get the vector factory of this variable:
125  const SG::IAuxTypeVectorFactory* factory =
126  SG::AuxTypeRegistry::instance().getFactory( auxid );
127  if ( ! factory ) {
128  ATH_MSG_FATAL("Could not get the vector factory for type: " << type->name() );
129  return StatusCode::FAILURE;
130  }
131  ATH_MSG_VERBOSE("Got the vector factory for type: " << type->name() );
132 
133 
134  // If the parent doesn't have this variable, then we're done already:
135  const void* originalShallowAuxDataVector = auxStore->getData( auxid );
136  if ( ! originalShallowAuxDataVector ) {
137  ATH_MSG_WARNING("Could not get the aux data vector of the original ShallowCopyContainer for auxid=" << auxid
138  << ". The input container had size " << originalShallowCopyCont->size()
139  << ", and the output container had size " << outContSize );
140  continue;
141  //return StatusCode::FAILURE;
142  }
143  ATH_MSG_VERBOSE("This auxID=" << auxid << " is part of the ShallowCopyAuxStore...");
144 
145  // Create the variable in the dynamic store of the new ShallowCopyContainer
146  (void)outContShallowCopy.second->getData( auxid, outContSize, outContSize );
147 
148 
149  // Then, loop over these, get the index of the corresponding object in the
150  // input shallow copy container and copy the variables that are stored there
151  // locally (i.e., NOT only present in the master container, but where the
152  // variable lives in the ShallowCopyContainer) from there
153  for ( std::size_t i=0; i<outContSize; ++i ) {
154  // Get the original shallow copy particle
155  const std::size_t inIdx = inPartIdxList.at(i);
156  factory->copy( auxid, *outContShallowCopy.first, i, *originalShallowCopyCont, inIdx, 1 );
157  }
158 
159  } // End: Loop over all aux-ids
160 
161  } // End: loop over output shallow copy containers
162 
163 
164  // Now, also create the new view containers that point to the objects in the
165  // new, reduced, containers that we just produced above (both the master
166  // container and all its shallow copy containers).
167  /// This will only be done if we have a valid prefix.
168  if ( !(m_outPrefix.value().empty()) ){
169  ATH_MSG_DEBUG("Will now also go and create new output view containers with the prefix " << m_outPrefix.value() );
170  for ( std::size_t i=0; i<m_inViewContNameListList.size(); ++i ){
171  const std::vector<std::string>& inViewNames = m_inViewContNameListList[i];
172  const std::vector<std::string>& outViewNames = m_outViewContNameListList[i];
173  const xAOD::IParticleContainer* currentOutCont = m_outContList[i];
174  for ( std::size_t j=0; j<inViewNames.size(); ++j ){
175  const std::string& inViewName = inViewNames[j];
176  const std::string& outViewName = outViewNames[j];
177  ATH_MSG_VERBOSE("Going to create a new view container with name '" << outViewName
178  << "' from original view container with name '" << inViewName << "'" );
179  const xAOD::IParticleContainer* inViewCont = nullptr;
180  ATH_CHECK( evtStore()->retrieve( inViewCont, inViewName ) );
181  ConstDataVector<CONT>* outViewCont = new ConstDataVector<CONT>(SG::VIEW_ELEMENTS);
182  outViewCont->reserve(inViewCont->size());
183  ATH_CHECK( evtStore()->record ( outViewCont, outViewName ) );
184  for ( const xAOD::IParticle* inViewPart : *inViewCont ){
185  const std::size_t oldIdx = inViewPart->index();
186  const std::size_t newIdx = oldToNewIndex[oldIdx];
187  const xAOD::IParticle* outPart = (*currentOutCont)[newIdx];
188  outViewCont->push_back(static_cast<const PART*>(outPart));
189  }
190  }
191  }
192  }
193 
194 
195  // Now, also try to re-bend the existing view containers to point to the new
196  // containers.
197  if (m_resetViewConts.value()){
198  ATH_MSG_DEBUG("Will now also go and try to re-map the input view containers to the new containers");
199  for ( std::size_t i=0; i<m_inViewContNameListList.size(); ++i ){
200  const std::vector<std::string>& inViewNames = m_inViewContNameListList[i];
201  const xAOD::IParticleContainer* currentOutCont = m_outContList[i];
202  for ( std::size_t j=0; j<inViewNames.size(); ++j ){
203  const std::string& inViewName = inViewNames[j];
204  ATH_MSG_VERBOSE("Going to re-map existing view container with name '" << inViewName << "'" );
205  const CONT* inViewCont = nullptr;
206  ATH_CHECK( evtStore()->retrieve( inViewCont, inViewName ) );
207  ATH_MSG_DEBUG("Got the input view container with name: " << inViewName << " and size: " << inViewCont->size() );
208  ConstDataVector<CONT>* outViewCont = new ConstDataVector<CONT>(SG::VIEW_ELEMENTS);
209  outViewCont->reserve(inViewCont->size());
210  for ( std::size_t partIdx=0; partIdx<inViewCont->size(); ++partIdx ){
211  const PART* inViewPart = inViewCont->at(partIdx);
212  const SG::AuxVectorData* oldCont = inViewPart->container();
213  const std::size_t oldIdx = inViewPart->index();
214  const std::size_t newIdx = oldToNewIndex[oldIdx];
215  const xAOD::IParticle* outPart = (*currentOutCont)[newIdx];
216  outViewCont->push_back(static_cast<const PART*>(outPart));
217  ATH_MSG_VERBOSE("Did re-map particle from old index " << oldIdx
218  << " to new index " << inViewCont->at(partIdx)->index()
219  << " and old container " << oldCont
220  << " to new container " << inViewCont->at(partIdx)->container() );
221  }
222  ATH_MSG_DEBUG("Going to overwrite view container with name: " << inViewName << " and size: " << outViewCont->size() );
223  for ( const PART* part : *outViewCont ){
224  ATH_MSG_VERBOSE("Have an old pointer adress of: " << part );
225  ATH_MSG_VERBOSE("Have an old particle with pt= " << 0.001*(part->pt()) );
226  }
227  ATH_CHECK( evtStore()->overwrite( outViewCont, inViewName ) );
228  ATH_MSG_DEBUG("Did overwrite view container with name: " << inViewName << " and size: " << outViewCont->size() );
229  for ( const PART* part : *outViewCont ){
230  ATH_MSG_VERBOSE("Have a new pointer adress of: " << part );
231  ATH_MSG_VERBOSE("Have a new particle with pt= " << 0.001*(part->pt()) );
232  }
233  }
234  }
235  }
236 
237  return StatusCode::SUCCESS;
238 }