2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
6/// @author Christos Anastopoulos DataPool strategy
7/// @author Andrei Gaponenko <agaponenko@lbl.gov>, 2006-2009
9#include <Identifier/Identifier.h>
10#include <Identifier/IdentifierHash.h>
12#include "AthContainers/OwnershipPolicy.h"
14#include "IDC_OverlayCommon.h"
16template <bool sortCollections, bool usePool, typename Type, typename IDC_Container>
17StatusCode IDC_OverlayBase::overlayContainerImpl(
18 const IDC_Container *bkgContainer,
19 const IDC_Container *signalContainer,
20 IDC_Container *outputContainer,
21 DataPool<Type> *dataItems) const
24 ATH_MSG_DEBUG("overlayContainer<>() begin");
25 typedef typename IDC_Container::base_value_type Collection;
27 // There are some use cases where background is empty
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);
36 signalCollection = Overlay::copyCollection(hashId, ptr);
38 if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
39 ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
40 return StatusCode::FAILURE;
42 //coverity[RESOURCE_LEAK]
43 (void)signalCollection.release();
47 return StatusCode::SUCCESS;
51 // The MC signal container should typically be smaller than bkgContainer,
52 // because the latter contains all the noise, minimum bias and pile up.
53 // Thus we firstly iterate over signal hashes and store them in a map.
54 std::vector < std::pair<IdentifierHash, bool> > overlapMap;
55 overlapMap.reserve(signalContainer->numberOfCollections());
56 for (const auto &[hashId, ptr] : signalContainer->GetAllHashPtrPair()) {
57 overlapMap.emplace_back(hashId, false);
60 // Now loop through the background hashes and copy unique ones over
61 for (const auto &[hashId, ptr] : bkgContainer->GetAllHashPtrPair()) {
62 auto search = std::lower_bound( overlapMap.begin(), overlapMap.end(), hashId,
63 [](const std::pair<IdentifierHash, bool> &lhs, IdentifierHash rhs) -> bool { return lhs.first < rhs; } );
64 if (search == overlapMap.end() || search->first != hashId) {
65 // Copy the background collection
66 std::unique_ptr<Collection> bkgCollection = nullptr;
67 if constexpr (usePool) {
68 bkgCollection = Overlay::copyCollection(hashId, ptr, *dataItems);
70 bkgCollection = Overlay::copyCollection(hashId, ptr);
72 if (outputContainer->addCollection(bkgCollection.get(), hashId).isFailure()) {
73 ATH_MSG_ERROR("Adding background Collection with hashId " << hashId << " failed");
74 return StatusCode::FAILURE;
76 //coverity[RESOURCE_LEAK]
77 (void)bkgCollection.release();
80 // Flip the overlap flag
81 search->second = true;
85 // Finally loop through the map and process the signal and overlay if
87 for (const auto &[hashId, overlap] : overlapMap) {
88 // Copy the signal collection
89 std::unique_ptr<Collection> signalCollection = nullptr;
90 if constexpr (usePool) {
91 signalCollection = Overlay::copyCollection(
92 hashId, signalContainer->indexFindPtr(hashId), *dataItems);
94 signalCollection = Overlay::copyCollection(
95 hashId, signalContainer->indexFindPtr(hashId));
98 if (overlap) { // Do overlay
99 // Create the output collection, only works for Inner Detector
100 auto outputCollection = std::make_unique<Collection>(hashId);
101 outputCollection->setIdentifier(signalCollection->identify());
102 if constexpr (usePool) {
103 // if we use pool the output is also to go to the pool
104 outputCollection->clear(SG::VIEW_ELEMENTS);
106 // Copy the background collection
108 std::unique_ptr<Collection> bkgCollection = nullptr;
109 if constexpr (usePool) {
110 bkgCollection = Overlay::copyCollection(
111 hashId, bkgContainer->indexFindPtr(hashId), *dataItems);
112 if constexpr (sortCollections) {
113 Overlay::mergeSortedCollections(bkgCollection.get(), signalCollection.get(),
114 outputCollection.get(), this, *dataItems);
116 Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(),
117 outputCollection.get(), this, *dataItems);
121 Overlay::copyCollection(hashId, bkgContainer->indexFindPtr(hashId));
122 Overlay::mergeCollections(bkgCollection.get(), signalCollection.get(),
123 outputCollection.get(), this);
125 if (outputContainer->addCollection(outputCollection.get(), hashId).isFailure()) {
126 ATH_MSG_ERROR("Adding overlaid Collection with hashId " << hashId << " failed");
127 return StatusCode::FAILURE;
129 //coverity[RESOURCE_LEAK]
130 std::ignore = outputCollection.release();
132 } else { // Only write signal out
133 if (outputContainer->addCollection(signalCollection.get(), hashId).isFailure()) {
134 ATH_MSG_ERROR("Adding signal Collection with hashId " << hashId << " failed");
135 return StatusCode::FAILURE;
137 //coverity[RESOURCE_LEAK]
138 (void)signalCollection.release();
142 return StatusCode::SUCCESS;
145template <typename IDC_Container>
146StatusCode IDC_OverlayBase::overlayContainer(const IDC_Container *bkgContainer,
147 const IDC_Container *signalContainer,
148 IDC_Container *outputContainer) const
150 return overlayContainerImpl<false, false, void>(
151 bkgContainer, signalContainer, outputContainer, nullptr);
154template <typename IDC_Container, typename Type>
155StatusCode IDC_OverlayBase::overlayContainer(const IDC_Container *bkgContainer,
156 const IDC_Container *signalContainer,
157 IDC_Container *outputContainer,
158 DataPool<Type>& dataItems) const
160 return overlayContainerImpl<false, true>(
161 bkgContainer, signalContainer, outputContainer, &dataItems);
164template <typename IDC_Container, typename Type>
165StatusCode IDC_OverlayBase::overlayContainerWithSorting(const IDC_Container *bkgContainer,
166 const IDC_Container *signalContainer,
167 IDC_Container *outputContainer,
168 DataPool<Type>& dataItems) const
170 return overlayContainerImpl<true, true>(
171 bkgContainer, signalContainer, outputContainer, &dataItems);