ATLAS Offline Software
IDC_OverlayBase.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 /// @author Tadej Novak
6 /// @author Christos Anastopoulos DataPool strategy
7 /// @author Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
8 
9 #include <Identifier/Identifier.h>
10 #include <Identifier/IdentifierHash.h>
11 
12 #include "AthContainers/OwnershipPolicy.h"
13 
14 #include "IDC_OverlayCommon.h"
15 
16 template <bool usePool, typename Type, typename IDC_Container>
17 StatusCode IDC_OverlayBase::overlayContainerImpl(
18  const IDC_Container *bkgContainer,
19  const IDC_Container *signalContainer,
20  IDC_Container *outputContainer,
21  DataPool<Type> *dataItems) const
22 {
23 
24  ATH_MSG_DEBUG("overlayContainer<>() begin");
25  typedef typename IDC_Container::base_value_type Collection;
26 
27  // There are some use cases where background is empty
28  if (!bkgContainer) {
29  // Only loop through the signal collections and copy them over
30  for (const auto &[hashId, ptr] : signalContainer->GetAllHashPtrPair()) {
31  // Copy the signal collection
32  std::unique_ptr<Collection> signalCollection = nullptr;
33  if constexpr (usePool){
34  signalCollection = Overlay::copyCollection(hashId, ptr, *dataItems);
35  } else {
36  signalCollection = Overlay::copyCollection(hashId, ptr);
37  }
38  if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
39  ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
40  return StatusCode::FAILURE;
41  } else {
42  (void)signalCollection.release();
43  }
44  }
45 
46  return StatusCode::SUCCESS;
47  }
48 
49 
50  // The MC signal container should typically be smaller than bkgContainer,
51  // because the latter contains all the noise, minimum bias and pile up.
52  // Thus we firstly iterate over signal hashes and store them in a map.
53  std::vector < std::pair<IdentifierHash, bool> > overlapMap;
54  overlapMap.reserve(signalContainer->numberOfCollections());
55  for (const auto &[hashId, ptr] : signalContainer->GetAllHashPtrPair()) {
56  overlapMap.emplace_back(hashId, false);
57  }
58 
59  // Now loop through the background hashes and copy unique ones over
60  for (const auto &[hashId, ptr] : bkgContainer->GetAllHashPtrPair()) {
61  auto search = std::lower_bound( overlapMap.begin(), overlapMap.end(), hashId,
62  [](const std::pair<IdentifierHash, bool> &lhs, IdentifierHash rhs) -> bool { return lhs.first < rhs; } );
63  if (search == overlapMap.end() || search->first != hashId) {
64  // Copy the background collection
65  std::unique_ptr<Collection> bkgCollection = nullptr;
66  if constexpr (usePool) {
67  bkgCollection = Overlay::copyCollection(hashId, ptr, *dataItems);
68  } else {
69  bkgCollection = Overlay::copyCollection(hashId, ptr);
70  }
71  if (outputContainer->addCollection(bkgCollection.get(), hashId).isFailure()) {
72  ATH_MSG_ERROR("Adding background Collection with hashId " << hashId << " failed");
73  return StatusCode::FAILURE;
74  } else {
75  (void)bkgCollection.release();
76  }
77  } else {
78  // Flip the overlap flag
79  search->second = true;
80  }
81  }
82 
83  // Finally loop through the map and process the signal and overlay if
84  // necessary
85  for (const auto &[hashId, overlap] : overlapMap) {
86  // Copy the signal collection
87  std::unique_ptr<Collection> signalCollection = nullptr;
88  if constexpr (usePool) {
89  signalCollection = Overlay::copyCollection(
90  hashId, signalContainer->indexFindPtr(hashId), *dataItems);
91  } else {
92  signalCollection = Overlay::copyCollection(
93  hashId, signalContainer->indexFindPtr(hashId));
94  }
95 
96  if (overlap) { // Do overlay
97  // Create the output collection, only works for Inner Detector
98  auto outputCollection = std::make_unique<Collection>(hashId);
99  outputCollection->setIdentifier(signalCollection->identify());
100  if constexpr (usePool) {
101  // if we use pool the output is also to go to the pool
102  outputCollection->clear(SG::VIEW_ELEMENTS);
103  }
104  // Copy the background collection
105  // Merge collections
106  std::unique_ptr<Collection> bkgCollection = nullptr;
107  if constexpr (usePool) {
108  bkgCollection = Overlay::copyCollection(
109  hashId, bkgContainer->indexFindPtr(hashId), *dataItems);
110  Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(),
111  outputCollection.get(), this, *dataItems);
112  } else {
113  bkgCollection =
114  Overlay::copyCollection(hashId, bkgContainer->indexFindPtr(hashId));
115  Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(),
116  outputCollection.get(), this);
117  }
118  if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
119  ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
120  return StatusCode::FAILURE;
121  } else {
122  outputCollection.release();
123  }
124  } else { // Only write signal out
125  if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
126  ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
127  return StatusCode::FAILURE;
128  } else {
129  (void)signalCollection.release();
130  }
131  }
132  }
133  return StatusCode::SUCCESS;
134 }
135 
136 template <typename IDC_Container>
137 StatusCode IDC_OverlayBase::overlayContainer(const IDC_Container *bkgContainer,
138  const IDC_Container *signalContainer,
139  IDC_Container *outputContainer) const
140 {
141  return overlayContainerImpl<false, void>(
142  bkgContainer, signalContainer, outputContainer, nullptr);
143 }
144 
145 template <typename IDC_Container, typename Type>
146 StatusCode IDC_OverlayBase::overlayContainer(const IDC_Container *bkgContainer,
147  const IDC_Container *signalContainer,
148  IDC_Container *outputContainer,
149  DataPool<Type>& dataItems) const
150 {
151  return overlayContainerImpl<true>(bkgContainer,signalContainer,outputContainer,&dataItems);
152 }