ATLAS Offline Software
BCMOverlay.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #include "StoreGate/ReadHandle.h"
9 
10 
11 BCMOverlay::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
22  ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_bkgInputKey);
24  ATH_MSG_VERBOSE("Initialized ReadHandleKey: " << m_signalInputKey);
26  ATH_MSG_VERBOSE("Initialized WriteHandleKey: " << m_outputKey);
27 
28  return StatusCode::SUCCESS;
29 }
30 
31 StatusCode 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
58  SG::WriteHandle<BCM_RDO_Container> outputContainer(m_outputKey, ctx);
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 
72 StatusCode 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 
156 std::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 (size_t i = 0; i < merged_pulses.size()-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 
229 void 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 
279 std::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 
288 bool 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 }
BCM_RawData::getPulse2Width
int getPulse2Width() const
Definition: BCM_RawData.h:84
BCM_Pulse::p
unsigned int p
Definition: BCMOverlay.h:19
BCMOverlay::m_storeAllBCID
Gaudi::Property< bool > m_storeAllBCID
Definition: BCMOverlay.h:50
BCM_Pulse::w
unsigned int w
Definition: BCMOverlay.h:21
SG::ReadHandle::cptr
const_pointer_type cptr()
Dereference the pointer.
SG::ReadHandle
Definition: StoreGate/StoreGate/ReadHandle.h:70
SG::VarHandleBase::name
const std::string & name() const
Return the StoreGate ID for the referenced object.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleBase.cxx:75
BCMOverlay::mergeChannel
std::unique_ptr< BCM_RawData > mergeChannel(const BCM_RawData *bkgRDO, const BCM_RawData *signalRDO) const
Definition: BCMOverlay.cxx:156
skel.it
it
Definition: skel.GENtoEVGEN.py:396
BCMOverlay::initialize
virtual StatusCode initialize() override final
Definition: BCMOverlay.cxx:16
BCMOverlay::timeOrder
static std::pair< BCM_Pulse *, BCM_Pulse * > timeOrder(BCM_Pulse *pulse1, BCM_Pulse *pulse2)
Definition: BCMOverlay.cxx:279
BCM_RawData::getLVL1ID
int getLVL1ID() const
Definition: BCM_RawData.h:87
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
SG::VarHandleKey::empty
bool empty() const
Test if the key is blank.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:150
BCM_RawData::getChannel
int getChannel() const
Definition: BCM_RawData.h:80
BCM_Pulse
Definition: BCMOverlay.h:18
AthReentrantAlgorithm
An algorithm that can be simultaneously executed in multiple threads.
Definition: AthReentrantAlgorithm.h:83
BCMOverlay::m_bkgInputKey
SG::ReadHandleKey< BCM_RDO_Container > m_bkgInputKey
Definition: BCMOverlay.h:52
WriteHandle.h
Handle class for recording to StoreGate.
BCM_RDO_Collection::setChannel
virtual void setChannel(unsigned int chanId)
Definition: BCM_RDO_Collection.h:34
BCM_RawData::getPulse1Position
int getPulse1Position() const
Definition: BCM_RawData.h:81
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
lumiFormat.i
int i
Definition: lumiFormat.py:85
BCM_RDO_Container
Definition: BCM_RDO_Container.h:27
BCM_RawData::getWord2
int getWord2() const
Definition: BCM_RawData.h:79
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
SG::WriteHandle::ptr
pointer_type ptr()
Dereference the pointer.
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
BCM_RawData
Definition: BCM_RawData.h:36
BCMOverlay::m_dataOverlay
Gaudi::Property< bool > m_dataOverlay
Definition: BCMOverlay.h:49
BCMOverlay::overlayPulses
static void overlayPulses(std::vector< std::unique_ptr< BCM_Pulse >> &merged_pulses)
Definition: BCMOverlay.cxx:229
SG::VarHandleBase::store
std::string store() const
Return the name of the store holding the object we are proxying.
Definition: StoreGate/src/VarHandleBase.cxx:376
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
SG::VarHandleKey::initialize
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Definition: AthToolSupport/AsgDataHandles/Root/VarHandleKey.cxx:103
BCMOverlay.h
SG::ReadHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
BCMOverlay::overlayContainer
StatusCode overlayContainer(const EventContext &ctx, const BCM_RDO_Container *bkgContainer, const BCM_RDO_Container *signalContainer, BCM_RDO_Container *outputContainer) const
Definition: BCMOverlay.cxx:72
SG::WriteHandle::isValid
virtual bool isValid() override final
Can the handle be successfully dereferenced?
BCMOverlay::BCMOverlay
BCMOverlay(const std::string &name, ISvcLocator *pSvcLocator)
Definition: BCMOverlay.cxx:11
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
BCMOverlay::m_outputKey
SG::WriteHandleKey< BCM_RDO_Container > m_outputKey
Definition: BCMOverlay.h:54
SG::WriteHandle
Definition: StoreGate/StoreGate/WriteHandle.h:76
a
TList * a
Definition: liststreamerinfos.cxx:10
BCM_RawData::getPulse2Position
int getPulse2Position() const
Definition: BCM_RawData.h:83
SG::WriteHandle::record
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
BCM_RawData::getPulse1Width
int getPulse1Width() const
Definition: BCM_RawData.h:82
BCM_RawData::getWord1
int getWord1() const
Definition: BCM_RawData.h:78
BCM_RawData::getLVL1A
int getLVL1A() const
Definition: BCM_RawData.h:85
BCMOverlay::m_signalInputKey
SG::ReadHandleKey< BCM_RDO_Container > m_signalInputKey
Definition: BCMOverlay.h:53
ReadHandle.h
Handle class for reading from StoreGate.
BCM_RDO_Collection
Definition: BCM_RDO_Collection.h:27
BCMOverlay::compare
static bool compare(const std::unique_ptr< BCM_Pulse > &a, const std::unique_ptr< BCM_Pulse > &b)
Definition: BCMOverlay.cxx:288
BCMOverlay::execute
virtual StatusCode execute(const EventContext &ctx) const override final
Definition: BCMOverlay.cxx:31
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
BCM_RawData::getBCID
int getBCID() const
Definition: BCM_RawData.h:86