ATLAS Offline Software
Loading...
Searching...
No Matches
SystematicsHandles/SystematicsHandles/CopyHelpers.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8#ifndef SYSTEMATICS_HANDLES__COPY_HELPERS_H
9#define SYSTEMATICS_HANDLES__COPY_HELPERS_H
10
19
20#include <memory>
21#include <type_traits>
22#include <utility> //std::declval
23
24namespace CP
25{
26 namespace detail
27 {
29 template <typename T>
31 {
32 template <class, class> class checker;
33
34 template <typename C>
35 static std::true_type test_iparticle(checker<C, decltype((*(const xAOD::IParticle**)nullptr) = ((C*)nullptr)->at(0))> *);
36
37 template <typename C>
38 static std::false_type test_iparticle(...);
39
40 template <typename C>
41 static std::true_type test_container(checker<C, decltype((*(const SG::AuxVectorBase**)nullptr) = ((C*)nullptr))>*);
42
43 template <typename C>
44 static std::false_type test_container(...);
45
50 static const int value = ( std::is_same< std::true_type, decltype( test_iparticle< T >( nullptr ) ) >::value ?
51 1 : ( std::is_same< std::true_type, decltype( test_container< T >( nullptr ) ) >::value ?
52 2 : 3 ) );
53 };
54
62 template<typename T, int type = ContainerType<T>::value>
64 {
65 static_assert ((type==1)||(type==2)||(type==3),
66 "Type can not be shallow copied");
67 };
68
69 template<typename T>
70 struct ShallowCopy<T,1>
71 {
73 public:
74 typedef std::decay<decltype(
75 *(std::declval<EL::AnaAlgorithm>().evtStore()))>::type StoreType;
76
77 static StatusCode
78 getCopy (MsgStream& msgStream, StoreType& store,
79 T*& object, const T *inputObject,
80 const std::string& outputName, const std::string& auxName)
81 {
82 // Define the msg(...) function as a lambda.
83 // Suppress thread-checker warning because this provides just a wrapper to MsgStream.
84 const auto msg = [&] ATLAS_NOT_THREAD_SAFE (MSG::Level lvl) -> MsgStream& {
85 msgStream << lvl;
86 return msgStream;
87 };
88
89 // Make sure that we get a valid pointer.
90 assert (inputObject != nullptr);
91
92 // Handle the case when the input object is a view container.
93 if( ! inputObject->getConstStore() ) {
94
95 // Decide how to handle the container.
96 if( inputObject->size() ) {
97 // Get the pointer to the "owning container" from the first
98 // element.
99 const T* originContainer =
100 dynamic_cast< const T* >( ( *inputObject )[ 0 ]->container() );
101 if (!originContainer){
102 ANA_MSG_ERROR( "Dynamic cast failed." );
103 return StatusCode::FAILURE;
104 }
105 // Make sure that every element in the view container has the same
106 // parent.
107 for( size_t i = 1; i < inputObject->size(); ++i ) {
108 if( ( *inputObject )[ i ]->container() != originContainer ) {
109 ANA_MSG_ERROR( "Not all elements of the received view "
110 "container come from the same container!" );
111 return StatusCode::FAILURE;
112 }
113 }
114 // Postfix for the shallow-copy container of the origin container.
115 static const char* const ORIGIN_POSTFIX = "_ShallowCopyOrigin";
116 // Make a shallow copy of the origin container.
117 auto originCopy = xAOD::shallowCopyContainer( *originContainer );
118 if( ( ! originCopy.first ) || ( ! originCopy.second ) ) {
119 ANA_MSG_ERROR( "Failed to shallow copy the origin of a view "
120 << "container, meant for: " << outputName );
121 return StatusCode::FAILURE;
122 }
123 // ...and record it.
124 ANA_CHECK( store.record( originCopy.first,
125 outputName + ORIGIN_POSTFIX ) );
126 ANA_CHECK( store.record( originCopy.second,
127 outputName + ORIGIN_POSTFIX + "Aux." ) );
128 // Make a view copy on top of it.
129 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
130 auto viewCopyPtr = viewCopy.get();
131 for( const auto* element : *inputObject ) {
132 viewCopy->push_back( originCopy.first->at( element->index() ) );
133 }
134 // Set the origin links on it. Note that
135 // xAOD::setOriginalObjectLink's "container version" doesn't work
136 // with view containers, we have to call this function one-by-one
137 // on the elements.
138 for( size_t i = 0; i < inputObject->size(); ++i ) {
139 if( ! xAOD::setOriginalObjectLink( *( ( *inputObject )[ i ] ),
140 *( ( *viewCopy )[ i ] ) ) ) {
141 return StatusCode::FAILURE;
142 }
143 }
144 // Finally, record the view container with the requested name.
145 ANA_CHECK( store.record( viewCopy.release(), outputName ) );
146 // The copy is done.
147 object = viewCopyPtr;
148 return StatusCode::SUCCESS;
149 } else {
150 // If the container was empty, then let's just make a new empty
151 // container, and that's that...
152 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
153 auto viewCopyPtr = viewCopy.get();
154 ANA_CHECK( store.record( viewCopy.release(), outputName ) );
155 // The copy is done.
156 object = viewCopyPtr;
157 return StatusCode::SUCCESS;
158 }
159
160 } else {
161
162 // We can just copy the container as is.
163 auto copy = xAOD::shallowCopyContainer( *inputObject );
164 if (!copy.first || !copy.second)
165 {
166 ANA_MSG_ERROR ("failed to shallow copy object: " << outputName);
167 ANA_MSG_ERROR ("likely shallow copying a view container");
168 return StatusCode::FAILURE;
169 }
170
171 if (!xAOD::setOriginalObjectLink (*inputObject, *copy.first)) {
172 return StatusCode::FAILURE;
173 }
174
175 ANA_CHECK (store.record (copy.second, auxName));
176 ANA_CHECK (store.record (copy.first, outputName));
177 object = copy.first;
178 return StatusCode::SUCCESS;
179 }
180 }
181 };
182
183 template<typename T>
184 struct ShallowCopy<T,2>
185 {
187 public:
188 typedef std::decay<decltype(
189 *(std::declval<EL::AnaAlgorithm>().evtStore()))>::type StoreType;
190
191 static StatusCode
192 getCopy (MsgStream& msgStream, StoreType& store,
193 T*& object, const T *inputObject,
194 const std::string& outputName, const std::string& auxName)
195 {
196 // Define the msg(...) function as a lambda.
197 // Suppress thread-checker warning because this provides just a wrapper to MsgStream.
198 const auto msg = [&] ATLAS_NOT_THREAD_SAFE (MSG::Level lvl) -> MsgStream& {
199 msgStream << lvl;
200 return msgStream;
201 };
202
203 // Make sure that we get a valid pointer.
204 assert (inputObject != nullptr);
205
206 // Handle the case when the input object is a view container.
207 if( ! inputObject->getConstStore() ) {
208
209 // Decide how to handle the container.
210 if( inputObject->size() ) {
211 // Get the pointer to the "owning container" from the first
212 // element.
213 const T* originContainer = dynamic_cast< const T* >( ( *inputObject )[ 0 ]->container() );
214 if (!originContainer){
215 ANA_MSG_ERROR( "Dynamic cast returned nullptr!" );
216 return StatusCode::FAILURE;
217 }
218 // Make sure that every element in the view container has the same
219 // parent.
220 for( size_t i = 1; i < inputObject->size(); ++i ) {
221 if( ( *inputObject )[ i ]->container() != originContainer ) {
222 ANA_MSG_ERROR( "Not all elements of the received view "
223 "container come from the same container!" );
224 return StatusCode::FAILURE;
225 }
226 }
227 // Postfix for the shallow-copy container of the origin container.
228 static const char* const ORIGIN_POSTFIX = "_ShallowCopyOrigin";
229 // Make a shallow copy of the origin container.
230 auto originCopy = xAOD::shallowCopyContainer( *originContainer );
231 if( ( ! originCopy.first ) || ( ! originCopy.second ) ) {
232 ANA_MSG_ERROR( "Failed to shallow copy the origin of a view "
233 << "container, meant for: " << outputName );
234 return StatusCode::FAILURE;
235 }
236 // ...and record it.
237 ANA_CHECK( store.record( originCopy.first,
238 outputName + ORIGIN_POSTFIX ) );
239 ANA_CHECK( store.record( originCopy.second,
240 outputName + ORIGIN_POSTFIX +
241 "Aux." ) );
242 // Make a view copy on top of it.
243 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
244 auto viewCopyPtr = viewCopy.get();
245 for( const auto* element : *inputObject ) {
246 viewCopy->push_back( originCopy.first->at( element->index() ) );
247 }
248 // Finally, record the view container with the requested name.
249 ANA_CHECK( store.record( viewCopy.release(), outputName ) );
250 // The copy is done.
251 object = viewCopyPtr;
252 return StatusCode::SUCCESS;
253 } else {
254 // If the container was empty, then let's just make a new empty
255 // container, and that's that...
256 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
257 auto viewCopyPtr = viewCopy.get();
258 ANA_CHECK( store.record( viewCopy.release(), outputName ) );
259 // The copy is done.
260 object = viewCopyPtr;
261 return StatusCode::SUCCESS;
262 }
263
264 } else {
265
266 // We can just copy the container as is.
267 auto copy = xAOD::shallowCopyContainer( *inputObject );
268 if (!copy.first || !copy.second)
269 {
270 ANA_MSG_ERROR ("failed to shallow copy object: " << outputName);
271 ANA_MSG_ERROR ("likely shallow copying a view container");
272 return StatusCode::FAILURE;
273 }
274
275 ANA_CHECK (store.record (copy.second, auxName));
276 ANA_CHECK (store.record (copy.first, outputName));
277 object = copy.first;
278 return StatusCode::SUCCESS;
279 }
280 }
281 };
282
283 template<typename T>
284 struct ShallowCopy<T,3>
285 {
287 public:
288 typedef std::decay<decltype(
289 *(std::declval<EL::AnaAlgorithm>().evtStore()))>::type StoreType;
290
291 static StatusCode
292 getCopy (MsgStream& msgStream, StoreType& store,
293 T*& object, const T *inputObject,
294 const std::string& outputName, const std::string& auxName)
295 {
296 // Define the msg(...) function as a lambda.
297 // Suppress thread-checker warning because this provides just a wrapper to MsgStream.
298 const auto msg = [&] ATLAS_NOT_THREAD_SAFE (MSG::Level lvl) -> MsgStream& {
299 msgStream << lvl;
300 return msgStream;
301 };
302
303 // We can just copy the object as is.
304 auto copy = xAOD::shallowCopyObject( *inputObject );
305 if (!copy.first || !copy.second)
306 {
307 ANA_MSG_ERROR ("failed to shallow copy object: " << outputName);
308 ANA_MSG_ERROR ("likely shallow copying a view container");
309 return StatusCode::FAILURE;
310 }
311
312 ANA_CHECK (store.record (copy.second, auxName));
313 ANA_CHECK (store.record (copy.first, outputName));
314 object = copy.first;
315 return StatusCode::SUCCESS;
316 }
317 };
318
319 template<>
321 {
323 public:
324 typedef std::decay<decltype(
325 *(std::declval<EL::AnaAlgorithm>().evtStore()))>::type StoreType;
326 static StatusCode
327 getCopy (MsgStream& msgStream, StoreType& store,
329 const xAOD::IParticleContainer *inputObject,
330 const std::string& outputName, const std::string& auxName);
331 };
332 }
333}
334
335#endif
macros for messaging and checking status codes
#define ANA_MSG_ERROR(xmsg)
Macro printing error messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
Define macros for attributes used to control the static checker.
void record(const T *p, const std::string &key)
Definition TestStore.h:81
Manage index tracking and synchronization of auxiliary data.
Class providing the definition of the 4-vector interface.
struct color C
Select isolated Photons, Electrons and Muons.
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
STL namespace.
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
std::pair< std::unique_ptr< T >, std::unique_ptr< ShallowAuxContainer > > shallowCopyContainer(const T &cont, const EventContext &ctx)
Function making a shallow copy of a constant container.
bool setOriginalObjectLink(const IParticle &original, IParticle &copy)
This function should be used by CP tools when they make a deep copy of an object in their correctedCo...
std::pair< T *, ShallowAuxInfo * > shallowCopyObject(const T &obj)
Function making a shallow copy of a constant standalone object.
void ClearTransientTrees ATLAS_NOT_THREAD_SAFE()
Function cleaning up the managed memory.
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.
check what kind of object/container the argument is
static std::true_type test_container(checker< C, decltype((*(const SG::AuxVectorBase **) nullptr)=((C *) nullptr))> *)
static std::false_type test_iparticle(...)
static std::false_type test_container(...)
static std::true_type test_iparticle(checker< C, decltype((*(const xAOD::IParticle **) nullptr)=((C *) nullptr) ->at(0))> *)
std::decay< decltype(*(std::declval< EL::AnaAlgorithm >().evtStore()))>::type StoreType
the type of the event store we use
static StatusCode getCopy(MsgStream &msgStream, StoreType &store, T *&object, const T *inputObject, const std::string &outputName, const std::string &auxName)
static StatusCode getCopy(MsgStream &msgStream, StoreType &store, T *&object, const T *inputObject, const std::string &outputName, const std::string &auxName)
std::decay< decltype(*(std::declval< EL::AnaAlgorithm >().evtStore()))>::type StoreType
the type of the event store we use
std::decay< decltype(*(std::declval< EL::AnaAlgorithm >().evtStore()))>::type StoreType
the type of the event store we use
static StatusCode getCopy(MsgStream &msgStream, StoreType &store, T *&object, const T *inputObject, const std::string &outputName, const std::string &auxName)
std::decay< decltype(*(std::declval< EL::AnaAlgorithm >().evtStore()))>::type StoreType
the type of the event store we use
static StatusCode getCopy(MsgStream &msgStream, StoreType &store, xAOD::IParticleContainer *&object, const xAOD::IParticleContainer *inputObject, const std::string &outputName, const std::string &auxName)
a helper class to create shallow copies and register them in the event store
MsgStream & msg
Definition testRead.cxx:32