ATLAS Offline Software
Loading...
Searching...
No Matches
TileHitVecToCntTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5//************************************************************
6// FileName : TileHitVecToCntTool.cxx
7// Author : Vishnu Zutshi
8// Created : Dec. 2009
9//************************************************************
10
11// Tile includes
18
19// Calo includes
22
23// Athena includes
29// For the Athena-based random numbers.
32
33#include "CLHEP/Random/Randomize.h"
34#include "CLHEP/Random/RandomEngine.h"
36
37#include <algorithm>
38#include <functional>
39#include <memory>
40
41using CLHEP::RandFlat;
42using CLHEP::RandGaussQ; // FIXME CLHEP::RandGaussZiggurat is faster and more accurate.
43using CLHEP::RandPoissonT;
44using CLHEP::RandGeneral;
45
47 const std::string& name,
48 const IInterface* parent)
49 : PileUpToolBase(type,name,parent)
50{
51}
52
54
55 ATH_MSG_DEBUG("TileHitVecToCntTool initialization started");
56
57 ATH_CHECK(m_rndmSvc.retrieve());
58
59 // retrieve TileID helper from det store
60 ATH_CHECK(detStore()->retrieve(m_tileID));
61
62 ATH_CHECK(detStore()->retrieve(m_tileTBID));
63
64 ATH_CHECK(detStore()->retrieve(m_tileHWID));
65
66 ATH_CHECK( m_samplingFractionKey.initialize() );
67
68 ATH_CHECK(m_cablingSvc.retrieve());
69 m_cabling = m_cablingSvc->cablingService();
70
71 m_run2 = m_cabling->isRun2Cabling();
72 m_run2plus = m_cabling->isRun2PlusCabling();
73
75 ATH_MSG_INFO("No photostatistics effect will be simulated");
76 }
77
78 if (m_rndmEvtOverlay) {
79 m_pileUp = false;
80 ATH_MSG_INFO("Zero-luminosity pile-up selected");
81 ATH_MSG_INFO("Taking hits from original event only");
82 }
83
85 ATH_MSG_INFO("take events from PileUp service");
86
88 ATH_CHECK(m_mergeSvc.retrieve());
89 }
90
91 if (m_useTriggerTime) {
92 ATH_MSG_INFO(" In case of pileup, the trigger time subtraction is done in PileUpSvc");
93 ATH_MSG_INFO(" => TileHitVecToCnt will not apply Trigger Time ");
94 m_useTriggerTime = false;
95 }
96 m_timeFlag = 0;
97
98 if (m_pileUp) {
99 m_mbtsOffset = m_tileID->pmt_hash_max();
100 }
101
102 } else {
103
104 ATH_MSG_INFO("no pile up");
105
106 if (m_useTriggerTime) {
107
108 m_timeFlag = 2;
109
110 if (!m_triggerTimeKey.empty()) {
111 ATH_MSG_INFO( "Trigger time is taken from external ojbect '" << m_triggerTimeKey.key()
112 << "'; therefore set HitTimeFlag to 2");
113 ATH_CHECK(m_triggerTimeKey.initialize());
114 }
115 }
116
117 switch (m_timeFlag) {
118 case 2:
119 if (m_triggerTimeKey.empty()) {
120 if (m_triggerTime > 0.0) {
121 m_useTriggerTime = true;
122 ATH_MSG_INFO("Fixed trigger time of " << m_triggerTime << " ns will be used");
123 } else if (m_triggerTime < 0.0) {
124 m_useTriggerTime = false;
125 ATH_MSG_INFO( "Minimal hit time will be used as trigger time"
126 << " with random additional shift between 0 and " << -m_triggerTime << " ns");
127 } else {
128 m_useTriggerTime = false;
129 ATH_MSG_INFO("Average time will be calculated in every event");
130 }
131 }
132 break;
133 case 1:
134 ATH_MSG_INFO("Time of all hits will be reset to zero");
135 break;
136 default:
137 ATH_MSG_INFO("Time of all hits will be preserved during copy");
138 m_timeFlag = 0;
139 break;
140 }
141 }
142
143 if (m_run2plus) {
144 m_fragHashFunc.initialize(m_tileHWID);
145
146 m_E1merged.resize(m_tileHWID->drawer_hash_max());
147 m_MBTSmerged.resize(m_tileHWID->drawer_hash_max());
148
149 for (int ros = 3; ros < 5; ++ros) {
150 for (int drawer = 0; drawer < 64; ++drawer) {
151 int frag_id = m_tileHWID->frag(ros, drawer);
152 IdentifierHash frag_hash = m_fragHashFunc(frag_id);
153 m_E1merged[frag_hash] = (m_cabling->E1_merged_with_run2plus(ros, drawer) != 0);
154 m_MBTSmerged[frag_hash] = (m_cabling->is_MBTS_merged_run2plus(drawer));
155 }
156 }
157 ATH_MSG_INFO("Number of E1 cell to be merged: " << std::count (m_E1merged.begin(), m_E1merged.end(), true));
158 ATH_MSG_INFO("Number of MBTS cell to be merged: " << std::count (m_MBTSmerged.begin(), m_MBTSmerged.end(), true));
159 }
160
163 }
164 else {
165 ATH_CHECK(m_hitVectorKeys.assign(m_inputKeys.value()));
166 }
167 ATH_MSG_DEBUG("Input objects in these containers : '" << m_hitVectorNames << "'");
168
169 // Initialize ReadHandleKey
171
172 ATH_CHECK( m_hitContainerKey.initialize() );
174
175 ATH_MSG_DEBUG("TileHitVecToCntTool initialization completed");
176
177 return StatusCode::SUCCESS;
178}
179
181
182 ATH_MSG_VERBOSE("TileHitVecToCntTool createContainers started");
183
184 if (m_pileUp) {
185 m_hits = std::make_unique<TileHitNonConstContainer>(SG::VIEW_ELEMENTS);
186 if(m_doDigiTruth) m_hits_DigiHSTruth = std::make_unique<TileHitNonConstContainer>(SG::VIEW_ELEMENTS);
187
188 if (m_allHits.empty()) {
189
192
193 } else {
194 for (std::unique_ptr<TileHit>& hit : m_allHits) {
195 hit->setZero();
196 }
197
198 if(m_doDigiTruth){
199 for (std::unique_ptr<TileHit>& hit : m_allHits_DigiHSTruth) {
200 hit->setZero();
201 }
202 }
203 }
204 } else {
205 m_hits = std::make_unique<TileHitNonConstContainer>(SG::OWN_ELEMENTS);
206 if(m_doDigiTruth) m_hits_DigiHSTruth = std::make_unique<TileHitNonConstContainer>(SG::OWN_ELEMENTS);
207
208 }
209
210 ATH_MSG_VERBOSE("TileHitVecToCntTool createContainers finished");
211
212 return StatusCode::SUCCESS;
213
214}
215
216StatusCode TileHitVecToCntTool::prepareEvent(const EventContext& ctx, unsigned int /*nInputEvents*/) {
217
218 ATH_MSG_DEBUG("TileHitVecToCntTool prepareEvent initialization started");
219
220 CHECK(this->createContainers());
221
222 ATH_MSG_DEBUG("TileHitVecToCntTool prepareEvent finished");
223
224 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
225 rngWrapper->setSeed( m_randomStreamName, ctx );
226
227 return StatusCode::SUCCESS;
228}
229
230void TileHitVecToCntTool::processHitVectorForOverlay(const TileHitVector* inputHits, std::unique_ptr<TileHitNonConstContainer>& hits, int& nHit, double& eHitTot) const {
231
232 TileHitVecConstIterator inpItr = inputHits->begin();
233 TileHitVecConstIterator end = inputHits->end();
234
235 for (; inpItr != end; ++inpItr) {
236
237 const TileHit * cinp = &(*inpItr);
238
239 eHitTot += cinp->energy(); // not really correct if TileHit contains vector of energies
240 // but eHitTot is needed for debug purposes only
241 TileHit * pHit = new TileHit(*cinp);
242 hits->push_back(pHit);
243 ++nHit;
244
245 if (msgLvl(MSG::VERBOSE)) {
246 int hitsize = cinp->size();
247 double eHit = 0.0;
248 double tHit = 0.0;
249 for (int i = 0; i < hitsize; ++i) {
250 eHit += cinp->energy(i);
251 tHit += cinp->time(i) * cinp->energy(i);
252 }
253 if (eHit > 0.0)
254 tHit /= eHit;
255 else
256 tHit = cinp->time();
257
258 eHitTot += eHit - cinp->energy(); // put total energy instead of first hit energy
259
260 msg(MSG::VERBOSE) << " nHit=" << nHit
261 << " id=" << m_tileID->to_string(cinp->identify(), -1)
262 << " eHit=" << eHit
263 << " tHit=" << tHit
264 << " Copy hit: ener=";
265 for (int i = 0; i < hitsize; ++i)
266 msg(MSG::VERBOSE) << cinp->energy(i) << " ";
267 msg(MSG::VERBOSE) << "time=";
268 for (int i = 0; i < hitsize; ++i)
269 msg(MSG::VERBOSE) << cinp->time(i) << " ";
270 msg(MSG::VERBOSE) << endmsg;
271 }
272 }
273 return;
274}
275
276void TileHitVecToCntTool::processHitVectorForPileUp(const TileHitVector* inputHits, double SubEvtTimOffset,
277 std::vector<std::unique_ptr<TileHit>>& allHits,
278 std::vector<std::unique_ptr<TileHit>>& allHits_DigiHSTruth,
279 int& nHit, double& eHitTot, bool isSignal) const {
280
281 IdContext pmt_context = m_tileID->pmt_context();
282 IdContext tbchannel_context = m_tileTBID->channel_context();
283 IdentifierHash hit_idhash;
284
285 // Loop over hits in this HitVector
286 TileHitVecConstIterator inpItr = inputHits->begin();
287 TileHitVecConstIterator end = inputHits->end();
288
289 for (; inpItr != end; ++inpItr) {
290
291 const TileHit * cinp = &(*inpItr);
292 Identifier hit_id = cinp->identify();
293
294 if (m_tileTBID->is_tiletb(hit_id)) {
295 int side = std::max(0, m_tileTBID->type(hit_id));
296 int phi = m_tileTBID->module(hit_id);
297 int eta = m_tileTBID->channel(hit_id);
298 if (eta < 2)
299 hit_idhash = mbts_index(side, phi, eta);
300 else
301 hit_idhash = e4pr_index(phi);
302 } else {
303 m_tileID->get_hash(hit_id, hit_idhash, &pmt_context);
304 }
305
306 if (hit_idhash >= allHits.size()) {
307 // Seems to be E4pr or MBTS hit in minimum bias while geometry is used without them => skipping
308 continue;
309 }
310
311 double ener = cinp->energy();
312 double time = cinp->time() + SubEvtTimOffset;
313
314 ++nHit;
315 eHitTot += ener;
316
317 std::unique_ptr<TileHit>& pHit = allHits[hit_idhash];
318 std::unique_ptr<TileHit> inValidHit(nullptr);
319 std::unique_ptr<TileHit>& pHit_DigiHSTruth = m_doDigiTruth ? allHits_DigiHSTruth[hit_idhash] : inValidHit;
320
321 if (time < m_maxHitTime){
322 pHit->add(ener, time, m_deltaT);
323 if(m_doDigiTruth){
324 if(isSignal) {
325 pHit_DigiHSTruth->add(ener, time, m_deltaT);
326 } else {
327 pHit_DigiHSTruth->add(0,time, m_deltaT);
328 }
329 }
330 }
331
332 if (msgLvl(MSG::VERBOSE)) {
333 if (pHit->size() > 1 || pHit->energy() != 0.0)
334 msg(MSG::VERBOSE) << " nHit=" << nHit
335 << " id=" << m_tileID->to_string(hit_id, -1)
336 << " ener=" << ener
337 << " time=" << time
338 << " offs=" << SubEvtTimOffset
339 << " double hit" << endmsg;
340 else
341 msg(MSG::VERBOSE) << " nH=" << nHit
342 << " id=" << m_tileID->to_string(hit_id, -1)
343 << " HWid=" << m_tileID->to_string(pHit->pmt_HWID())
344 << " e=" << ener
345 << " time=" << time
346 << " offs=" << SubEvtTimOffset
347 << " new hit" << endmsg;
348 }
349
350 int hitsize = cinp->size();
351 for (int ind = 1; ind < hitsize; ++ind) { // if we have double hits in original hit
352 ener = cinp->energy(ind); // merge all of them with appropriate time
353 time = cinp->time(ind) + SubEvtTimOffset;
354
355 ++nHit;
356 eHitTot += ener;
357
358 if (time < m_maxHitTime){
359 pHit->add(ener, time, m_deltaT);
360 if(m_doDigiTruth){
361 if(isSignal)
362 pHit_DigiHSTruth->add(ener, time, m_deltaT);
363 else
364 pHit_DigiHSTruth->add(0, time, m_deltaT);
365 }
366 }
367
368 if (msgLvl(MSG::VERBOSE))
369 msg(MSG::VERBOSE) << " nHit=" << nHit
370 << " id=" << m_tileID->to_string(hit_id, -1)
371 << " ener=" << ener
372 << " time=" << time
373 << " double hit from single hit" << endmsg;
374 }
375 } // loop over hits in one vector
376 return;
377}
378
379void TileHitVecToCntTool::processHitVectorWithoutPileUp(const TileHitVector* inputHits, int& nHit, double& eHitTot, TileHitNonConstContainer* hitCont, CLHEP::HepRandomEngine * engine) const {
380
381 TileHitVecConstIterator inpItr = inputHits->begin();
382 TileHitVecConstIterator end = inputHits->end();
383
384 //**
385 //* Iterate over hits, creating new TileHits
386 //* Add each TileHit to the TileHitContainer.
387 //**
388
389 switch (m_timeFlag) {
390
391 case 0: {
392 for (; inpItr != end; ++inpItr) {
393 const TileHit * cinp = &(*inpItr);
394 eHitTot += cinp->energy(); // not really correct if TileHit contains vector of energies
395 // but eHitTot is needed for debug purposes only
396 TileHit * pHit = new TileHit(*cinp);
397 hitCont->push_back(pHit);
398 ++nHit;
399
400 if (msgLvl(MSG::VERBOSE)) {
401 int hitsize = cinp->size();
402 double eHit = 0.0;
403 double tHit = 0.0;
404 for (int i = 0; i < hitsize; ++i) {
405 eHit += cinp->energy(i);
406 tHit += cinp->time(i) * cinp->energy(i);
407 }
408 if (eHit > 0.0)
409 tHit /= eHit;
410 else
411 tHit = cinp->time();
412
413 eHitTot += eHit - cinp->energy(); // put total energy instead of first hit energy
414
415 msg(MSG::VERBOSE) << " nHit=" << nHit
416 << " id=" << m_tileID->to_string(cinp->identify(), -1)
417 << " eHit=" << eHit
418 << " tHit=" << tHit
419 << " Copy hit: ener=";
420 for (int i = 0; i < hitsize; ++i)
421 msg(MSG::VERBOSE) << cinp->energy(i) << " ";
422 msg(MSG::VERBOSE) << "time=";
423 for (int i = 0; i < hitsize; ++i)
424 msg(MSG::VERBOSE) << cinp->time(i) << " ";
425 msg(MSG::VERBOSE) << endmsg;
426 }
427 }
428 break;
429 }
430
431 case 1: {
432
433 for (; inpItr != end; ++inpItr) {
434 const TileHit * cinp = &(*inpItr);
435 int size = cinp->size();
436 double eHit = 0.0;
437 for (int i = 0; i < size; ++i) {
438 eHit += cinp->energy(i);
439 }
440 eHitTot += eHit;
441
442 // create hit with total energy at time=0 instead of original one
443 Identifier pmID = cinp->pmt_ID();
444 TileHit * pHit = new TileHit(pmID, eHit, 0.);
445
446 hitCont->push_back(pHit);
447 ++nHit;
448
449 if (msgLvl(MSG::VERBOSE)) {
450 int hitsize = cinp->size();
451 msg(MSG::VERBOSE) << " nHit=" << nHit
452 << " id=" << m_tileID->to_string(cinp->identify(), -1)
453 << " eHit=" << eHit
454 << " tHit=0.0"
455 << " Input hit: ener=";
456 for (int i = 0; i < hitsize; ++i)
457 msg(MSG::VERBOSE) << cinp->energy(i) << " ";
458 msg(MSG::VERBOSE) << "time=";
459 for (int i = 0; i < hitsize; ++i)
460 msg(MSG::VERBOSE) << cinp->time(i) << " ";
461 msg(MSG::VERBOSE) << endmsg;
462 }
463 }
464 break;
465
466 }
467
468 case 2: {
469
470 double avtime = 0.0;
471
472 if (m_useTriggerTime) {
473
474 if (m_triggerTimeKey.empty()) {
475 avtime = m_triggerTime;
476 } else {
478 avtime = cosTriggerTime->time();
479 }
480 ATH_MSG_DEBUG("Trigger time used : " << avtime);
481
482 } else {
483
484 if (m_triggerTime < 0.0) {
485
486 avtime = 1.0e20;
487
488 // loop to find minimal time
489 for (; inpItr != end; ++inpItr) {
490 const TileHit * cinp = &(*inpItr);
491 int size = cinp->size();
492 for (int i = 0; i < size; ++i) {
493 if (cinp->time(i) < avtime) avtime = cinp->time(i);
494 }
495 }
496 ATH_MSG_DEBUG("Minimal time in input event " << avtime);
497 double shift = RandFlat::shoot(engine, m_triggerTime, 0.0);
498 ATH_MSG_DEBUG("Minimal time after random shift " << shift);
499 avtime -= shift; // subtracting negative shift value here
500
501 } else {
502
503 double weight = 0.0;
504
505 // loop to calculate average time
506 for (; inpItr != end; ++inpItr) {
507 const TileHit * cinp = &(*inpItr);
508 int size = cinp->size();
509 for (int i = 0; i < size; ++i) {
510 avtime += cinp->time(i) * cinp->energy(i);
511 weight += cinp->energy(i);
512 }
513 }
514 if (weight > 0.0)
515 avtime /= weight;
516 else
517 avtime = 0.0;
518
519 ATH_MSG_DEBUG("Average time used : " << avtime);
520 }
521
522 // reset iterator to the first hit
523 inpItr = inputHits->begin();
524 }
525
526 for (; inpItr != end; ++inpItr) {
527 const TileHit * cinp = &(*inpItr);
528 TileHit * pHit = new TileHit(*cinp);
529 // subract average time from all time bins in the hit
530 int size = pHit->size();
531 for (int i = 0; i < size; ++i) {
532 pHit->setTime(pHit->time(i) - avtime, i);
533 eHitTot += cinp->energy(i);
534 }
535
536 hitCont->push_back(pHit);
537 ++nHit;
538
539 if (msgLvl(MSG::VERBOSE)) {
540 int hitsize = pHit->size();
541 double eHit = 0.0;
542 double tHit = 0.0;
543 for (int i = 0; i < hitsize; ++i) {
544 eHit += pHit->energy(i);
545 tHit += pHit->time(i) * cinp->energy(i);
546 }
547 if (eHit > 0.0)
548 tHit /= eHit;
549 else
550 tHit = cinp->time(); // just first time
551
552 msg(MSG::VERBOSE) << " nHit=" << nHit
553 << " id=" << m_tileID->to_string(pHit->identify(), -1)
554 << " eHit=" << eHit
555 << " tHit=" << tHit
556 << " Output hit: ener=";
557 for (int i = 0; i < hitsize; ++i)
558 msg(MSG::VERBOSE) << pHit->energy(i) << " ";
559 msg(MSG::VERBOSE) << "time=";
560 for (int i = 0; i < hitsize; ++i)
561 msg(MSG::VERBOSE) << pHit->time(i) << " ";
562 msg(MSG::VERBOSE) << endmsg;
563 }
564 }
565 break;
566 }
567
568 default:
569 ATH_MSG_ERROR("unexpected value m_timeFlag=" << m_timeFlag);
570 break;
571 }
572
573 return;
574}
575
577 , SubEventIterator bSubEvents
578 , SubEventIterator eSubEvents)
579{
580
581 ATH_MSG_DEBUG("Inside TileHitVecToCntTool processBunchXing" << bunchXing);
582 // setFilterPassed(true);
583
584 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
585 CLHEP::HepRandomEngine * engine = rngWrapper->getEngine(Gaudi::Hive::currentContext());
586
587 SubEventIterator iEvt(bSubEvents);
588 if (m_rndmEvtOverlay && bunchXing != 0) iEvt = eSubEvents; // in overlay skip all events except BC=0
589
590 while (iEvt != eSubEvents) {
591 /* zero all counters and sums */
592 int nHit(0);
593 double eHitTot(0.0);
594
595 std::vector<std::string>::const_iterator hitVecNamesItr = m_hitVectorNames.begin();
596 std::vector<std::string>::const_iterator hitVecNamesEnd = m_hitVectorNames.end();
597 for (; hitVecNamesItr != hitVecNamesEnd; ++hitVecNamesItr) {
598
599 const std::string hitVectorName(*hitVecNamesItr);
600
601 if (m_pileUp || m_rndmEvtOverlay) {
602
603 const TileHitVector* inputHits = nullptr;
604 if (!(m_mergeSvc->retrieveSingleSubEvtData(hitVectorName, inputHits, bunchXing, iEvt))){
605 ATH_MSG_ERROR(" Tile Hit container not found for event key " << hitVectorName);
606 }
607
608 const double SubEvtTimOffset(iEvt->time());
609
610 if (m_rndmEvtOverlay) { // overlay code
611 if (fabs(SubEvtTimOffset) > 0.1) {
612 ATH_MSG_ERROR("Wrong time for in-time event: " << SubEvtTimOffset << " Ignoring all hits ");
613 } else {
614 ATH_MSG_DEBUG(" New HitCont. TimeOffset=" << SubEvtTimOffset << ", size =" << inputHits->size());
615 this->processHitVectorForOverlay(inputHits, m_hits, nHit, eHitTot);
616 //if( m_doDigiTruth && iEvt == bSubEvents) this->processHitVectorWithoutPileUp(inputHits, nHit, eHitTot, m_signalHits, engine);
617 }
618 } else if (m_pileUp) { // pileup code
619 bool isSignal = false;
620 if(iEvt == bSubEvents) isSignal = true;
621 this->processHitVectorForPileUp(inputHits, SubEvtTimOffset, m_allHits, m_allHits_DigiHSTruth, nHit, eHitTot, isSignal);
622 }
623 } else { // no PileUp
624 //**
625 //* Get TileHits from TileHitVector
626 //**
627 const TileHitVector * inputHits = nullptr;
628 if (!(m_mergeSvc->retrieveSingleSubEvtData(hitVectorName, inputHits, bunchXing, iEvt))){
629 ATH_MSG_ERROR(" Tile Hit container not found for event key " << hitVectorName);
630 }
631
632 this->processHitVectorWithoutPileUp(inputHits, nHit, eHitTot, m_hits.get(), engine);
633 if(m_doDigiTruth) this->processHitVectorWithoutPileUp(inputHits, nHit, eHitTot, m_hits_DigiHSTruth.get(), engine);
634 } // to pile-up or not
635
636 } // end of the loop over different input hitVectorNames (normal hits and MBTS hits)
637
638 ++iEvt;
639 if (m_rndmEvtOverlay) iEvt = eSubEvents; // in overlay skip all events except fisrt one
640 } // subEvent loop
641
642 ATH_MSG_DEBUG("Exiting processBunchXing in TileHitVecToCntTool");
643
644 return StatusCode::SUCCESS;
645}
646
647StatusCode TileHitVecToCntTool::processAllSubEvents(const EventContext& ctx) {
648 return ((const TileHitVecToCntTool*) this)->processAllSubEvents(ctx);
649}
650
651
652StatusCode TileHitVecToCntTool::processAllSubEvents(const EventContext& ctx) const {
653
654
655 ATH_MSG_DEBUG("TileHitVecToCntTool processAllSubEvents started");
656 typedef PileUpMergeSvc::TimedList<TileHitVector>::type TimedHitContList;
657
659
660 std::vector<std::unique_ptr<TileHit>> allHits;
661 auto hits = std::make_unique<TileHitNonConstContainer>(ownPolicy);
662
663 std::vector<std::unique_ptr<TileHit>> allHits_DigiHSTruth;
664 std::unique_ptr<TileHitNonConstContainer> hits_DigiHSTruth;
665 if (m_doDigiTruth) {
666 hits_DigiHSTruth = std::make_unique<TileHitNonConstContainer>(ownPolicy);
667 }
668 if (m_pileUp) {
669 prepareAllHits(allHits);
670 if (m_doDigiTruth) {
671 prepareAllHits(allHits_DigiHSTruth);
672 }
673 }
674
675 /* zero all counters and sums */
676 int nHit(0);
677 double eHitTot(0.0);
678
679 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
680 rngWrapper->setSeed( name(), ctx );
681 CLHEP::HepRandomEngine * engine = rngWrapper->getEngine(ctx);
682
684 auto hitVectorHandles = m_hitVectorKeys.makeHandles(ctx);
685 for (auto & inputHits : hitVectorHandles) {
686 if (!inputHits.isValid()) {
687 ATH_MSG_ERROR("Input Tile hit container is missing!");
688 return StatusCode::FAILURE;
689 }
690 const double SubEvtTimeOffset(0.0);
691 // get HitVector for this subevent
692 ATH_MSG_DEBUG(" New HitCont. TimeOffset=" << SubEvtTimeOffset << ", size =" << inputHits->size());
693 this->processHitVectorForOverlay(inputHits.cptr(), hits, nHit, eHitTot);
694 if(m_doDigiTruth) this->processHitVectorWithoutPileUp(inputHits.cptr(), nHit, eHitTot, hits_DigiHSTruth.get(), engine);
695 }
696 ATH_CHECK(commitContainers(ctx, hits, hits_DigiHSTruth, ownPolicy));
697 return StatusCode::SUCCESS;
698 }
699
700 for (const auto& hitVectorName : m_hitVectorNames) {
701
702 if (m_pileUp || m_rndmEvtOverlay) {
703 TimedHitContList hitContList;
704 // retrieve list of pairs (time,container) from PileUp service
705 if (!(m_mergeSvc->retrieveSubEvtsData(hitVectorName, hitContList).isSuccess()) || hitContList.size() == 0) {
706 ATH_MSG_WARNING("Could not fill TimedHitContList for hit vector " << hitVectorName);
707 continue; // continue to the next hit vector
708 }
709
710 // loop over this list
711 TimedHitContList::iterator iCont(hitContList.begin());
712 TimedHitContList::iterator iEndCont(hitContList.end());
713
714 if (m_rndmEvtOverlay) { // overlay code
715 if (iCont != iEndCont) { // use only hits from first container
716 // get time for this subevent
717 const double SubEvtTimeOffset(iCont->first.time());
718 if (fabs(SubEvtTimeOffset) > 0.1) {
719 ATH_MSG_ERROR("Wrong time for in-time event: " << SubEvtTimeOffset << " Ignoring all hits ");
720 } else {
721 // get HitVector for this subevent
722 const TileHitVector* inputHits = &(*(iCont->second));
723 ATH_MSG_DEBUG(" New HitCont. TimeOffset=" << SubEvtTimeOffset << ", size =" << inputHits->size());
724 this->processHitVectorForOverlay(inputHits, hits, nHit, eHitTot);
725 if(m_doDigiTruth) this->processHitVectorWithoutPileUp(inputHits, nHit, eHitTot, hits_DigiHSTruth.get(), engine);
726 }
727 }
728 } else if (m_pileUp) { // pileup code
729
730 for (; iCont != iEndCont; ++iCont) {
731 // get time for this subevent
732 const double SubEvtTimeOffset(iCont->first.time());
733 // get HitVector for this subevent
734 const TileHitVector* inputHits = &(*(iCont->second));
735 ATH_MSG_VERBOSE(" New HitCont. TimeOffset=" << SubEvtTimeOffset << ", size =" << inputHits->size());
736 bool isSignal = false;
737 if(iCont == hitContList.begin() ) isSignal = true;
738 this->processHitVectorForPileUp(inputHits, SubEvtTimeOffset, allHits, allHits_DigiHSTruth, nHit, eHitTot, isSignal);
739 }
740 } // loop over subevent list
741 } else { // no PileUp
742
743 //**
744 //* Get TileHits from TileHitVector
745 //**
746 SG::ReadHandle<TileHitVector> inputHits(hitVectorName);
747 if (!inputHits.isValid()) {
748 ATH_MSG_WARNING("Hit Vector "<< hitVectorName << " not found in StoreGate");
749 continue; // continue to the next hit vector
750 }
751 this->processHitVectorWithoutPileUp(inputHits.cptr(), nHit, eHitTot, hits.get(), engine);
752 if(m_doDigiTruth) this->processHitVectorWithoutPileUp(inputHits.cptr(), nHit, eHitTot, hits_DigiHSTruth.get(), engine);
753 }
754
755 } // end of the loop over different input hitVectorNames (normal hits and MBTS hits)
756
757 if (m_pileUp) {
758 putAllHitsInContainer(allHits, allHits_DigiHSTruth, hits, hits_DigiHSTruth, ownPolicy);
759 }
760
761 ATH_CHECK(commitContainers(ctx, hits, hits_DigiHSTruth, ownPolicy));
762
763 return StatusCode::SUCCESS;
764}
765
766void TileHitVecToCntTool::putAllHitsInContainer(std::vector<std::unique_ptr<TileHit>>& allHits,
767 std::vector<std::unique_ptr<TileHit>>& allHits_DigiHSTruth,
768 std::unique_ptr<TileHitNonConstContainer>& hits,
769 std::unique_ptr<TileHitNonConstContainer>& hits_DigiHSTruth,
770 SG::OwnershipPolicy ownPolicy) const {
771
772 std::vector<std::unique_ptr<TileHit>>::iterator iHit = allHits.begin();
773 std::vector<std::unique_ptr<TileHit>>::iterator lastHit = allHits.end();
774 std::vector<std::unique_ptr<TileHit>>::iterator iHit_DigiHSTruth = allHits_DigiHSTruth.begin();
775
776 int nHitUni = 0;
777 double eHitInTime = 0.0;
778
779 ATH_MSG_DEBUG("Hits being stored in container");
780
781 std::function<TileHit*(std::unique_ptr<TileHit>&)> getOrRelease(&std::unique_ptr<TileHit>::get);
782 if (ownPolicy == SG::OWN_ELEMENTS) getOrRelease = &std::unique_ptr<TileHit>::release;
783
784 for (; iHit != lastHit; ++iHit) {
785 std::unique_ptr<TileHit>& hit = (*iHit);
786 if (hit->size() > 1 || hit->energy() != 0.0) { // hit exists
787 eHitInTime += hit->energy();
788 hits->push_back(getOrRelease(hit));
789 if(m_doDigiTruth) hits_DigiHSTruth->push_back(getOrRelease((*iHit_DigiHSTruth)));
790 ++nHitUni;
791 }
792 if(m_doDigiTruth) ++iHit_DigiHSTruth;
793 }
794
795 ATH_MSG_DEBUG(" nHitUni=" << nHitUni << " eHitInTime="<< eHitInTime);
796}
797
798StatusCode TileHitVecToCntTool::commitContainers(const EventContext& ctx,
799 std::unique_ptr<TileHitNonConstContainer>& hits,
800 std::unique_ptr<TileHitNonConstContainer>& hits_DigiHSTruth,
801 SG::OwnershipPolicy ownPolicy) const {
802
803 ATH_MSG_DEBUG("Entering commitContainers");
804
805 if (!m_pileUp) {
808 if (m_doDigiTruth) {
809 findAndMergeMultipleHitsInChannel(hits_DigiHSTruth);
810 }
811 }
812 }
813
814 if (m_run2plus) {
815 // Merge MBTS and E1 where it is needed.
816
817 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
818 int frag_id = coll->identify();
819 IdentifierHash frag_hash = m_fragHashFunc(frag_id);
820 if (m_E1merged[frag_hash])
821 findAndMergeE1(coll.get(), frag_id, hits.get());
822 else if (m_MBTSmerged[frag_hash]) findAndMergeMBTS(coll.get(), frag_id, hits.get());
823 }
824 if(m_doDigiTruth){
825 TileHitNonConstContainer::iterator collIt = hits_DigiHSTruth->begin();
826 TileHitNonConstContainer::iterator endcollIt = hits_DigiHSTruth->end();
827
828 for (; collIt != endcollIt; ++collIt) {
829 int frag_id = (*collIt)->identify();
830 IdentifierHash frag_hash = m_fragHashFunc(frag_id);
831 if (m_E1merged[frag_hash]) findAndMergeE1((*collIt).get(), frag_id, hits_DigiHSTruth.get());
832 else if (m_MBTSmerged[frag_hash]) findAndMergeMBTS((*collIt).get(), frag_id, hits_DigiHSTruth.get());
833 }
834 }
835 }
836
837 //photoelectron statistics.
838 //loop over all hits in TileHitContainer and take energy deposited in certain period of time
839 //std::vector<std::string>::const_iterator hitVecNamesEnd = m_hitVectorNames.end();
840
841 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
842 CLHEP::HepRandomEngine * engine = rngWrapper->getEngine(ctx);
843
845 ATH_CHECK( samplingFraction.isValid() );
846
847 TileHitNonConstContainer::iterator collIt_DigiHSTruth;
848 TileHitNonConstContainer::iterator endColl_DigiHSTruth;
849 if(m_doDigiTruth) {
850 collIt_DigiHSTruth = hits_DigiHSTruth->begin();
851 endColl_DigiHSTruth = hits_DigiHSTruth->end();
852 }
853
854 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
855 TileHitCollection* coll_DigiHSTruth;
856 TileHitCollection::iterator hitItr_DigiHSTruth;
857 TileHitCollection::iterator hitEnd_DigiHSTruth;
858 if(m_doDigiTruth) {
859 coll_DigiHSTruth = (*collIt_DigiHSTruth).get();
860 hitItr_DigiHSTruth = coll_DigiHSTruth->begin();
861 hitEnd_DigiHSTruth = coll_DigiHSTruth->end();
862 }
863
864 HWIdentifier drawer_id = m_tileHWID->drawer_id(coll->identify());
865 int ros = m_tileHWID->ros(drawer_id);
866 int drawer = m_tileHWID->drawer(drawer_id);
867 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
868
869 for (TileHit* pHit : *coll) {
870 double ehit = 0.0;
871 int hitsize = pHit->size();
872 for (int i = 0; i < hitsize; ++i) {
873 double thit = pHit->time(i);
874 if (fabs(thit) < m_photoStatisticsWindow) ehit += pHit->energy(i);
875 }
876
877 Identifier pmt_id = pHit->pmt_ID();
878 //HWIdentifier channel_id = (*hitItr)->pmt_HWID();
879 // for gap/crack scintillators
880 if (m_tileID->sample(pmt_id) == 3) {
881 pmt_id = m_tileID->pmt_id(m_tileID->cell_id(pmt_id), 0);
882 //channel_id = m_cabling->s2h_channel_id(pmt_id);
883 }
884
885 double scaleFactor = 1.0;
887 scaleFactor = applyPhotoStatistics(ehit, pmt_id, engine, *samplingFraction, drawerIdx);
888 pHit->scale(scaleFactor);
889 }
890
891 if(m_doDigiTruth){
892 TileHit *pHit_DigiHSTruth = (*hitItr_DigiHSTruth);
893 pHit_DigiHSTruth->scale(scaleFactor);
894
895 ++hitItr_DigiHSTruth;
896 }
897 }
898
899 if(m_doDigiTruth) ++collIt_DigiHSTruth;
900 }
901
902
903 /* Register the set of TileHits to the event store. */
904 auto hitCont = std::make_unique<TileHitContainer>(false, ownPolicy);
905 size_t hashId = 0;
906 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
907 CHECK(hitCont->addCollection (coll.release(), hashId++));
908 }
909
911 ATH_CHECK( hitContainer.record(std::move(hitCont)) );
912
913 ATH_MSG_DEBUG("TileHit container registered to the TES with name" << m_hitContainerKey.key());
914
915 if(m_doDigiTruth){
916 auto hitCont_DigiHSTruth = std::make_unique<TileHitContainer>(false, ownPolicy);
917 size_t hashId_DigiHSTruth = 0;
918 for (std::unique_ptr<TileHitCollection>& coll : *hits_DigiHSTruth ) {
919 ATH_CHECK(hitCont_DigiHSTruth->addCollection (coll.release(), hashId_DigiHSTruth++));
920 }
921
923 ATH_CHECK( hitContainer_DigiHSTruth.record(std::move(hitCont_DigiHSTruth)) );
924 }
925
926 ATH_MSG_DEBUG("Exiting mergeEvent in TileHitVecToCntTool");
927 return StatusCode::SUCCESS;
928}
929
930
931StatusCode TileHitVecToCntTool::mergeEvent(const EventContext &ctx) {
933 if (m_pileUp) {
934 ownPolicy = SG::VIEW_ELEMENTS;
936 }
937 return commitContainers(ctx, m_hits, m_hits_DigiHSTruth, ownPolicy);
938}
939
941
942 ATH_MSG_DEBUG("Finalizing TileHitVecToCntTool");
943
944 ATH_MSG_DEBUG("TileHitVecToCntTool finalized");
945
946 return StatusCode::SUCCESS;
947
948}
949
950double TileHitVecToCntTool::applyPhotoStatistics(double energy, Identifier pmt_id, CLHEP::HepRandomEngine* engine,
951 const TileSamplingFraction* samplingFraction, int drawerIdx) const {
952
953 int channel = m_tileHWID->channel(m_cabling->s2h_channel_id(pmt_id));
954 // take number of photoelectrons per GeV divide by 1000 to go to MeV
955 // and multiply by inverted sampling fraction (about 36, depends on G4 version, sampling and eta)
956 // to get number of photoelectrons per 1 MeV energy in scintillator
957 float nPhotoElectrons = samplingFraction->getNumberOfPhotoElectrons(drawerIdx, channel)
958 / (Gaudi::Units::GeV / Gaudi::Units::MeV) * samplingFraction->getSamplingFraction(drawerIdx, channel);
959
960 nPhotoElectrons = std::round(nPhotoElectrons * 1000) / 1000;
961
962 double pe = energy * nPhotoElectrons;
963 double pe_scale = 1., RndmPois = 1.;
964
966 case 2:
967 if (pe > 20.0) {
968 RndmPois = std::max(0.0, RandGaussQ::shoot(engine, pe, sqrt(pe))); // FIXME CLHEP::RandGaussZiggurat is faster and more accurate.
969 pe_scale = RndmPois / pe;
970 } else { // pe<=20
971
972 if (pe > 0.) {
973 double singleMEAN = 1.0; //Parameterization of monoelectron spectra
974 double singleSIGMA = 1.0;
975 RndmPois = RandPoissonT::shoot(engine, pe);
976
977 if (RndmPois > 0) {
978 pe_scale = 0;
979 for (int i = 0; i < RndmPois; i++)
980 pe_scale += 1 / (1.08332) * std::max(0., RandGaussQ::shoot(engine, singleMEAN, singleSIGMA)); // FIXME CLHEP::RandGaussZiggurat is faster and more accurate.
981
982 pe_scale /= RndmPois;
983 } else
984 pe_scale = 0; //RndmPois==0
985 }
986 }
987 break;
988
989 case 0:
990 if (pe > 0.0) {
991 RndmPois = RandPoissonT::shoot(engine, pe);
992 pe_scale = RndmPois / pe;
993 }
994 break;
995
996 case 1:
997 if (pe > 0.0) {
998 if (pe > 10.0) {
999 RndmPois = std::max(0.0, RandGaussQ::shoot(engine, pe, sqrt(pe))); // FIXME CLHEP::RandGaussZiggurat is faster and more accurate.
1000 } else {
1001 int nn = std::max(10, (int) (pe * 10.0));
1002 double * ProbFunc = new double[nn];
1003 ProbFunc[0] = exp(-pe);
1004 for (int i = 1; i < nn; ++i) {
1005 ProbFunc[i] = ProbFunc[i - 1] * pe / i;
1006 }
1007 RandGeneral* RandG = new RandGeneral(ProbFunc, nn, 0);
1008 RndmPois = RandG->shoot(engine) * nn;
1009 //here RndmPois is continuously distributed random value obtained from Poisson
1010 //distribution by approximation.
1011 delete RandG;
1012 delete[] ProbFunc;
1013 }
1014 pe_scale = RndmPois / pe;
1015 }
1016 break;
1017 } //end switch(m_PhElStat)
1018
1019 ATH_MSG_VERBOSE( "PhotoElec: id=" << m_tileID->to_string(pmt_id,-1)
1020 << " totEne=" << energy
1021 << ", numPhElec=" << nPhotoElectrons
1022 << ", pe=" << pe
1023 << ", rndmPoisson=" << RndmPois
1024 << ", pe_scale=" << pe_scale);
1025
1026 return pe_scale;
1027}
1028
1029
1031 int module = frag_id & 0x3F;
1032
1033 TileHitCollection::iterator hitIt = coll->begin();
1034 TileHitCollection::iterator endHitIt = coll->end();
1035
1036 TileHitCollection::iterator fromHitIt = coll->end();
1037 TileHit* toHit(0);
1038
1039 for (; hitIt != endHitIt; ++hitIt) {
1040 Identifier pmt_id = (*hitIt)->pmt_ID();
1041 if (m_tileID->tower(pmt_id) == E1_TOWER && m_tileID->sample(pmt_id) == TileID::SAMP_E) {
1042 if (module == m_tileID->module(pmt_id)) {
1043 toHit = *hitIt;
1044 } else {
1045 fromHitIt = hitIt; // need iterator to delete this hit later.
1046 }
1047 }
1048 }
1049
1050 if (fromHitIt != coll->end()) {
1051 ATH_MSG_VERBOSE("Found TileHit (E1 cell) for merging [" << m_tileID->to_string((*fromHitIt)->pmt_ID(), -1)
1052 << "] in module: " << module);
1053 bool isToHitNew = false;
1054 if (toHit == 0) {
1055 int side = m_tileID->side((*fromHitIt)->pmt_ID());
1056 Identifier to_pmt_id = m_tileID->pmt_id(TileID::GAPDET, side, module, E1_TOWER, TileID::SAMP_E, 0);
1057 toHit = new TileHit(to_pmt_id);
1058 isToHitNew = true;
1059 ATH_MSG_VERBOSE("New TileHit (E1 cell) for merging added Id: " << m_tileID->to_string(toHit->pmt_ID(), -1) );
1060 } else {
1061 ATH_MSG_VERBOSE("Found TileHit (E1 cell) for merging Id: " << m_tileID->to_string(toHit->pmt_ID(), -1) );
1062 }
1063
1064 ATH_MSG_DEBUG( "TileHit (E1 cell) Id: " << m_tileID->to_string((*fromHitIt)->pmt_ID(), -1)
1065 << " will be merged to " << m_tileID->to_string(toHit->pmt_ID(), -1) );
1066
1067 if (msgLvl(MSG::VERBOSE)) {
1068 msg(MSG::VERBOSE) << "Before merging (E1 cell) => " << (std::string) (**fromHitIt) << endmsg;
1069 msg(MSG::VERBOSE) << "Before merging (E1 cell) => " << (std::string) (*toHit) << endmsg;
1070 }
1071
1072 toHit->add(*fromHitIt, 0.1);
1073
1074 if (msgLvl(MSG::VERBOSE)) {
1075 msg(MSG::VERBOSE) << "After merging (E1 cell) => " << (std::string) (*toHit) << endmsg;
1076 msg(MSG::VERBOSE) << "TileHit to be deleted Id (E1 cell): " << m_tileID->to_string((*fromHitIt)->pmt_ID(), -1) << endmsg;
1077 }
1078
1079 coll->erase(fromHitIt);
1080
1081 if (isToHitNew) {
1082 hitCont->push_back(toHit);
1083 }
1084 }
1085}
1086
1087
1089 int module = frag_id & 0x3F;
1090
1091 TileHitCollection::iterator hitIt = coll->begin();
1092 TileHitCollection::iterator endHitIt = coll->end();
1093
1094 TileHitCollection::iterator fromHitIt = coll->end();
1095 TileHit* toHit(0);
1096
1097 for (; hitIt != endHitIt; ++hitIt) {
1098 Identifier pmt_id = (*hitIt)->pmt_ID();
1099 if (m_tileTBID->is_tiletb(pmt_id)) {
1100 if (m_tileTBID->phi(pmt_id) % 2 == 0) {
1101 toHit = *hitIt;
1102 } else {
1103 fromHitIt = hitIt; // need iterator to delete this hit later.
1104 }
1105 }
1106 }
1107
1108 if (fromHitIt != coll->end()) {
1109 ATH_MSG_VERBOSE("Found TileHit (MBTS) for merging [" << m_tileTBID->to_string((*fromHitIt)->pmt_ID(), 0)
1110 << "] in module: " << module);
1111 bool isToHitNew = false;
1112 if (toHit == 0) {
1113 int side = m_tileTBID->side((*fromHitIt)->pmt_ID());
1114 int phi = m_tileTBID->phi((*fromHitIt)->pmt_ID()) - 1;
1115 Identifier to_pmt_id = m_tileTBID->channel_id(side, phi, 1);
1116 toHit = new TileHit(to_pmt_id);
1117 isToHitNew = true;
1118 ATH_MSG_VERBOSE("New TileHit (MBTS) for merging added Id: " << m_tileTBID->to_string(toHit->pmt_ID(), 0) );
1119 } else {
1120 ATH_MSG_VERBOSE("Found TileHit (MBTS) for merging Id: " << m_tileTBID->to_string(toHit->pmt_ID(), 0) );
1121 }
1122
1123 ATH_MSG_DEBUG( "TileHit (MBTS) Id: " << m_tileTBID->to_string((*fromHitIt)->pmt_ID(), 0)
1124 << " will be merged to " << m_tileTBID->to_string(toHit->pmt_ID(), 0) );
1125
1126 if (msgLvl(MSG::VERBOSE)) {
1127 msg(MSG::VERBOSE) << "Before merging (MBTS) => " << (std::string) (**fromHitIt) << endmsg;
1128 msg(MSG::VERBOSE) << "Before merging (MBTS) => " << (std::string) (*toHit) << endmsg;
1129 }
1130
1131 toHit->add(*fromHitIt, 0.1);
1132
1133 if (msgLvl(MSG::VERBOSE)) {
1134 msg(MSG::VERBOSE) << "After merging (MBTS) => " << (std::string) (*toHit) << endmsg;
1135 msg(MSG::VERBOSE) << "TileHit to be deleted Id (MBTS): "
1136 << m_tileTBID->to_string((*fromHitIt)->pmt_ID(), 0) << endmsg;
1137 }
1138
1139 coll->erase(fromHitIt);
1140
1141 if (isToHitNew) {
1142 hitCont->push_back(toHit);
1143 }
1144 }
1145}
1146
1147void TileHitVecToCntTool::findAndMergeMultipleHitsInChannel(std::unique_ptr<TileHitNonConstContainer>& hitCont) const {
1148 for (std::unique_ptr<TileHitCollection>& coll : *hitCont) {
1149
1150 int frag_id = coll->identify();
1151 int module = frag_id & 0x3F;
1152 IdentifierHash frag_hash = m_fragHashFunc(frag_id);
1153 std::vector<TileHit*> hits(48, nullptr);
1154 std::vector<std::unique_ptr<TileHit>> otherModuleHits;
1155 coll->erase(std::remove_if(coll->begin(), coll->end(),
1156 [this, &hits, &otherModuleHits, module, frag_hash] (TileHit* hit) {
1157 Identifier pmt_id = hit->pmt_ID();
1158 int channel = m_tileHWID->channel(hit->pmt_HWID());
1159 TileHit* channelHit = hits[channel];
1160 if (channelHit) {
1161 mergeExtraHitToChannelHit(hit, channelHit);
1162 return true;
1163 } else if (m_run2plus // Special case for merged E1 and MBTS in Run 2+ geometries, which will be merged finally correctly later
1164 && ((m_E1merged[frag_hash] && m_tileID->module(pmt_id) != module
1165 && m_tileID->tower(pmt_id) == E1_TOWER && m_tileID->sample(pmt_id) == TileID::SAMP_E) // Merged E1 in Run 2+ from other module
1166 || (m_MBTSmerged[frag_hash] && m_tileTBID->is_tiletb(pmt_id) && (m_tileTBID->phi(pmt_id) % 2 == 1)))) { // Merged MBTS in Run 2+ from other module
1167 otherModuleHits.push_back(std::make_unique<TileHit>(*hit));
1168 return true;
1169 } else {
1170 hits[channel] = hit;
1171 return false;
1172 }}),
1173 coll->end());
1174
1175 for (std::unique_ptr<TileHit>& hit : otherModuleHits) {
1176 int channel = m_tileHWID->channel(hit->pmt_HWID());
1177 TileHit* channelHit = hits[channel];
1178 if (channelHit) {
1179 mergeExtraHitToChannelHit(hit.get(), channelHit);
1180 } else {
1181 hits[channel] = hit.get();
1182 coll->push_back(std::move(hit));
1183 }
1184 }
1185 }
1186}
1187
1189
1190 ATH_MSG_DEBUG("Found extra hit for channel Id: "
1191 << m_tileID->to_string(extraHit->pmt_ID(), -1) << ", will be merged to "
1192 << m_tileID->to_string(channelHit->pmt_ID(), -1));
1193 ATH_MSG_VERBOSE("Before merging => " << (std::string) (*extraHit));
1194 ATH_MSG_VERBOSE("Before merging => " << (std::string) (*channelHit));
1195
1196 channelHit->add(extraHit, 0.1);
1197
1198 ATH_MSG_VERBOSE("After merging => " << (std::string) (*channelHit));
1199}
1200
1201
1202void TileHitVecToCntTool::prepareAllHits(std::vector<std::unique_ptr<TileHit>>& allHits) const {
1203
1206 allHits.reserve(nHits);
1207
1208 Identifier hit_id;
1209 IdContext pmt_context = m_tileID->pmt_context();
1210 for (int i = 0; i < m_mbtsOffset; ++i) {
1211 m_tileID->get_id((IdentifierHash) i, hit_id, &pmt_context);
1212 allHits.emplace_back(std::make_unique<TileHit>(hit_id, 0., 0.));
1213 allHits.back()->reserve(71); // reserve max possible size for pileup
1214 }
1215
1216 allHits.resize(allHits.size() + N_MBTS_CELLS);
1217 for (int side = 0; side < N_SIDE; ++side) {
1218 for (int phi = 0; phi < N_PHI; ++phi) {
1219 for (int eta = 0; eta < N_ETA; ++eta) {
1220 int mbtsIndex = mbts_index(side, phi, eta);
1221 hit_id = m_tileTBID->channel_id((side > 0) ? 1 : -1, phi, eta);
1222 allHits[mbtsIndex] = std::make_unique<TileHit>(hit_id, 0., 0.);
1223 allHits[mbtsIndex]->reserve(71); // reserve max possible size for pileup
1224 }
1225 }
1226 }
1227 if (m_run2) {
1228 allHits.resize(allHits.size() + N_E4PRIME_CELLS);
1229 for (int phi = 0; phi < E4_N_PHI; ++phi) {
1230 int e4prIndex = e4pr_index(phi);
1231 hit_id = m_tileTBID->channel_id(E4_SIDE, phi, E4_ETA);
1232 allHits[e4prIndex] = std::make_unique<TileHit>(hit_id, 0., 0.);
1233 allHits[e4prIndex]->reserve(71); // reserve max possible size for pileup
1234 }
1235 }
1236}
Scalar eta() const
pseudorapidity method
Scalar phi() const
phi method
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Helpers for checking error return status codes and reporting errors.
#define CHECK(...)
Evaluate an expression and check for errors.
std::vector< xAOD::EventInfo::SubEvent >::const_iterator SubEventIterator
Definition IPileUpTool.h:22
if(febId1==febId2)
static const uint32_t nHits
Handle class for recording to StoreGate.
AtlasHitsVector< TileHit >::const_iterator TileHitVecConstIterator
AtlasHitsVector< TileHit > TileHitVector
A wrapper class for event-slot-local random engines.
Definition RNGWrapper.h:56
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
Definition RNGWrapper.h:169
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition RNGWrapper.h:134
const_iterator begin() const
size_type size() const
const_iterator end() const
const T * get(size_type n) const
Access an element, as an rvalue.
DataModel_detail::iterator< DataVector > iterator
Standard iterator.
Definition DataVector.h:842
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
iterator erase(iterator position)
Remove element at a given position.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
Definition IdContext.h:26
This is a "hash" representation of an Identifier.
PileUpToolBase(const std::string &type, const std::string &name, const IInterface *parent)
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
This is a minimal version of a TileHitContainer in which the saved collections remain non-const.
TileHitVecToCntTool(const std::string &type, const std::string &name, const IInterface *parent)
Constructor.
bool m_run2plus
if true => RUN2+ geometry with merged E1 (and E4' in RUN2)
Gaudi::Property< bool > m_rndmEvtOverlay
If true => overlay with random event (zero-luminosity pile-up)
void processHitVectorForPileUp(const TileHitVector *inputHits, double SubEvtTimOffset, std::vector< std::unique_ptr< TileHit > > &allHits, std::vector< std::unique_ptr< TileHit > > &allHits_DigiHSTruth, int &nHit, double &eHitTot, bool isSignal=false) const
double applyPhotoStatistics(double energy, Identifier pmt_id, CLHEP::HepRandomEngine *engine, const TileSamplingFraction *samplingFraction, int drawerIdx) const
std::unique_ptr< TileHitNonConstContainer > m_hits
pointer to hits container
virtual StatusCode prepareEvent(const EventContext &ctx, unsigned int) override final
SG::WriteHandleKey< TileHitContainer > m_hitContainer_DigiHSTruthKey
void findAndMergeMultipleHitsInChannel(std::unique_ptr< TileHitNonConstContainer > &hitCont) const
Gaudi::Property< double > m_photoStatisticsWindow
sum up energy in [-m_photoStatWindow,+m_photoStatWindow] and use it for photostatistics
void prepareAllHits(std::vector< std::unique_ptr< TileHit > > &allHits) const
SG::ReadHandleKey< CosTrigTime > m_triggerTimeKey
void findAndMergeMBTS(TileHitCollection *coll, int frag_id, TileHitNonConstContainer *hitCont) const
int mbts_index(int side, int phi, int eta) const
Gaudi::Property< bool > m_useTriggerTime
if true => take trigger time from external tool or from m_triggerTime
SG::ReadCondHandleKey< TileSamplingFraction > m_samplingFractionKey
Name of TileSamplingFraction in condition store.
std::vector< std::string > m_hitVectorNames
static const int N_MBTS_CELLS
int e4pr_index(int phi) const
virtual StatusCode mergeEvent(const EventContext &ctx) override final
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number generator engine to use.
Gaudi::Property< std::string > m_randomStreamName
Random Stream Name.
void mergeExtraHitToChannelHit(TileHit *extraHit, TileHit *channelHit) const
ServiceHandle< PileUpMergeSvc > m_mergeSvc
StatusCode commitContainers(const EventContext &ctx, std::unique_ptr< TileHitNonConstContainer > &hits, std::unique_ptr< TileHitNonConstContainer > &hits_DigiHSTruth, SG::OwnershipPolicy ownPolicy) const
void processHitVectorForOverlay(const TileHitVector *inputHits, std::unique_ptr< TileHitNonConstContainer > &hits, int &nHit, double &eHitTot) const
StringArrayProperty m_inputKeys
vector with the names of TileHitVectors to use
void processHitVectorWithoutPileUp(const TileHitVector *inputHits, int &nHit, double &eHitTot, TileHitNonConstContainer *hitCont, CLHEP::HepRandomEngine *engine) const
const TileID * m_tileID
Pointer to TileID helper.
std::vector< std::unique_ptr< TileHit > > m_allHits_DigiHSTruth
vector for all TileHits
const TileHWID * m_tileHWID
Pointer to TileID helper.
Gaudi::Property< double > m_deltaT
minimal time granularity for TileHit
Gaudi::Property< double > m_maxHitTime
all sub-hits with time above m_maxHitTime will be ignored
SG::ReadHandleKeyArray< TileHitVector > m_hitVectorKeys
bool m_run2
if true => RUN2 geometry with E4' and merged E1
Gaudi::Property< bool > m_mergeMultipleHitsInChannel
Gaudi::Property< bool > m_pileUp
if true => pileup mode is activated
void findAndMergeE1(TileHitCollection *coll, int frag_id, TileHitNonConstContainer *hitCont) const
SG::WriteHandleKey< TileHitContainer > m_hitContainerKey
const TileCablingService * m_cabling
Gaudi::Property< int > m_photoElectronStatistics
photoelectron statistics type: 0 - Poisson, 1 - "new" Poisson + Gauss, 2 - Poisson->Gauss
std::vector< std::unique_ptr< TileHit > > m_allHits
vector for all TileHits
static const int E4_N_PHI
Gaudi::Property< bool > m_usePhotoStatistics
StatusCode initialize() override final
std::vector< bool > m_E1merged
static const int N_E4PRIME_CELLS
ServiceHandle< TileCablingSvc > m_cablingSvc
Gaudi::Property< int > m_timeFlag
special options to deal with times of hits for cosmics and TB
const TileTBID * m_tileTBID
Pointer to TileID helper.
virtual StatusCode processBunchXing(int bunchXing, SubEventIterator bSubEvents, SubEventIterator eSubEvents) override final
void putAllHitsInContainer(std::vector< std::unique_ptr< TileHit > > &allHits, std::vector< std::unique_ptr< TileHit > > &allHits_DigiHSTruth, std::unique_ptr< TileHitNonConstContainer > &hits, std::unique_ptr< TileHitNonConstContainer > &hits_DigiHSTruth, SG::OwnershipPolicy ownPolicy) const
virtual StatusCode processAllSubEvents(const EventContext &ctx) override final
Gaudi::Property< bool > m_onlyUseContainerName
Gaudi::Property< double > m_triggerTime
fixed trigger time value (default=0)
std::unique_ptr< TileHitNonConstContainer > m_hits_DigiHSTruth
pointer to hits container
Gaudi::Property< bool > m_doDigiTruth
std::vector< bool > m_MBTSmerged
StatusCode finalize() override final
void setTime(float t, int ind=0)
Set time of ind-th sub-hit in a hit.
float time(int ind=0) const
Return time of ind-th sub-hit.
void scale(float coeff)
Scale energy of all sub-hits in a hit.
Definition TileHit.cxx:117
Identifier pmt_ID(void) const
Return logical ID of the pmt.
float energy(int ind=0) const
Return energy of ind-th sub-hit.
Identifier identify(void) const
Return logical ID of the pmt.
int add(float energy, float time)
Add sub-hit to a given hit.
Definition TileHit.cxx:74
int size(void) const
Return length of energy/time vectors.
std::vector< std::unique_ptr< TileHitCollection > >::iterator iterator
Condition object to keep and provide Tile Calorimeter sampling fraction and number of photoelectrons.
float getNumberOfPhotoElectrons(unsigned int drawerIdx, unsigned int channel) const
Return number of photoelectrons per 1 GeV in Tile Calorimeter scintilator.
float getSamplingFraction(unsigned int drawerIdx, unsigned int channel) const
Return Tile Calorimeter sampling fraction.
OwnershipPolicy
@ OWN_ELEMENTS
this data object owns its elements
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
DataModel_detail::iterator< DVL > remove_if(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end, Predicate pred)
Specialization of remove_if for DataVector/List.
std::list< value_t > type
type of the collection of timed data object
MsgStream & msg
Definition testRead.cxx:32