ATLAS Offline Software
Loading...
Searching...
No Matches
BCMOverlay.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
9
10
11BCMOverlay::BCMOverlay(const std::string &name, ISvcLocator *pSvcLocator)
12 : AthReentrantAlgorithm(name, pSvcLocator)
13{
14}
15
17{
18 ATH_MSG_DEBUG("Initializing...");
19
20 // Check and initialize keys
21 ATH_CHECK( m_bkgInputKey.initialize(!m_bkgInputKey.empty()) );
22 ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_bkgInputKey);
23 ATH_CHECK( m_signalInputKey.initialize() );
24 ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_signalInputKey);
25 ATH_CHECK( m_outputKey.initialize() );
26 ATH_MSG_VERBOSE("Initialized WriteHandleKey: " << m_outputKey);
27
28 return StatusCode::SUCCESS;
29}
30
31StatusCode BCMOverlay::execute(const EventContext& ctx) const
32{
33 ATH_MSG_DEBUG("execute() begin");
34
35 // Reading the input RDOs
36 ATH_MSG_VERBOSE("Retrieving input RDO containers");
37
38 const BCM_RDO_Container *bkgContainerPtr = nullptr;
39 if (!m_bkgInputKey.empty()) {
41 if (!bkgContainer.isValid()) {
42 ATH_MSG_ERROR("Could not get background BCM RDO container " << bkgContainer.name() << " from store " << bkgContainer.store());
43 return StatusCode::FAILURE;
44 }
45 bkgContainerPtr = bkgContainer.cptr();
46
47 ATH_MSG_DEBUG("Found background BCM RDO container " << bkgContainer.name() << " in store " << bkgContainer.store());
48 }
49
51 if (!signalContainer.isValid()) {
52 ATH_MSG_ERROR("Could not get signal BCM RDO container " << signalContainer.name() << " from store " << signalContainer.store());
53 return StatusCode::FAILURE;
54 }
55 ATH_MSG_DEBUG("Found signal BCM RDO container " << signalContainer.name() << " in store " << signalContainer.store());
56
57 // Creating output RDO container
59 ATH_CHECK(outputContainer.record(std::make_unique<BCM_RDO_Container>()));
60 if (!outputContainer.isValid()) {
61 ATH_MSG_ERROR("Could not record output BCM RDO container " << outputContainer.name() << " to store " << outputContainer.store());
62 return StatusCode::FAILURE;
63 }
64 ATH_MSG_DEBUG("Recorded output BCM RDO container " << outputContainer.name() << " in store " << outputContainer.store());
65
66 ATH_CHECK(overlayContainer(ctx, bkgContainerPtr, signalContainer.cptr(), outputContainer.ptr()));
67
68 ATH_MSG_DEBUG("execute() end");
69 return StatusCode::SUCCESS;
70}
71
72StatusCode BCMOverlay::overlayContainer(const EventContext& ctx,
73 const BCM_RDO_Container *bkgContainer,
74 const BCM_RDO_Container *signalContainer,
75 BCM_RDO_Container *outputContainer) const
76{
77
78 if (!bkgContainer) {
79 for (const BCM_RDO_Collection *coll : *signalContainer) {
80
81 std::unique_ptr<BCM_RDO_Collection> outputColl = std::make_unique<BCM_RDO_Collection>();
82
83 for (const BCM_RawData *rdo : *coll) {
84 outputColl->push_back(new BCM_RawData(rdo->getWord1(), rdo->getWord2()));
85 }
86 outputContainer->push_back(outputColl.release());
87 }
88
89 return StatusCode::SUCCESS;
90 }
91
92 std::unordered_map<unsigned int, const BCM_RDO_Collection *> bkgChannelMap;
93 for (const BCM_RDO_Collection *bkgColl : *bkgContainer) {
94 bkgChannelMap.emplace(bkgColl->getChannel(), bkgColl);
95 }
96
97 for (const BCM_RDO_Collection *sigColl : *signalContainer) {
98
99 auto it = bkgChannelMap.find(sigColl->getChannel());
100 if (it == bkgChannelMap.end()) {
101 ATH_MSG_ERROR ("No BCM background collection with channel " << sigColl->getChannel());
102 return StatusCode::FAILURE;
103 }
104
105 const BCM_RDO_Collection *bkgColl = it->second;
106 bkgChannelMap.erase(it);
107 std::unique_ptr<BCM_RDO_Collection> outputColl = std::make_unique<BCM_RDO_Collection>();
108 outputColl->setChannel(sigColl->getChannel());
109
110 constexpr size_t mcSize{1}; // MC always has exactly one RDO
111 if (m_dataOverlay.value()) {
112 // Data has RDOs from more BCIDs, check MC size
113 if (sigColl->size() != mcSize) {
114 ATH_MSG_ERROR ("BCM signal collection size mismatch");
115 return StatusCode::FAILURE;
116 }
117 } else {
118 // In case of MC+MC overlay collection sizes are the same
119 size_t collectionSize = bkgColl->size();
120 if (collectionSize != sigColl->size() && collectionSize != mcSize) {
121 ATH_MSG_ERROR ("BCM signal and background collection size mismatch");
122 return StatusCode::FAILURE;
123 }
124 }
125
126 int currentBCID = ctx.eventID().bunch_crossing_id();
127 for (const BCM_RawData *bkgRDO : *bkgColl) {
128 if (m_dataOverlay.value() && bkgRDO->getBCID() != currentBCID) {
129 if (m_storeAllBCID.value()) {
130 outputColl->push_back(new BCM_RawData(bkgRDO->getWord1(), bkgRDO->getWord2()));
131 }
132 continue;
133 }
134
135 const BCM_RawData *sigRDO = sigColl->front();
136 if (bkgRDO->getChannel() == sigRDO->getChannel()) {
137 std::unique_ptr<BCM_RawData> mergedRDO = mergeChannel(bkgRDO, sigRDO);
138 if (mergedRDO != nullptr) {
139 outputColl->push_back(mergedRDO.release());
140 } else {
141 ATH_MSG_ERROR ("BCM channel merging failed");
142 return StatusCode::FAILURE;
143 }
144 } else {
145 ATH_MSG_ERROR ("BCM signal and background channel mismatch");
146 return StatusCode::FAILURE;
147 }
148
149 }
150 outputContainer->push_back(outputColl.release());
151 }
152
153 return StatusCode::SUCCESS;
154}
155
156std::unique_ptr<BCM_RawData> BCMOverlay::mergeChannel(const BCM_RawData *bkgRDO,
157 const BCM_RawData *signalRDO) const
158{
159
160 if (bkgRDO->getPulse1Width()==0) {
161 return std::make_unique<BCM_RawData>(signalRDO->getWord1(), signalRDO->getWord2());
162 } else if (signalRDO->getPulse1Width()==0) {
163 return std::make_unique<BCM_RawData>(bkgRDO->getWord1(), bkgRDO->getWord2());
164 }
165
166 unsigned int bkg_p1 = bkgRDO->getPulse1Position();
167 unsigned int bkg_w1 = bkgRDO->getPulse1Width();
168 unsigned int bkg_p2 = bkgRDO->getPulse2Position();
169 unsigned int bkg_w2 = bkgRDO->getPulse2Width();
170 unsigned int sig_p1 = signalRDO->getPulse1Position();
171 unsigned int sig_w1 = signalRDO->getPulse1Width();
172 unsigned int sig_p2 = signalRDO->getPulse2Position();
173 unsigned int sig_w2 = signalRDO->getPulse2Width();
174
175 std::vector<std::unique_ptr<BCM_Pulse>> merged_pulses;
176
177 if (bkg_w1 > 0) merged_pulses.push_back(std::make_unique<BCM_Pulse>(bkg_p1,bkg_w1));
178 if (bkg_w2 > 0) merged_pulses.push_back(std::make_unique<BCM_Pulse>(bkg_p2,bkg_w2));
179 if (sig_w1 > 0) merged_pulses.push_back(std::make_unique<BCM_Pulse>(sig_p1,sig_w1));
180 if (sig_w2 > 0) merged_pulses.push_back(std::make_unique<BCM_Pulse>(sig_p2,sig_w2));
181
182 overlayPulses(merged_pulses);
183 std::sort(merged_pulses.begin(), merged_pulses.end(), compare);
184
185 // Check whether some of the pulses merged
186 for (int i{}; i < std::ssize(merged_pulses)-1; i++) {
187
188 BCM_Pulse *early = merged_pulses.at(i).get();
189 BCM_Pulse *later = merged_pulses.at(i+1).get();
190
191 if ( (early->p + early->w - 1) >= later->p ) {
192 early->w = later->p - early->p + later->w; // Enlarge early pulse
193 merged_pulses.erase(merged_pulses.begin()+i+1,
194 merged_pulses.begin()+i+2); // Omit later pulse
195 i--;
196 }
197 }
198
199 unsigned int merged_p1;
200 unsigned int merged_w1;
201 unsigned int merged_p2;
202 unsigned int merged_w2;
203
204 if (!merged_pulses.empty()) {
205 merged_p1 = merged_pulses.at(0)->p;
206 merged_w1 = merged_pulses.at(0)->w;
207 } else {
208 merged_p1 = 0;
209 merged_w1 = 0;
210 }
211
212 if (merged_pulses.size() > 1) {
213 merged_p2 = merged_pulses.at(1)->p;
214 merged_w2 = merged_pulses.at(1)->w;
215 } else {
216 merged_p2 = 0;
217 merged_w2 = 0;
218 }
219
220 // Record two earliest pulses into the output RDO
221 return std::make_unique<BCM_RawData>(bkgRDO->getChannel(),
222 merged_p1, merged_w1,
223 merged_p2, merged_w2,
224 bkgRDO->getLVL1A(),
225 bkgRDO->getBCID(),
226 bkgRDO->getLVL1ID());
227}
228
229void BCMOverlay::overlayPulses(std::vector<std::unique_ptr<BCM_Pulse>>& merged_pulses)
230{
231
232 constexpr double fullPulseWidth{15.}; // Analogue pulse width
233 // before application of
234 // time over threshold
235 constexpr double slopeUpFraction{1./3.}; // Pulse rise time,
236 // expressed in the fraction
237 // of full pulse width
238 constexpr double slopeDownFraction{2./3.}; // Pulse fall time,
239 // expressed in the fraction
240 // of full pulse width
241
242 for (size_t i = 0; i < merged_pulses.size(); i++) {
243 BCM_Pulse* pulse_1 = merged_pulses.at(i).get();
244
245 for (size_t j = 0; j < i; j++) {
246 BCM_Pulse* pulse_2 = merged_pulses.at(j).get();
247 auto[early,later] = timeOrder(pulse_1, pulse_2);
248
249 int below_thr_later = fullPulseWidth - later->w;
250 int below_thr_early = fullPulseWidth - early->w;
251 double slope_up = 1./slopeUpFraction;
252 double slope_down = 1./slopeDownFraction;
253 if (below_thr_later != 0) slope_up /= below_thr_later;
254 if (below_thr_early != 0) slope_down /= below_thr_early;
255
256 int bin_min = early->p + early->w;
257 int bin_max = later->p;
258
259 // Widen the pulses, if they lie close enough to each other
260 for (int bin_iter=bin_min; bin_iter < bin_max; bin_iter++) {
261 if (slope_up*(bin_iter - bin_max) - slope_down*(bin_iter - bin_min) > -1) {
262 early->w++;
263 }
264 else break;
265 }
266 for (int bin_iter=bin_max-1; bin_iter >= bin_min; bin_iter--) {
267 if (slope_up*(bin_iter - bin_max) - slope_down*(bin_iter - bin_min) > -1) {
268 later->p = bin_iter;
269 later->w++;
270 }
271 else break;
272 }
273
274 }
275 }
276
277}
278
279std::pair<BCM_Pulse*, BCM_Pulse*> BCMOverlay::timeOrder(BCM_Pulse* pulse1,
280 BCM_Pulse* pulse2)
281{
282
283 if (pulse2->p > pulse1->p) return std::pair(pulse1,pulse2);
284 else return std::pair(pulse2,pulse1);
285
286}
287
288bool BCMOverlay::compare(const std::unique_ptr<BCM_Pulse>& a,
289 const std::unique_ptr<BCM_Pulse>& b)
290{
291
292 return a->p < b->p;
293
294}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_DEBUG(x)
static Double_t a
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
An algorithm that can be simultaneously executed in multiple threads.
StatusCode overlayContainer(const EventContext &ctx, const BCM_RDO_Container *bkgContainer, const BCM_RDO_Container *signalContainer, BCM_RDO_Container *outputContainer) const
static void overlayPulses(std::vector< std::unique_ptr< BCM_Pulse > > &merged_pulses)
std::unique_ptr< BCM_RawData > mergeChannel(const BCM_RawData *bkgRDO, const BCM_RawData *signalRDO) const
virtual StatusCode initialize() override final
SG::ReadHandleKey< BCM_RDO_Container > m_bkgInputKey
Definition BCMOverlay.h:52
virtual StatusCode execute(const EventContext &ctx) const override final
static bool compare(const std::unique_ptr< BCM_Pulse > &a, const std::unique_ptr< BCM_Pulse > &b)
SG::WriteHandleKey< BCM_RDO_Container > m_outputKey
Definition BCMOverlay.h:54
SG::ReadHandleKey< BCM_RDO_Container > m_signalInputKey
Definition BCMOverlay.h:53
Gaudi::Property< bool > m_dataOverlay
Definition BCMOverlay.h:49
static std::pair< BCM_Pulse *, BCM_Pulse * > timeOrder(BCM_Pulse *pulse1, BCM_Pulse *pulse2)
BCMOverlay(const std::string &name, ISvcLocator *pSvcLocator)
Gaudi::Property< bool > m_storeAllBCID
Definition BCMOverlay.h:50
int getPulse1Width() const
Definition BCM_RawData.h:82
int getWord1() const
Definition BCM_RawData.h:78
int getLVL1ID() const
Definition BCM_RawData.h:87
int getWord2() const
Definition BCM_RawData.h:79
int getPulse2Position() const
Definition BCM_RawData.h:83
int getLVL1A() const
Definition BCM_RawData.h:85
int getPulse2Width() const
Definition BCM_RawData.h:84
int getChannel() const
Definition BCM_RawData.h:80
int getPulse1Position() const
Definition BCM_RawData.h:81
int getBCID() const
Definition BCM_RawData.h:86
value_type push_back(value_type pElem)
Add an element to the end of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
std::string store() const
Return the name of the store holding the object we are proxying.
const std::string & name() const
Return the StoreGate ID for the referenced object.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
pointer_type ptr()
Dereference the pointer.
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
unsigned int w
Definition BCMOverlay.h:21
unsigned int p
Definition BCMOverlay.h:20