2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5 // Generic overlaying code for Muon Identifiable Containers.
7 // Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
9 #include <Identifier/Identifier.h>
11 #include <IDC_OverlayBase/IDC_OverlayCommon.h>
12 #include <MuonOverlayBase/IDC_MultiHitOverlayCommon.h>
15 template <class Collection>
16 std::unique_ptr<Collection> IDC_MuonOverlayBase::copyCollection(const IdentifierHash &hashId,
17 const Collection *collection) const
19 typedef typename Collection::base_value_type Datum;
21 auto outputCollection = std::make_unique<Collection>(collection->identify(), hashId);
23 for (const Datum *existingDatum : *collection) {
24 // Owned by the collection
25 Datum *datumCopy = new Datum(*existingDatum);
26 outputCollection->push_back(datumCopy);
29 return outputCollection;
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
39 typedef typename IDC_Container::base_value_type Collection;
41 ATH_MSG_DEBUG("overlayContainer<>() begin");
43 // There are some use cases where background is empty
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);
50 if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
51 ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
52 return StatusCode::FAILURE;
54 (void)signalCollection.release();
58 return StatusCode::SUCCESS;
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);
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));
78 if (outputContainer->addCollection(bkgCollection.get(), hashId).isFailure()) {
79 ATH_MSG_ERROR("Adding background Collection with hashId " << hashId << " failed");
80 return StatusCode::FAILURE;
82 (void)bkgCollection.release();
85 // Flip the overlap flag
86 search->second = true;
90 // Finally loop through the map and process the signal and overlay if
92 for (const auto &[hashId, overlap] : overlapMap) {
93 // Copy the signal collection
94 std::unique_ptr<Collection> signalCollection = copyCollection(hashId, signalContainer->indexFindPtr(hashId));
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));
103 if constexpr(isMultiHitCollection) {
104 Overlay::mergeMultiHitCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get());
106 Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get(), this);
109 if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
110 ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
111 return StatusCode::FAILURE;
113 outputCollection.release();
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;
120 (void)signalCollection.release();
125 return StatusCode::SUCCESS;