ATLAS Offline Software
Loading...
Searching...
No Matches
TileHitVecToCntTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 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 IdentifierHash hit_idhash;
283
284 // Loop over hits in this HitVector
285 TileHitVecConstIterator inpItr = inputHits->begin();
286 TileHitVecConstIterator end = inputHits->end();
287
288 for (; inpItr != end; ++inpItr) {
289
290 const TileHit * cinp = &(*inpItr);
291 Identifier hit_id = cinp->identify();
292
293 if (m_tileTBID->is_tiletb(hit_id)) {
294 int side = std::max(0, m_tileTBID->type(hit_id));
295 int phi = m_tileTBID->module(hit_id);
296 int eta = m_tileTBID->channel(hit_id);
297 if (eta < 2)
298 hit_idhash = mbts_index(side, phi, eta);
299 else
300 hit_idhash = e4pr_index(phi);
301 } else {
302 m_tileID->get_hash(hit_id, hit_idhash, &pmt_context);
303 }
304
305 if (hit_idhash >= allHits.size()) {
306 // Seems to be E4pr or MBTS hit in minimum bias while geometry is used without them => skipping
307 continue;
308 }
309
310 double ener = cinp->energy();
311 double time = cinp->time() + SubEvtTimOffset;
312
313 ++nHit;
314 eHitTot += ener;
315
316 std::unique_ptr<TileHit>& pHit = allHits[hit_idhash];
317 std::unique_ptr<TileHit> inValidHit(nullptr);
318 std::unique_ptr<TileHit>& pHit_DigiHSTruth = m_doDigiTruth ? allHits_DigiHSTruth[hit_idhash] : inValidHit;
319
320 if (time < m_maxHitTime){
321 pHit->add(ener, time, m_deltaT);
322 if(m_doDigiTruth){
323 if(isSignal) {
324 pHit_DigiHSTruth->add(ener, time, m_deltaT);
325 } else {
326 pHit_DigiHSTruth->add(0,time, m_deltaT);
327 }
328 }
329 }
330
331 if (msgLvl(MSG::VERBOSE)) {
332 if (pHit->size() > 1 || pHit->energy() != 0.0)
333 msg(MSG::VERBOSE) << " nHit=" << nHit
334 << " id=" << m_tileID->to_string(hit_id, -1)
335 << " ener=" << ener
336 << " time=" << time
337 << " offs=" << SubEvtTimOffset
338 << " double hit" << endmsg;
339 else
340 msg(MSG::VERBOSE) << " nH=" << nHit
341 << " id=" << m_tileID->to_string(hit_id, -1)
342 << " HWid=" << m_tileID->to_string(pHit->pmt_HWID())
343 << " e=" << ener
344 << " time=" << time
345 << " offs=" << SubEvtTimOffset
346 << " new hit" << endmsg;
347 }
348
349 int hitsize = cinp->size();
350 for (int ind = 1; ind < hitsize; ++ind) { // if we have double hits in original hit
351 ener = cinp->energy(ind); // merge all of them with appropriate time
352 time = cinp->time(ind) + SubEvtTimOffset;
353
354 ++nHit;
355 eHitTot += ener;
356
357 if (time < m_maxHitTime){
358 pHit->add(ener, time, m_deltaT);
359 if(m_doDigiTruth){
360 if(isSignal)
361 pHit_DigiHSTruth->add(ener, time, m_deltaT);
362 else
363 pHit_DigiHSTruth->add(0, time, m_deltaT);
364 }
365 }
366
367 if (msgLvl(MSG::VERBOSE))
368 msg(MSG::VERBOSE) << " nHit=" << nHit
369 << " id=" << m_tileID->to_string(hit_id, -1)
370 << " ener=" << ener
371 << " time=" << time
372 << " double hit from single hit" << endmsg;
373 }
374 } // loop over hits in one vector
375 return;
376}
377
378void TileHitVecToCntTool::processHitVectorWithoutPileUp(const TileHitVector* inputHits, int& nHit, double& eHitTot, TileHitNonConstContainer* hitCont, CLHEP::HepRandomEngine * engine) const {
379
380 TileHitVecConstIterator inpItr = inputHits->begin();
381 TileHitVecConstIterator end = inputHits->end();
382
383 //**
384 //* Iterate over hits, creating new TileHits
385 //* Add each TileHit to the TileHitContainer.
386 //**
387
388 switch (m_timeFlag) {
389
390 case 0: {
391 for (; inpItr != end; ++inpItr) {
392 const TileHit * cinp = &(*inpItr);
393 eHitTot += cinp->energy(); // not really correct if TileHit contains vector of energies
394 // but eHitTot is needed for debug purposes only
395 TileHit * pHit = new TileHit(*cinp);
396 hitCont->push_back(pHit);
397 ++nHit;
398
399 if (msgLvl(MSG::VERBOSE)) {
400 int hitsize = cinp->size();
401 double eHit = 0.0;
402 double tHit = 0.0;
403 for (int i = 0; i < hitsize; ++i) {
404 eHit += cinp->energy(i);
405 tHit += cinp->time(i) * cinp->energy(i);
406 }
407 if (eHit > 0.0)
408 tHit /= eHit;
409 else
410 tHit = cinp->time();
411
412 eHitTot += eHit - cinp->energy(); // put total energy instead of first hit energy
413
414 msg(MSG::VERBOSE) << " nHit=" << nHit
415 << " id=" << m_tileID->to_string(cinp->identify(), -1)
416 << " eHit=" << eHit
417 << " tHit=" << tHit
418 << " Copy hit: ener=";
419 for (int i = 0; i < hitsize; ++i)
420 msg(MSG::VERBOSE) << cinp->energy(i) << " ";
421 msg(MSG::VERBOSE) << "time=";
422 for (int i = 0; i < hitsize; ++i)
423 msg(MSG::VERBOSE) << cinp->time(i) << " ";
424 msg(MSG::VERBOSE) << endmsg;
425 }
426 }
427 break;
428 }
429
430 case 1: {
431
432 for (; inpItr != end; ++inpItr) {
433 const TileHit * cinp = &(*inpItr);
434 int size = cinp->size();
435 double eHit = 0.0;
436 for (int i = 0; i < size; ++i) {
437 eHit += cinp->energy(i);
438 }
439 eHitTot += eHit;
440
441 // create hit with total energy at time=0 instead of original one
442 Identifier pmID = cinp->pmt_ID();
443 TileHit * pHit = new TileHit(pmID, eHit, 0.);
444
445 hitCont->push_back(pHit);
446 ++nHit;
447
448 if (msgLvl(MSG::VERBOSE)) {
449 int hitsize = cinp->size();
450 msg(MSG::VERBOSE) << " nHit=" << nHit
451 << " id=" << m_tileID->to_string(cinp->identify(), -1)
452 << " eHit=" << eHit
453 << " tHit=0.0"
454 << " Input hit: ener=";
455 for (int i = 0; i < hitsize; ++i)
456 msg(MSG::VERBOSE) << cinp->energy(i) << " ";
457 msg(MSG::VERBOSE) << "time=";
458 for (int i = 0; i < hitsize; ++i)
459 msg(MSG::VERBOSE) << cinp->time(i) << " ";
460 msg(MSG::VERBOSE) << endmsg;
461 }
462 }
463 break;
464
465 }
466
467 case 2: {
468
469 double avtime = 0.0;
470
471 if (m_useTriggerTime) {
472
473 if (m_triggerTimeKey.empty()) {
474 avtime = m_triggerTime;
475 } else {
477 avtime = cosTriggerTime->time();
478 }
479 ATH_MSG_DEBUG("Trigger time used : " << avtime);
480
481 } else {
482
483 if (m_triggerTime < 0.0) {
484
485 avtime = 1.0e20;
486
487 // loop to find minimal time
488 for (; inpItr != end; ++inpItr) {
489 const TileHit * cinp = &(*inpItr);
490 int size = cinp->size();
491 for (int i = 0; i < size; ++i) {
492 if (cinp->time(i) < avtime) avtime = cinp->time(i);
493 }
494 }
495 ATH_MSG_DEBUG("Minimal time in input event " << avtime);
496 double shift = RandFlat::shoot(engine, m_triggerTime, 0.0);
497 ATH_MSG_DEBUG("Minimal time after random shift " << shift);
498 avtime -= shift; // subtracting negative shift value here
499
500 } else {
501
502 double weight = 0.0;
503
504 // loop to calculate average time
505 for (; inpItr != end; ++inpItr) {
506 const TileHit * cinp = &(*inpItr);
507 int size = cinp->size();
508 for (int i = 0; i < size; ++i) {
509 avtime += cinp->time(i) * cinp->energy(i);
510 weight += cinp->energy(i);
511 }
512 }
513 if (weight > 0.0)
514 avtime /= weight;
515 else
516 avtime = 0.0;
517
518 ATH_MSG_DEBUG("Average time used : " << avtime);
519 }
520
521 // reset iterator to the first hit
522 inpItr = inputHits->begin();
523 }
524
525 for (; inpItr != end; ++inpItr) {
526 const TileHit * cinp = &(*inpItr);
527 TileHit * pHit = new TileHit(*cinp);
528 // subract average time from all time bins in the hit
529 int size = pHit->size();
530 for (int i = 0; i < size; ++i) {
531 pHit->setTime(pHit->time(i) - avtime, i);
532 eHitTot += cinp->energy(i);
533 }
534
535 hitCont->push_back(pHit);
536 ++nHit;
537
538 if (msgLvl(MSG::VERBOSE)) {
539 int hitsize = pHit->size();
540 double eHit = 0.0;
541 double tHit = 0.0;
542 for (int i = 0; i < hitsize; ++i) {
543 eHit += pHit->energy(i);
544 tHit += pHit->time(i) * cinp->energy(i);
545 }
546 if (eHit > 0.0)
547 tHit /= eHit;
548 else
549 tHit = cinp->time(); // just first time
550
551 msg(MSG::VERBOSE) << " nHit=" << nHit
552 << " id=" << m_tileID->to_string(pHit->identify(), -1)
553 << " eHit=" << eHit
554 << " tHit=" << tHit
555 << " Output hit: ener=";
556 for (int i = 0; i < hitsize; ++i)
557 msg(MSG::VERBOSE) << pHit->energy(i) << " ";
558 msg(MSG::VERBOSE) << "time=";
559 for (int i = 0; i < hitsize; ++i)
560 msg(MSG::VERBOSE) << pHit->time(i) << " ";
561 msg(MSG::VERBOSE) << endmsg;
562 }
563 }
564 break;
565 }
566
567 default:
568 ATH_MSG_ERROR("unexpected value m_timeFlag=" << m_timeFlag);
569 break;
570 }
571
572 return;
573}
574
576 , SubEventIterator bSubEvents
577 , SubEventIterator eSubEvents)
578{
579
580 ATH_MSG_DEBUG("Inside TileHitVecToCntTool processBunchXing" << bunchXing);
581 // setFilterPassed(true);
582
583 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
584 CLHEP::HepRandomEngine * engine = rngWrapper->getEngine(Gaudi::Hive::currentContext());
585
586 SubEventIterator iEvt(bSubEvents);
587 if (m_rndmEvtOverlay && bunchXing != 0) iEvt = eSubEvents; // in overlay skip all events except BC=0
588
589 while (iEvt != eSubEvents) {
590 /* zero all counters and sums */
591 int nHit(0);
592 double eHitTot(0.0);
593
594 std::vector<std::string>::const_iterator hitVecNamesItr = m_hitVectorNames.begin();
595 std::vector<std::string>::const_iterator hitVecNamesEnd = m_hitVectorNames.end();
596 for (; hitVecNamesItr != hitVecNamesEnd; ++hitVecNamesItr) {
597
598 const std::string hitVectorName(*hitVecNamesItr);
599
600 if (m_pileUp || m_rndmEvtOverlay) {
601
602 const TileHitVector* inputHits = nullptr;
603 if (!(m_mergeSvc->retrieveSingleSubEvtData(hitVectorName, inputHits, bunchXing, iEvt))){
604 ATH_MSG_ERROR(" Tile Hit container not found for event key " << hitVectorName);
605 }
606
607 const double SubEvtTimOffset(iEvt->time());
608
609 if (m_rndmEvtOverlay) { // overlay code
610 if (fabs(SubEvtTimOffset) > 0.1) {
611 ATH_MSG_ERROR("Wrong time for in-time event: " << SubEvtTimOffset << " Ignoring all hits ");
612 } else {
613 ATH_MSG_DEBUG(" New HitCont. TimeOffset=" << SubEvtTimOffset << ", size =" << inputHits->size());
614 this->processHitVectorForOverlay(inputHits, m_hits, nHit, eHitTot);
615 //if( m_doDigiTruth && iEvt == bSubEvents) this->processHitVectorWithoutPileUp(inputHits, nHit, eHitTot, m_signalHits, engine);
616 }
617 } else if (m_pileUp) { // pileup code
618 bool isSignal = false;
619 if(iEvt == bSubEvents) isSignal = true;
620 this->processHitVectorForPileUp(inputHits, SubEvtTimOffset, m_allHits, m_allHits_DigiHSTruth, nHit, eHitTot, isSignal);
621 }
622 } else { // no PileUp
623 //**
624 //* Get TileHits from TileHitVector
625 //**
626 const TileHitVector * inputHits = nullptr;
627 if (!(m_mergeSvc->retrieveSingleSubEvtData(hitVectorName, inputHits, bunchXing, iEvt))){
628 ATH_MSG_ERROR(" Tile Hit container not found for event key " << hitVectorName);
629 }
630
631 this->processHitVectorWithoutPileUp(inputHits, nHit, eHitTot, m_hits.get(), engine);
632 if(m_doDigiTruth) this->processHitVectorWithoutPileUp(inputHits, nHit, eHitTot, m_hits_DigiHSTruth.get(), engine);
633 } // to pile-up or not
634
635 } // end of the loop over different input hitVectorNames (normal hits and MBTS hits)
636
637 ++iEvt;
638 if (m_rndmEvtOverlay) iEvt = eSubEvents; // in overlay skip all events except fisrt one
639 } // subEvent loop
640
641 ATH_MSG_DEBUG("Exiting processBunchXing in TileHitVecToCntTool");
642
643 return StatusCode::SUCCESS;
644}
645
646StatusCode TileHitVecToCntTool::processAllSubEvents(const EventContext& ctx) {
647 return ((const TileHitVecToCntTool*) this)->processAllSubEvents(ctx);
648}
649
650
651StatusCode TileHitVecToCntTool::processAllSubEvents(const EventContext& ctx) const {
652
653
654 ATH_MSG_DEBUG("TileHitVecToCntTool processAllSubEvents started");
655 typedef PileUpMergeSvc::TimedList<TileHitVector>::type TimedHitContList;
656
658
659 std::vector<std::unique_ptr<TileHit>> allHits;
660 auto hits = std::make_unique<TileHitNonConstContainer>(ownPolicy);
661
662 std::vector<std::unique_ptr<TileHit>> allHits_DigiHSTruth;
663 std::unique_ptr<TileHitNonConstContainer> hits_DigiHSTruth;
664 if (m_doDigiTruth) {
665 hits_DigiHSTruth = std::make_unique<TileHitNonConstContainer>(ownPolicy);
666 }
667 if (m_pileUp) {
668 prepareAllHits(allHits);
669 if (m_doDigiTruth) {
670 prepareAllHits(allHits_DigiHSTruth);
671 }
672 }
673
674 /* zero all counters and sums */
675 int nHit(0);
676 double eHitTot(0.0);
677
678 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
679 rngWrapper->setSeed( name(), ctx );
680 CLHEP::HepRandomEngine * engine = rngWrapper->getEngine(ctx);
681
683 auto hitVectorHandles = m_hitVectorKeys.makeHandles(ctx);
684 for (auto & inputHits : hitVectorHandles) {
685 if (!inputHits.isValid()) {
686 ATH_MSG_ERROR("Input Tile hit container is missing!");
687 return StatusCode::FAILURE;
688 }
689 const double SubEvtTimeOffset(0.0);
690 // get HitVector for this subevent
691 ATH_MSG_DEBUG(" New HitCont. TimeOffset=" << SubEvtTimeOffset << ", size =" << inputHits->size());
692 this->processHitVectorForOverlay(inputHits.cptr(), hits, nHit, eHitTot);
693 if(m_doDigiTruth) this->processHitVectorWithoutPileUp(inputHits.cptr(), nHit, eHitTot, hits_DigiHSTruth.get(), engine);
694 }
695 ATH_CHECK(commitContainers(ctx, hits, hits_DigiHSTruth, ownPolicy));
696 return StatusCode::SUCCESS;
697 }
698
699 for (const auto& hitVectorName : m_hitVectorNames) {
700
701 if (m_pileUp || m_rndmEvtOverlay) {
702 TimedHitContList hitContList;
703 // retrieve list of pairs (time,container) from PileUp service
704 if (!(m_mergeSvc->retrieveSubEvtsData(hitVectorName, hitContList).isSuccess()) || hitContList.size() == 0) {
705 ATH_MSG_WARNING("Could not fill TimedHitContList for hit vector " << hitVectorName);
706 continue; // continue to the next hit vector
707 }
708
709 // loop over this list
710 TimedHitContList::iterator iCont(hitContList.begin());
711 TimedHitContList::iterator iEndCont(hitContList.end());
712
713 if (m_rndmEvtOverlay) { // overlay code
714 if (iCont != iEndCont) { // use only hits from first container
715 // get time for this subevent
716 const double SubEvtTimeOffset(iCont->first.time());
717 if (fabs(SubEvtTimeOffset) > 0.1) {
718 ATH_MSG_ERROR("Wrong time for in-time event: " << SubEvtTimeOffset << " Ignoring all hits ");
719 } else {
720 // get HitVector for this subevent
721 const TileHitVector* inputHits = &(*(iCont->second));
722 ATH_MSG_DEBUG(" New HitCont. TimeOffset=" << SubEvtTimeOffset << ", size =" << inputHits->size());
723 this->processHitVectorForOverlay(inputHits, hits, nHit, eHitTot);
724 if(m_doDigiTruth) this->processHitVectorWithoutPileUp(inputHits, nHit, eHitTot, hits_DigiHSTruth.get(), engine);
725 }
726 }
727 } else if (m_pileUp) { // pileup code
728
729 for (; iCont != iEndCont; ++iCont) {
730 // get time for this subevent
731 const double SubEvtTimeOffset(iCont->first.time());
732 // get HitVector for this subevent
733 const TileHitVector* inputHits = &(*(iCont->second));
734 ATH_MSG_VERBOSE(" New HitCont. TimeOffset=" << SubEvtTimeOffset << ", size =" << inputHits->size());
735 bool isSignal = false;
736 if(iCont == hitContList.begin() ) isSignal = true;
737 this->processHitVectorForPileUp(inputHits, SubEvtTimeOffset, allHits, allHits_DigiHSTruth, nHit, eHitTot, isSignal);
738 }
739 } // loop over subevent list
740 } else { // no PileUp
741
742 //**
743 //* Get TileHits from TileHitVector
744 //**
745 SG::ReadHandle<TileHitVector> inputHits(hitVectorName);
746 if (!inputHits.isValid()) {
747 ATH_MSG_WARNING("Hit Vector "<< hitVectorName << " not found in StoreGate");
748 continue; // continue to the next hit vector
749 }
750 this->processHitVectorWithoutPileUp(inputHits.cptr(), nHit, eHitTot, hits.get(), engine);
751 if(m_doDigiTruth) this->processHitVectorWithoutPileUp(inputHits.cptr(), nHit, eHitTot, hits_DigiHSTruth.get(), engine);
752 }
753
754 } // end of the loop over different input hitVectorNames (normal hits and MBTS hits)
755
756 if (m_pileUp) {
757 putAllHitsInContainer(allHits, allHits_DigiHSTruth, hits, hits_DigiHSTruth, ownPolicy);
758 }
759
760 ATH_CHECK(commitContainers(ctx, hits, hits_DigiHSTruth, ownPolicy));
761
762 return StatusCode::SUCCESS;
763}
764
765void TileHitVecToCntTool::putAllHitsInContainer(std::vector<std::unique_ptr<TileHit>>& allHits,
766 std::vector<std::unique_ptr<TileHit>>& allHits_DigiHSTruth,
767 std::unique_ptr<TileHitNonConstContainer>& hits,
768 std::unique_ptr<TileHitNonConstContainer>& hits_DigiHSTruth,
769 SG::OwnershipPolicy ownPolicy) const {
770
771 std::vector<std::unique_ptr<TileHit>>::iterator iHit = allHits.begin();
772 std::vector<std::unique_ptr<TileHit>>::iterator lastHit = allHits.end();
773 std::vector<std::unique_ptr<TileHit>>::iterator iHit_DigiHSTruth = allHits_DigiHSTruth.begin();
774
775 int nHitUni = 0;
776 double eHitInTime = 0.0;
777
778 ATH_MSG_DEBUG("Hits being stored in container");
779
780 std::function<TileHit*(std::unique_ptr<TileHit>&)> getOrRelease(&std::unique_ptr<TileHit>::get);
781 if (ownPolicy == SG::OWN_ELEMENTS) getOrRelease = &std::unique_ptr<TileHit>::release;
782
783 for (; iHit != lastHit; ++iHit) {
784 std::unique_ptr<TileHit>& hit = (*iHit);
785 if (hit->size() > 1 || hit->energy() != 0.0) { // hit exists
786 eHitInTime += hit->energy();
787 hits->push_back(getOrRelease(hit));
788 if(m_doDigiTruth) hits_DigiHSTruth->push_back(getOrRelease((*iHit_DigiHSTruth)));
789 ++nHitUni;
790 }
791 if(m_doDigiTruth) ++iHit_DigiHSTruth;
792 }
793
794 ATH_MSG_DEBUG(" nHitUni=" << nHitUni << " eHitInTime="<< eHitInTime);
795}
796
797StatusCode TileHitVecToCntTool::commitContainers(const EventContext& ctx,
798 std::unique_ptr<TileHitNonConstContainer>& hits,
799 std::unique_ptr<TileHitNonConstContainer>& hits_DigiHSTruth,
800 SG::OwnershipPolicy ownPolicy) const {
801
802 ATH_MSG_DEBUG("Entering commitContainers");
803
804 if (!m_pileUp) {
807 if (m_doDigiTruth) {
808 findAndMergeMultipleHitsInChannel(hits_DigiHSTruth);
809 }
810 }
811 }
812
813 if (m_run2plus) {
814 // Merge MBTS and E1 where it is needed.
815
816 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
817 int frag_id = coll->identify();
818 IdentifierHash frag_hash = m_fragHashFunc(frag_id);
819 if (m_E1merged[frag_hash])
820 findAndMergeE1(coll.get(), frag_id, hits.get());
821 else if (m_MBTSmerged[frag_hash]) findAndMergeMBTS(coll.get(), frag_id, hits.get());
822 }
823 if(m_doDigiTruth){
824 TileHitNonConstContainer::iterator collIt = hits_DigiHSTruth->begin();
825 TileHitNonConstContainer::iterator endcollIt = hits_DigiHSTruth->end();
826
827 for (; collIt != endcollIt; ++collIt) {
828 int frag_id = (*collIt)->identify();
829 IdentifierHash frag_hash = m_fragHashFunc(frag_id);
830 if (m_E1merged[frag_hash]) findAndMergeE1((*collIt).get(), frag_id, hits_DigiHSTruth.get());
831 else if (m_MBTSmerged[frag_hash]) findAndMergeMBTS((*collIt).get(), frag_id, hits_DigiHSTruth.get());
832 }
833 }
834 }
835
836 //photoelectron statistics.
837 //loop over all hits in TileHitContainer and take energy deposited in certain period of time
838 //std::vector<std::string>::const_iterator hitVecNamesEnd = m_hitVectorNames.end();
839
840 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
841 CLHEP::HepRandomEngine * engine = rngWrapper->getEngine(ctx);
842
844 ATH_CHECK( samplingFraction.isValid() );
845
846 TileHitNonConstContainer::iterator collIt_DigiHSTruth;
847 TileHitNonConstContainer::iterator endColl_DigiHSTruth;
848 if(m_doDigiTruth) {
849 collIt_DigiHSTruth = hits_DigiHSTruth->begin();
850 endColl_DigiHSTruth = hits_DigiHSTruth->end();
851 }
852
853 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
854 TileHitCollection* coll_DigiHSTruth;
855 TileHitCollection::iterator hitItr_DigiHSTruth;
856 TileHitCollection::iterator hitEnd_DigiHSTruth;
857 if(m_doDigiTruth) {
858 coll_DigiHSTruth = (*collIt_DigiHSTruth).get();
859 hitItr_DigiHSTruth = coll_DigiHSTruth->begin();
860 hitEnd_DigiHSTruth = coll_DigiHSTruth->end();
861 }
862
863 HWIdentifier drawer_id = m_tileHWID->drawer_id(coll->identify());
864 int ros = m_tileHWID->ros(drawer_id);
865 int drawer = m_tileHWID->drawer(drawer_id);
866 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
867
868 for (TileHit* pHit : *coll) {
869 double ehit = 0.0;
870 int hitsize = pHit->size();
871 for (int i = 0; i < hitsize; ++i) {
872 double thit = pHit->time(i);
873 if (fabs(thit) < m_photoStatisticsWindow) ehit += pHit->energy(i);
874 }
875
876 Identifier pmt_id = pHit->pmt_ID();
877 //HWIdentifier channel_id = (*hitItr)->pmt_HWID();
878 // for gap/crack scintillators
879 if (m_tileID->sample(pmt_id) == 3) {
880 pmt_id = m_tileID->pmt_id(m_tileID->cell_id(pmt_id), 0);
881 //channel_id = m_cabling->s2h_channel_id(pmt_id);
882 }
883
884 double scaleFactor = 1.0;
886 scaleFactor = applyPhotoStatistics(ehit, pmt_id, engine, *samplingFraction, drawerIdx);
887 pHit->scale(scaleFactor);
888 }
889
890 if(m_doDigiTruth){
891 TileHit *pHit_DigiHSTruth = (*hitItr_DigiHSTruth);
892 pHit_DigiHSTruth->scale(scaleFactor);
893
894 ++hitItr_DigiHSTruth;
895 }
896 }
897
898 if(m_doDigiTruth) ++collIt_DigiHSTruth;
899 }
900
901
902 /* Register the set of TileHits to the event store. */
903 auto hitCont = std::make_unique<TileHitContainer>(false, ownPolicy);
904 size_t hashId = 0;
905 for (std::unique_ptr<TileHitCollection>& coll : *hits ) {
906 CHECK(hitCont->addCollection (coll.release(), hashId++));
907 }
908
910 ATH_CHECK( hitContainer.record(std::move(hitCont)) );
911
912 ATH_MSG_DEBUG("TileHit container registered to the TES with name" << m_hitContainerKey.key());
913
914 if(m_doDigiTruth){
915 auto hitCont_DigiHSTruth = std::make_unique<TileHitContainer>(false, ownPolicy);
916 size_t hashId_DigiHSTruth = 0;
917 for (std::unique_ptr<TileHitCollection>& coll : *hits_DigiHSTruth ) {
918 ATH_CHECK(hitCont_DigiHSTruth->addCollection (coll.release(), hashId_DigiHSTruth++));
919 }
920
922 ATH_CHECK( hitContainer_DigiHSTruth.record(std::move(hitCont_DigiHSTruth)) );
923 }
924
925 ATH_MSG_DEBUG("Exiting mergeEvent in TileHitVecToCntTool");
926 return StatusCode::SUCCESS;
927}
928
929
930StatusCode TileHitVecToCntTool::mergeEvent(const EventContext &ctx) {
932 if (m_pileUp) {
933 ownPolicy = SG::VIEW_ELEMENTS;
935 }
936 return commitContainers(ctx, m_hits, m_hits_DigiHSTruth, ownPolicy);
937}
938
940
941 ATH_MSG_DEBUG("Finalizing TileHitVecToCntTool");
942
943 ATH_MSG_DEBUG("TileHitVecToCntTool finalized");
944
945 return StatusCode::SUCCESS;
946
947}
948
949double TileHitVecToCntTool::applyPhotoStatistics(double energy, Identifier pmt_id, CLHEP::HepRandomEngine* engine,
950 const TileSamplingFraction* samplingFraction, int drawerIdx) const {
951
952 int channel = m_tileHWID->channel(m_cabling->s2h_channel_id(pmt_id));
953 // take number of photoelectrons per GeV divide by 1000 to go to MeV
954 // and multiply by inverted sampling fraction (about 36, depends on G4 version, sampling and eta)
955 // to get number of photoelectrons per 1 MeV energy in scintillator
956 float nPhotoElectrons = samplingFraction->getNumberOfPhotoElectrons(drawerIdx, channel)
957 / (Gaudi::Units::GeV / Gaudi::Units::MeV) * samplingFraction->getSamplingFraction(drawerIdx, channel);
958
959 nPhotoElectrons = std::round(nPhotoElectrons * 1000) / 1000;
960
961 double pe = energy * nPhotoElectrons;
962 double pe_scale = 1., RndmPois = 1.;
963
965 case 2:
966 if (pe > 20.0) {
967 RndmPois = std::max(0.0, RandGaussQ::shoot(engine, pe, sqrt(pe))); // FIXME CLHEP::RandGaussZiggurat is faster and more accurate.
968 pe_scale = RndmPois / pe;
969 } else { // pe<=20
970
971 if (pe > 0.) {
972 double singleMEAN = 1.0; //Parameterization of monoelectron spectra
973 double singleSIGMA = 1.0;
974 RndmPois = RandPoissonT::shoot(engine, pe);
975
976 if (RndmPois > 0) {
977 pe_scale = 0;
978 for (int i = 0; i < RndmPois; i++)
979 pe_scale += 1 / (1.08332) * std::max(0., RandGaussQ::shoot(engine, singleMEAN, singleSIGMA)); // FIXME CLHEP::RandGaussZiggurat is faster and more accurate.
980
981 pe_scale /= RndmPois;
982 } else
983 pe_scale = 0; //RndmPois==0
984 }
985 }
986 break;
987
988 case 0:
989 if (pe > 0.0) {
990 RndmPois = RandPoissonT::shoot(engine, pe);
991 pe_scale = RndmPois / pe;
992 }
993 break;
994
995 case 1:
996 if (pe > 0.0) {
997 if (pe > 10.0) {
998 RndmPois = std::max(0.0, RandGaussQ::shoot(engine, pe, sqrt(pe))); // FIXME CLHEP::RandGaussZiggurat is faster and more accurate.
999 } else {
1000 int nn = std::max(10, (int) (pe * 10.0));
1001 double * ProbFunc = new double[nn];
1002 ProbFunc[0] = exp(-pe);
1003 for (int i = 1; i < nn; ++i) {
1004 ProbFunc[i] = ProbFunc[i - 1] * pe / i;
1005 }
1006 RandGeneral* RandG = new RandGeneral(ProbFunc, nn, 0);
1007 RndmPois = RandG->shoot(engine) * nn;
1008 //here RndmPois is continuously distributed random value obtained from Poisson
1009 //distribution by approximation.
1010 delete RandG;
1011 delete[] ProbFunc;
1012 }
1013 pe_scale = RndmPois / pe;
1014 }
1015 break;
1016 } //end switch(m_PhElStat)
1017
1018 ATH_MSG_VERBOSE( "PhotoElec: id=" << m_tileID->to_string(pmt_id,-1)
1019 << " totEne=" << energy
1020 << ", numPhElec=" << nPhotoElectrons
1021 << ", pe=" << pe
1022 << ", rndmPoisson=" << RndmPois
1023 << ", pe_scale=" << pe_scale);
1024
1025 return pe_scale;
1026}
1027
1028
1030 int module = frag_id & 0x3F;
1031
1032 TileHitCollection::iterator hitIt = coll->begin();
1033 TileHitCollection::iterator endHitIt = coll->end();
1034
1035 TileHitCollection::iterator fromHitIt = coll->end();
1036 TileHit* toHit(0);
1037
1038 for (; hitIt != endHitIt; ++hitIt) {
1039 Identifier pmt_id = (*hitIt)->pmt_ID();
1040 if (m_tileID->tower(pmt_id) == E1_TOWER && m_tileID->sample(pmt_id) == TileID::SAMP_E) {
1041 if (module == m_tileID->module(pmt_id)) {
1042 toHit = *hitIt;
1043 } else {
1044 fromHitIt = hitIt; // need iterator to delete this hit later.
1045 }
1046 }
1047 }
1048
1049 if (fromHitIt != coll->end()) {
1050 ATH_MSG_VERBOSE("Found TileHit (E1 cell) for merging [" << m_tileID->to_string((*fromHitIt)->pmt_ID(), -1)
1051 << "] in module: " << module);
1052 bool isToHitNew = false;
1053 if (toHit == 0) {
1054 int side = m_tileID->side((*fromHitIt)->pmt_ID());
1055 Identifier to_pmt_id = m_tileID->pmt_id(TileID::GAPDET, side, module, E1_TOWER, TileID::SAMP_E, 0);
1056 toHit = new TileHit(to_pmt_id);
1057 isToHitNew = true;
1058 ATH_MSG_VERBOSE("New TileHit (E1 cell) for merging added Id: " << m_tileID->to_string(toHit->pmt_ID(), -1) );
1059 } else {
1060 ATH_MSG_VERBOSE("Found TileHit (E1 cell) for merging Id: " << m_tileID->to_string(toHit->pmt_ID(), -1) );
1061 }
1062
1063 ATH_MSG_DEBUG( "TileHit (E1 cell) Id: " << m_tileID->to_string((*fromHitIt)->pmt_ID(), -1)
1064 << " will be merged to " << m_tileID->to_string(toHit->pmt_ID(), -1) );
1065
1066 if (msgLvl(MSG::VERBOSE)) {
1067 msg(MSG::VERBOSE) << "Before merging (E1 cell) => " << (std::string) (**fromHitIt) << endmsg;
1068 msg(MSG::VERBOSE) << "Before merging (E1 cell) => " << (std::string) (*toHit) << endmsg;
1069 }
1070
1071 toHit->add(*fromHitIt, 0.1);
1072
1073 if (msgLvl(MSG::VERBOSE)) {
1074 msg(MSG::VERBOSE) << "After merging (E1 cell) => " << (std::string) (*toHit) << endmsg;
1075 msg(MSG::VERBOSE) << "TileHit to be deleted Id (E1 cell): " << m_tileID->to_string((*fromHitIt)->pmt_ID(), -1) << endmsg;
1076 }
1077
1078 coll->erase(fromHitIt);
1079
1080 if (isToHitNew) {
1081 hitCont->push_back(toHit);
1082 }
1083 }
1084}
1085
1086
1088 int module = frag_id & 0x3F;
1089
1090 TileHitCollection::iterator hitIt = coll->begin();
1091 TileHitCollection::iterator endHitIt = coll->end();
1092
1093 TileHitCollection::iterator fromHitIt = coll->end();
1094 TileHit* toHit(0);
1095
1096 for (; hitIt != endHitIt; ++hitIt) {
1097 Identifier pmt_id = (*hitIt)->pmt_ID();
1098 if (m_tileTBID->is_tiletb(pmt_id)) {
1099 if (m_tileTBID->phi(pmt_id) % 2 == 0) {
1100 toHit = *hitIt;
1101 } else {
1102 fromHitIt = hitIt; // need iterator to delete this hit later.
1103 }
1104 }
1105 }
1106
1107 if (fromHitIt != coll->end()) {
1108 ATH_MSG_VERBOSE("Found TileHit (MBTS) for merging [" << m_tileTBID->to_string((*fromHitIt)->pmt_ID(), 0)
1109 << "] in module: " << module);
1110 bool isToHitNew = false;
1111 if (toHit == 0) {
1112 int side = m_tileTBID->side((*fromHitIt)->pmt_ID());
1113 int phi = m_tileTBID->phi((*fromHitIt)->pmt_ID()) - 1;
1114 Identifier to_pmt_id = m_tileTBID->channel_id(side, phi, 1);
1115 toHit = new TileHit(to_pmt_id);
1116 isToHitNew = true;
1117 ATH_MSG_VERBOSE("New TileHit (MBTS) for merging added Id: " << m_tileTBID->to_string(toHit->pmt_ID(), 0) );
1118 } else {
1119 ATH_MSG_VERBOSE("Found TileHit (MBTS) for merging Id: " << m_tileTBID->to_string(toHit->pmt_ID(), 0) );
1120 }
1121
1122 ATH_MSG_DEBUG( "TileHit (MBTS) Id: " << m_tileTBID->to_string((*fromHitIt)->pmt_ID(), 0)
1123 << " will be merged to " << m_tileTBID->to_string(toHit->pmt_ID(), 0) );
1124
1125 if (msgLvl(MSG::VERBOSE)) {
1126 msg(MSG::VERBOSE) << "Before merging (MBTS) => " << (std::string) (**fromHitIt) << endmsg;
1127 msg(MSG::VERBOSE) << "Before merging (MBTS) => " << (std::string) (*toHit) << endmsg;
1128 }
1129
1130 toHit->add(*fromHitIt, 0.1);
1131
1132 if (msgLvl(MSG::VERBOSE)) {
1133 msg(MSG::VERBOSE) << "After merging (MBTS) => " << (std::string) (*toHit) << endmsg;
1134 msg(MSG::VERBOSE) << "TileHit to be deleted Id (MBTS): "
1135 << m_tileTBID->to_string((*fromHitIt)->pmt_ID(), 0) << endmsg;
1136 }
1137
1138 coll->erase(fromHitIt);
1139
1140 if (isToHitNew) {
1141 hitCont->push_back(toHit);
1142 }
1143 }
1144}
1145
1146void TileHitVecToCntTool::findAndMergeMultipleHitsInChannel(std::unique_ptr<TileHitNonConstContainer>& hitCont) const {
1147 for (std::unique_ptr<TileHitCollection>& coll : *hitCont) {
1148
1149 int frag_id = coll->identify();
1150 int module = frag_id & 0x3F;
1151 IdentifierHash frag_hash = m_fragHashFunc(frag_id);
1152 std::vector<TileHit*> hits(48, nullptr);
1153 std::vector<std::unique_ptr<TileHit>> otherModuleHits;
1154 coll->erase(std::remove_if(coll->begin(), coll->end(),
1155 [this, &hits, &otherModuleHits, module, frag_hash] (TileHit* hit) {
1156 Identifier pmt_id = hit->pmt_ID();
1157 int channel = m_tileHWID->channel(hit->pmt_HWID());
1158 TileHit* channelHit = hits[channel];
1159 if (channelHit) {
1160 mergeExtraHitToChannelHit(hit, channelHit);
1161 return true;
1162 } else if (m_run2plus // Special case for merged E1 and MBTS in Run 2+ geometries, which will be merged finally correctly later
1163 && ((m_E1merged[frag_hash] && m_tileID->module(pmt_id) != module
1164 && m_tileID->tower(pmt_id) == E1_TOWER && m_tileID->sample(pmt_id) == TileID::SAMP_E) // Merged E1 in Run 2+ from other module
1165 || (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
1166 otherModuleHits.push_back(std::make_unique<TileHit>(*hit));
1167 return true;
1168 } else {
1169 hits[channel] = hit;
1170 return false;
1171 }}),
1172 coll->end());
1173
1174 for (std::unique_ptr<TileHit>& hit : otherModuleHits) {
1175 int channel = m_tileHWID->channel(hit->pmt_HWID());
1176 TileHit* channelHit = hits[channel];
1177 if (channelHit) {
1178 mergeExtraHitToChannelHit(hit.get(), channelHit);
1179 } else {
1180 hits[channel] = hit.get();
1181 coll->push_back(std::move(hit));
1182 }
1183 }
1184 }
1185}
1186
1188
1189 ATH_MSG_DEBUG("Found extra hit for channel Id: "
1190 << m_tileID->to_string(extraHit->pmt_ID(), -1) << ", will be merged to "
1191 << m_tileID->to_string(channelHit->pmt_ID(), -1));
1192 ATH_MSG_VERBOSE("Before merging => " << (std::string) (*extraHit));
1193 ATH_MSG_VERBOSE("Before merging => " << (std::string) (*channelHit));
1194
1195 channelHit->add(extraHit, 0.1);
1196
1197 ATH_MSG_VERBOSE("After merging => " << (std::string) (*channelHit));
1198}
1199
1200
1201void TileHitVecToCntTool::prepareAllHits(std::vector<std::unique_ptr<TileHit>>& allHits) const {
1202
1205 allHits.reserve(nHits);
1206
1207 Identifier hit_id;
1208 IdContext pmt_context = m_tileID->pmt_context();
1209 for (int i = 0; i < m_mbtsOffset; ++i) {
1210 m_tileID->get_id((IdentifierHash) i, hit_id, &pmt_context);
1211 allHits.emplace_back(std::make_unique<TileHit>(hit_id, 0., 0.));
1212 allHits.back()->reserve(71); // reserve max possible size for pileup
1213 }
1214
1215 allHits.resize(allHits.size() + N_MBTS_CELLS);
1216 for (int side = 0; side < N_SIDE; ++side) {
1217 for (int phi = 0; phi < N_PHI; ++phi) {
1218 for (int eta = 0; eta < N_ETA; ++eta) {
1219 int mbtsIndex = mbts_index(side, phi, eta);
1220 hit_id = m_tileTBID->channel_id((side > 0) ? 1 : -1, phi, eta);
1221 allHits[mbtsIndex] = std::make_unique<TileHit>(hit_id, 0., 0.);
1222 allHits[mbtsIndex]->reserve(71); // reserve max possible size for pileup
1223 }
1224 }
1225 }
1226 if (m_run2) {
1227 allHits.resize(allHits.size() + N_E4PRIME_CELLS);
1228 for (int phi = 0; phi < E4_N_PHI; ++phi) {
1229 int e4prIndex = e4pr_index(phi);
1230 hit_id = m_tileTBID->channel_id(E4_SIDE, phi, E4_ETA);
1231 allHits[e4prIndex] = std::make_unique<TileHit>(hit_id, 0., 0.);
1232 allHits[e4prIndex]->reserve(71); // reserve max possible size for pileup
1233 }
1234 }
1235}
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
static const uint32_t nHits
if(pathvar)
Handle class for recording to StoreGate.
size_t size() const
Number of registered mappings.
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