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>
15template <class Collection>
16std::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;
34template <bool isMultiHitCollection, class IDC_Container>
35StatusCode 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 //coverity[RESOURCE_LEAK]
55 (void)signalCollection.release();
59 return StatusCode::SUCCESS;
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);
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));
79 if (outputContainer->addCollection(bkgCollection.get(), hashId).isFailure()) {
80 ATH_MSG_ERROR("Adding background Collection with hashId " << hashId << " failed");
81 return StatusCode::FAILURE;
83 //coverity[RESOURCE_LEAK]
84 (void)bkgCollection.release();
87 // Flip the overlap flag
88 search->second = true;
92 // Finally loop through the map and process the signal and overlay if
94 for (const auto &[hashId, overlap] : overlapMap) {
95 // Copy the signal collection
96 std::unique_ptr<Collection> signalCollection = copyCollection(hashId, signalContainer->indexFindPtr(hashId));
98 if (overlap) { // Do overlay
99 // Create the output collection
100 auto outputCollection = std::make_unique<Collection>(signalCollection->identify(), hashId);
101 // Copy the background collection
102 std::unique_ptr<Collection> bkgCollection = copyCollection(hashId, bkgContainer->indexFindPtr(hashId));
105 if constexpr(isMultiHitCollection) {
106 Overlay::mergeMultiHitCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get());
108 Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(), outputCollection.get(), this);
111 if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
112 ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
113 return StatusCode::FAILURE;
115 //coverity[RESOURCE_LEAK]
116 std::ignore = outputCollection.release();
118 } else { // Only write signal out
119 if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
120 ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
121 return StatusCode::FAILURE;
123 //coverity[RESOURCE_LEAK]
124 (void)signalCollection.release();
129 return StatusCode::SUCCESS;