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