1 // Dear emacs, this is -*- c++ -*-
4 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
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"
17 StatusCode ParticleRemoverAlg::removeParticles( const std::vector<bool>& keepParticleVec )
19 ATH_MSG_DEBUG ("removeParticles(...) " << name() << "...");
21 // Get the type of particle that the current container CONT has
22 typedef typename CONT::base_value_type PART;
24 // First, get the size of the current input container
25 const std::size_t inContSize = m_inContList[0]->size();
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);
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);
45 // Now, copy the elements that we want to keep from the input container to the
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
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 );
64 // Get the size of the output container
65 const std::size_t outContSize = outCont->size();
67 // Get the global registry for all aux data:
68 SG::AuxTypeRegistry& reg = SG::AuxTypeRegistry::instance();
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));
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));
85 // Also add the output shallow copy to the list of output containers
86 m_outContList.push_back(outContShallowCopy.first);
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");
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;
104 const SG::IAuxStore* auxStore = originalShallowCopyAuxCont->getStore();
106 ATH_MSG_FATAL("Could not get the aux store of the original ShallowCopyContainer");
107 return StatusCode::FAILURE;
109 const SG::auxid_set_t& auxIDs = auxStore->getAuxIDs();
110 ATH_MSG_DEBUG("We have " << auxIDs.size() << " variables to copy over for this ShallowCopyContainer");
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 );
116 // Get the type of this variable:
117 const std::type_info* type = reg.getType( auxid );
119 ATH_MSG_FATAL("Could not get the type of auxid: " << auxid );
120 return StatusCode::FAILURE;
122 ATH_MSG_VERBOSE("Got the type with name: " << type->name() );
124 // First let's get the vector factory of this variable:
125 const SG::IAuxTypeVectorFactory* factory =
126 SG::AuxTypeRegistry::instance().getFactory( auxid );
128 ATH_MSG_FATAL("Could not get the vector factory for type: " << type->name() );
129 return StatusCode::FAILURE;
131 ATH_MSG_VERBOSE("Got the vector factory for type: " << type->name() );
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 );
141 //return StatusCode::FAILURE;
143 ATH_MSG_VERBOSE("This auxID=" << auxid << " is part of the ShallowCopyAuxStore...");
145 // Create the variable in the dynamic store of the new ShallowCopyContainer
146 (void)outContShallowCopy.second->getData( auxid, outContSize, outContSize );
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 );
159 } // End: Loop over all aux-ids
161 } // End: loop over output shallow copy containers
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));
195 // Now, also try to re-bend the existing view containers to point to the new
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() );
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()) );
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()) );
237 return StatusCode::SUCCESS;