ATLAS Offline Software
IDC_MuonOverlayBase.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 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 <bool isMultiHitCollection, class IDC_Container>
35 StatusCode IDC_MuonOverlayBase::overlayContainerImpl(const IDC_Container *bkgContainer,
36  const IDC_Container *signalContainer,
37  IDC_Container *outputContainer) const
38 {
39  typedef typename IDC_Container::base_value_type Collection;
40 
41  ATH_MSG_DEBUG("overlayContainer<>() begin");
42 
43  // There are some use cases where background is empty
44  if (!bkgContainer) {
45  // Only loop through the signal collections and copy them over
46  for (const auto &[hashId, ptr] : signalContainer->GetAllHashPtrPair()) {
47  // Copy the signal collection
48  std::unique_ptr<Collection> signalCollection = copyCollection(hashId, ptr);
49 
50  if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
51  ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
52  return StatusCode::FAILURE;
53  } else {
54  (void)signalCollection.release();
55  }
56  }
57 
58  return StatusCode::SUCCESS;
59  }
60 
61  // The MC signal container should typically be smaller than bkgContainer,
62  // because the latter contains all the noise, minimum bias and pile up.
63  // Thus we firstly iterate over signal hashes and store them in a map.
64  std::vector < std::pair<IdentifierHash, bool> > overlapMap;
65  overlapMap.reserve(signalContainer->numberOfCollections());
66  for (const auto &[hashId, ptr] : signalContainer->GetAllHashPtrPair()) {
67  overlapMap.emplace_back(hashId, false);
68  }
69 
70  // Now loop through the background hashes and copy unique ones over
71  for (const auto &[hashId, ptr] : bkgContainer->GetAllHashPtrPair()) {
72  auto search = std::lower_bound( overlapMap.begin(), overlapMap.end(), hashId,
73  [](const std::pair<IdentifierHash, bool> &lhs, IdentifierHash rhs) -> bool { return lhs.first < rhs; } );
74  if (search == overlapMap.end() || search->first != hashId) {
75  // Copy the background collection
76  std::unique_ptr<Collection> bkgCollection = copyCollection(hashId, bkgContainer->indexFindPtr(hashId));
77 
78  if (outputContainer->addCollection(bkgCollection.get(), hashId).isFailure()) {
79  ATH_MSG_ERROR("Adding background Collection with hashId " << hashId << " failed");
80  return StatusCode::FAILURE;
81  } else {
82  (void)bkgCollection.release();
83  }
84  } else {
85  // Flip the overlap flag
86  search->second = true;
87  }
88  }
89 
90  // Finally loop through the map and process the signal and overlay if
91  // necessary
92  for (const auto &[hashId, overlap] : overlapMap) {
93  // Copy the signal collection
94  std::unique_ptr<Collection> signalCollection = copyCollection(hashId, signalContainer->indexFindPtr(hashId));
95 
96  if (overlap) { // Do overlay
97  // Create the output collection
98  auto outputCollection = std::make_unique<Collection>(signalCollection->identify(), hashId);
99  // Copy the background collection
100  std::unique_ptr<Collection> bkgCollection = copyCollection(hashId, bkgContainer->indexFindPtr(hashId));
101 
102  // Merge collections
103  if constexpr(isMultiHitCollection) {
104  Overlay::mergeMultiHitCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get());
105  } else {
106  Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get(), this);
107  }
108 
109  if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
110  ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
111  return StatusCode::FAILURE;
112  } else {
113  outputCollection.release();
114  }
115  } else { // Only write signal out
116  if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
117  ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
118  return StatusCode::FAILURE;
119  } else {
120  (void)signalCollection.release();
121  }
122  }
123  }
124 
125  return StatusCode::SUCCESS;
126 }