ATLAS Offline Software
IDC_MuonOverlayBase.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 // Generic overlaying code for Muon Identifiable Containers.
6 // Tadej Novak
7 // Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
8 
9 #include <Identifier/Identifier.h>
10 
11 #include <IDC_OverlayBase/IDC_OverlayCommon.h>
12 #include <MuonOverlayBase/IDC_MultiHitOverlayCommon.h>
13 
14 
15 template <class Collection>
16 std::unique_ptr<Collection> IDC_MuonOverlayBase::copyCollection(const IdentifierHash &hashId,
17  const Collection *collection) const
18 {
19  typedef typename Collection::base_value_type Datum;
20 
21  auto outputCollection = std::make_unique<Collection>(collection->identify(), hashId);
22 
23  for (const Datum *existingDatum : *collection) {
24  // Owned by the collection
25  Datum *datumCopy = new Datum(*existingDatum);
26  outputCollection->push_back(datumCopy);
27  }
28 
29  return outputCollection;
30 }
31 
32 
33 
34 template <class IDC_Container>
35 StatusCode IDC_MuonOverlayBase::overlayContainerBase(const IDC_Container *bkgContainer,
36  const IDC_Container *signalContainer,
37  IDC_Container *outputContainer,
38  bool isMultiHitCollection) const
39 {
40  typedef typename IDC_Container::base_value_type Collection;
41 
42  ATH_MSG_DEBUG("overlayContainer<>() begin");
43 
44  // There are some use cases where background is empty
45  if (!bkgContainer) {
46  // Only loop through the signal collections and copy them over
47  for (const auto &[hashId, ptr] : signalContainer->GetAllHashPtrPair()) {
48  // Copy the signal collection
49  std::unique_ptr<Collection> signalCollection = copyCollection(hashId, ptr);
50 
51  if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
52  ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
53  return StatusCode::FAILURE;
54  } else {
55  (void)signalCollection.release();
56  }
57  }
58 
59  return StatusCode::SUCCESS;
60  }
61 
62  // The MC signal container should typically be smaller than bkgContainer,
63  // because the latter contains all the noise, minimum bias and pile up.
64  // Thus we firstly iterate over signal hashes and store them in a map.
65  std::vector < std::pair<IdentifierHash, bool> > overlapMap;
66  overlapMap.reserve(signalContainer->numberOfCollections());
67  for (const auto &[hashId, ptr] : signalContainer->GetAllHashPtrPair()) {
68  overlapMap.emplace_back(hashId, false);
69  }
70 
71  // Now loop through the background hashes and copy unique ones over
72  for (const auto &[hashId, ptr] : bkgContainer->GetAllHashPtrPair()) {
73  auto search = std::lower_bound( overlapMap.begin(), overlapMap.end(), hashId,
74  [](const std::pair<IdentifierHash, bool> &lhs, IdentifierHash rhs) -> bool { return lhs.first < rhs; } );
75  if (search == overlapMap.end() || search->first != hashId) {
76  // Copy the background collection
77  std::unique_ptr<Collection> bkgCollection = copyCollection(hashId, bkgContainer->indexFindPtr(hashId));
78 
79  if (outputContainer->addCollection(bkgCollection.get(), hashId).isFailure()) {
80  ATH_MSG_ERROR("Adding background Collection with hashId " << hashId << " failed");
81  return StatusCode::FAILURE;
82  } else {
83  (void)bkgCollection.release();
84  }
85  } else {
86  // Flip the overlap flag
87  search->second = true;
88  }
89  }
90 
91  // Finally loop through the map and process the signal and overlay if
92  // necessary
93  for (const auto &[hashId, overlap] : overlapMap) {
94  // Copy the signal collection
95  std::unique_ptr<Collection> signalCollection = copyCollection(hashId, signalContainer->indexFindPtr(hashId));
96 
97  if (overlap) { // Do overlay
98  // Create the output collection
99  auto outputCollection = std::make_unique<Collection>(signalCollection->identify(), hashId);
100  // Copy the background collection
101  std::unique_ptr<Collection> bkgCollection = copyCollection(hashId, bkgContainer->indexFindPtr(hashId));
102 
103  // Merge collections
104  if (isMultiHitCollection) {
105  Overlay::mergeMultiHitCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get());
106  } else {
107  Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get(), this);
108  }
109 
110  if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
111  ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
112  return StatusCode::FAILURE;
113  } else {
114  outputCollection.release();
115  }
116  } else { // Only write signal out
117  if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
118  ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
119  return StatusCode::FAILURE;
120  } else {
121  (void)signalCollection.release();
122  }
123  }
124  }
125 
126  return StatusCode::SUCCESS;
127 }