ATLAS Offline Software
Loading...
Searching...
No Matches
TileCellBuilderFromHit.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5
6// Tile includes
19
20// Calo includes
23#include "CaloDetDescr/CaloDetDescrElement.h"
26
27// Atlas includes
32
35
36// access all Hits inside container
39
40
41//CLHEP includes
42#include <CLHEP/Random/Randomize.h>
43#include <CLHEP/Units/SystemOfUnits.h>
44#include <cmath>
45
46
47#ifndef ATHENAHIVE
48#define USE_TILECELLS_DATAPOOL
49#endif
50
51#ifdef USE_TILECELLS_DATAPOOL
52#define NEWTILECELL tileCellsP.nextElementPtr
53#else
54#define NEWTILECELL new TileCell
55#endif
56
57
58using CLHEP::RandGaussQ;
59using CLHEP::MeV;
60
61// uncomment line below for debug output
62// #define ALLOW_DEBUG_COUT 1
63
64static const InterfaceID IID_ITileCellBuilderFromHit("TileCellBuilderFromHit", 1, 0);
65
69
70//Constructor
71TileCellBuilderFromHit::TileCellBuilderFromHit(const std::string& type, const std::string& name,
72 const IInterface* parent)
73 : base_class(type, name, parent)
74 , m_eneForTimeCut(35. * MeV) // keep time only for cells above 70 MeV (more than 35 MeV in at least one PMT to be precise)
75 , m_eneForTimeCutMBTS(0.03675) // the same cut for MBTS, but in pC, corresponds to 3 ADC counts or 35 MeV
76 , m_qualityCut(254) // cut on overflow in quality (if quality is 255 - assume that channel is bad)
77 , m_maxTime (25.)
78 , m_minTime(-25.)
79 , m_maskBadChannels(false)
80 , m_noiseSigma(20.*MeV)
82 , m_RUN2(false)
83 , m_RUN2plus(false)
84 , m_E1_TOWER(10)
85{
86 declareInterface<TileCellBuilderFromHit>( this );
87
88 //memset(m_drawerRunStatus, 0, sizeof(m_drawerRunStatus));
89 //memset(m_eventErrorCounter, 0, sizeof(m_eventErrorCounter));
90
91 // never set energy to zero, but set it to some small number
92 // this will help TopoCluster to assign proper weight to the cell if needed
93 m_zeroEnergy = 0.5 * MeV; // half a MeV in both PMTs i.e. one MeV in a cell
94
95 // Noise Sigma
96 declareProperty("NoiseSigma",m_noiseSigma);
97
98 // Maximum and minimum time for a cell to be included:
99 declareProperty("MaxTime", m_maxTime);
100 declareProperty("MinTime", m_minTime);
101
102 // put zero energy in bad channels and recover from single-channel failure using second PMT is a cell
103 declareProperty("maskBadChannels", m_maskBadChannels);
104
105 // PMT energy will be set to this value if channel is bad
106 declareProperty("BadChannelZeroEnergy", m_zeroEnergy);
107 // PMT with energy above cut will preserve time info in ESD
108 declareProperty("EneForTimeCut", m_eneForTimeCut);
109 declareProperty("EneForTimeCutMBTS", m_eneForTimeCutMBTS);
110 // PMT with quality greater than this cut will be masked
111 declareProperty("QualityCut", m_qualityCut);
112}
113
119
124
125 // retrieve MBTS and Tile detector manager, TileID helper and TileIfno from det store
126 // retrieve MBTS and Tile detector manager, TileID helper and TileIfno from det store
127 if (m_MBTSContainerKey.empty()) {
128 m_mbtsMgr = nullptr;
129 } else {
130
131 ATH_CHECK( m_MBTSContainerKey.initialize() );
132 ATH_MSG_INFO( "Storing MBTS cells in " << m_MBTSContainerKey.key() );
133
134 if (detStore()->retrieve(m_mbtsMgr).isFailure()) {
135 ATH_MSG_WARNING( "Unable to retrieve MbtsDetDescrManager from DetectorStore" );
136 m_mbtsMgr = nullptr;
137 }
138 }
139
140 ATH_CHECK( m_eventInfoKey.initialize() );
141 ATH_CHECK( m_hitContainerKey.initialize() );
142 ATH_CHECK( m_samplingFractionKey.initialize() );
143 ATH_CHECK( m_emScaleKey.initialize() );
144
145 ATH_CHECK( detStore()->retrieve(m_tileMgr) );
146 ATH_CHECK( detStore()->retrieve(m_tileID) );
147 ATH_CHECK( detStore()->retrieve(m_tileTBID) );
148 ATH_CHECK( detStore()->retrieve(m_tileHWID) );
149
150 //=== get TileBadChanTool
151 ATH_CHECK( m_tileBadChanTool.retrieve() );
152
153 //---- retrieve the noise ----------------
154 if (!m_caloNoiseKey.empty()) {
155 ATH_CHECK( m_caloNoiseKey.initialize() );
156 ATH_MSG_INFO( "Reading electronic noise from DB" );
157 } else {
158 ATH_MSG_INFO( "Noise Sigma " << m_noiseSigma << " MeV is selected!" );
159 }
160
161 ATH_CHECK( m_rndmSvc.retrieve());
162 (void) m_rndmSvc->getEngine(this); // get this created early.
163
164 ATH_MSG_INFO( "max time thr " << m_maxTime << " ns" );
165 ATH_MSG_INFO( "min time thr " << m_minTime << " ns" );
166
167 m_E1_TOWER = (m_tileID->cell_hash_max() < 10000) ? 10 : 40;
168
169 ATH_MSG_INFO( "taking hits from '" << m_hitContainerKey.key() << "'" );
170
171 ATH_CHECK( m_cablingSvc.retrieve() );
172 m_cabling = m_cablingSvc->cablingService();
173
174 m_RUN2 = (m_cabling->getCablingType() == TileCablingService::RUN2Cabling);
175 m_RUN2plus = m_cabling->isRun2PlusCabling();
176
177 if (m_RUN2 && !m_E4prContainerKey.empty()) {
178 ATH_CHECK( m_E4prContainerKey.initialize() );
179 ATH_MSG_INFO( "Storing E4' cells in " << m_E4prContainerKey.key() );
180 } else {
181 m_E4prContainerKey = ""; // no E4' container for RUN1
182 }
183
184
185 ATH_MSG_INFO( "TileCellBuilderFromHit initialization completed" );
186
187 return StatusCode::SUCCESS;
188}
189
191
192 ATH_MSG_INFO( "Finalizing" );
193
194 return StatusCode::SUCCESS;
195}
196
198 const EventContext& ctx) const
199{
200 //**
201 //* Get TileHits
202 //**
203
204 TileDrawerEvtStatusArray drawerEvtStatus;
205
207 ATH_CHECK( samplingFraction.isValid() );
208
210
211 if (!hitContainer.isValid()) {
212
213 ATH_MSG_WARNING( " Could not find container " << m_hitContainerKey.key() );
214 ATH_MSG_WARNING( " do not fill CaloCellContainer " );
215
216 } else {
217
218 ATH_MSG_DEBUG( "Container " << m_hitContainerKey.key() << " with TileHits found ");
219
220 std::unique_ptr<TileCellContainer> MBTSCells;
221 if (!m_MBTSContainerKey.empty()) {
222 MBTSCells = std::make_unique<TileCellContainer>(SG::VIEW_ELEMENTS);
223 }
224
225 std::unique_ptr<TileCellContainer> E4prCells;
226 if (!m_E4prContainerKey.empty()) {
227 E4prCells = std::make_unique<TileCellContainer>(SG::VIEW_ELEMENTS);
228 }
229
230 SelectAllObject<TileHitContainer> selAll(hitContainer.cptr());
231 SelectAllObject<TileHitContainer>::const_iterator begin = selAll.begin();
232 SelectAllObject<TileHitContainer>::const_iterator end = selAll.end();
233
234 const CaloNoise* caloNoise = nullptr;
235 if (!m_caloNoiseKey.empty()) {
237 caloNoise = noiseH.cptr();
238 }
239
240 if (begin != end) {
241 ATH_MSG_DEBUG( " Calling build() method for hits from " << m_hitContainerKey.key() );
242 build (caloNoise, drawerEvtStatus, begin, end, theCellContainer,
243 MBTSCells.get(), E4prCells.get(), *samplingFraction);
244 }
245
246 if (!m_MBTSContainerKey.empty()) {
248 ATH_CHECK( MBTSContainer.record(std::move(MBTSCells)) );
249 }
250
251 if (!m_E4prContainerKey.empty()) {
253 ATH_CHECK( E4prContainer.record(std::move(E4prCells)) );
254 }
255
257 //specify that a given calorimeter has been filled
258 if (theCellContainer->hasCalo(caloNum)) {
259 // log << MSG::WARNING << "CaloCellContainer has already been filled with TileCells (caloNum = "
260 // << caloNum << ")" << endreq ;
261 }
262 theCellContainer->setHasCalo(caloNum);
263 }
264
265 //enum EventFlagErrorState { NotSet, Warning, Error };
267 // flag will contain status of a given event
268 // every 4 bits - status of partitions LBA,LBC,EBA,EBC
269 // bits 0-3 - there is a signal above threshold in partitions
270 // bits 4-7 - there are channels with underflow (sample=0) in partition (since rel 17.2.6.4)
271 // bits 8-11 - there are channels with overflow (sample=m_tileInfo->ADCmax()) in partition (since rel 17.2.6.4)
272 // bits 12-15 - there are at least 16 drawers with bad quality in partition
273 // bits 16-19 - maximal length of consecutive bad area (since rel 17.2.6.5)
274 // bits 20-23 - there are at least 16 drawers which are completely masked in partition
275 // bits 24-27 - there are at least 16 drawers which do not send data in partition
276 // bits 28-31 - reserved for global good/warning/bad status
277 // bits 20-27 are also used for module number which gives warning status (since release 17.2.6.5)
278 // in case of warning we are sure that bits which indicates error are not filled
279 unsigned int flag = 0;
280
281 int drConsecMaxMax = 0;
282 int drConsecNum = 0;
283
284 for (int p = 1; p < 5; ++p) {
285 TileDrawerEvtStatus * evt = drawerEvtStatus[p];
286 //TileDrawerRunStatus * run = m_drawerRunStatus[p];
287 int drAbsent = 0;
288 int drMasked = 0;
289 int drConsec = 0;
290 int drConsecMax = 0;
291 int hasBadQ = 0;
292 int hasOver = 0;
293 int hasUnder = 0;
294 int hasSig = 0;
295 for (int d = 0; d < 64; ++d) {
296 if (evt[d].nChannels == 0) {
297 ++drConsec;
298 ++drAbsent;
299 //++(run[d].drawerAbsent);
300 } else if (evt[d].nMaskedChannels >= evt[d].nChannels) {
301 ++drConsec;
302 ++drMasked;
303 //++(run[d].drawerMasked);
304 } else {
305 if (drConsec > drConsecMax) {
306 drConsecMax = drConsec;
307 if (drConsecMax > drConsecMaxMax) {
308 drConsecMaxMax = drConsecMax;
309 drConsecNum = ((p - 1) << 6) | (d - drConsec);
310 }
311 }
312 drConsec = 0;
313 //if (evt[d].nMaskedChannels > 0) {
314 // ++(run[d].channelsMasked);
315 //}
316 if (evt[d].nBadQuality) ++hasBadQ;
317 if (evt[d].nOverflow) ++hasOver;
318 if (evt[d].nUnderflow) ++hasUnder;
319 if (evt[d].nSomeSignal) ++hasSig;
320 }
321 }
322 if (drConsec != 0 && drConsecMax < 64) { // 64th drawer is bad - check transition from 64th to 1st drawer
323 for (int d = 0; d < drConsecMax; ++d) {
324 if (evt[d].nChannels == 0 || evt[d].nMaskedChannels >= evt[d].nChannels) {
325 ++drConsec;
326 } else {
327 break;
328 }
329 }
330 if (drConsec > drConsecMax) {
331 drConsecMax = drConsec;
332 }
333 }
334 unsigned int fl = 0;
335 if (drAbsent > 15) {
336 fl |= 0x01000000;
338 }
339 if (drMasked > 15) {
340 fl |= 0x00100000;
342 }
343 //if (drConsecMax > 1)fl |= 0x00010000; // want to use these bits for length of consecutive area
344 if (hasBadQ > 15) fl |= 0x00001000;
345 if (hasOver) fl |= 0x00000100;
346 if (hasUnder) fl |= 0x00000010;
347 if (hasSig) fl |= 0x00000001;
348
349#ifdef ALLOW_DEBUG_COUT
350 std::cout<<"partition "<<p<<" drAbsent "<<drAbsent<<" drMasked "<<drMasked<<" drConsec "<<drConsecMax
351 <<" hasBadQ "<<hasBadQ<<" hasOver "<<hasOver<<" hasUnder "<<hasUnder<<" hasSig "<<hasSig<<std::endl;
352#endif
353 flag |= fl << (p - 1);
354 }
355
356 // number of consecutively masked modules (if it's > 15 we have error already set)
357 flag |= (std::min(15, drConsecMaxMax) << 16);
358
359 if (drConsecMaxMax > 1 && error < xAOD::EventInfo::Warning) {
360 // setting warning flag
362 // putting starting module number of consecutive bad area
363 // instead of bits which indicates 16 masked or 16 absent modules in partition
364 flag |= (drConsecNum << 20);
365#ifdef ALLOW_DEBUG_COUT
366 std::cout<<"warning in partition " << (drConsecNum>>6)+1 << " for modules "
367 <<(drConsecNum)%64 <<" - " <<(drConsecNum+drConsecMaxMax-1)%64 <<std::endl;
368#endif
369 }
370
371#ifdef ALLOW_DEBUG_COUT
372 std::cout<<"partition flag 0x0"<<std::hex<<flag<<std::dec<<" error "<<error<<std::endl;
373#endif
374
375 //++m_eventErrorCounter[error]; // error index is 0 or 1 or 2 here
376 //++m_eventErrorCounter[3]; // count separately total number of events
377
378 // retrieve EventInfo
380
381 if (eventInfo.isValid()) {
382
383 if (flag != 0) {
384 ATH_MSG_DEBUG( " set eventInfo for Tile for this event to 0x" << MSG::hex << flag << MSG::dec );
385 if (!eventInfo->updateEventFlags(xAOD::EventInfo::Tile, flag)) {
386 ATH_MSG_WARNING( " cannot set eventInfo for Tile " );
387 }
388 }
389
391 ATH_MSG_DEBUG( " set error bits for Tile for this event to " << error );
392 if (!eventInfo->updateErrorState(xAOD::EventInfo::Tile, error)) {
393 ATH_MSG_WARNING( " cannot set error state for Tile " );
394 }
395 }
396
397 }
398 else {
399 ATH_MSG_WARNING( " cannot retrieve EventInfo, will not set Tile information " );
400 }
401
402 // Execution completed.
403 ATH_MSG_DEBUG( "TileCellBuilderFromHit execution completed." );
404
405 return StatusCode::SUCCESS;
406}
407
408//************************************************************************
409void TileCellBuilderFromHit::correctCell(TileCell* pCell, int correction, int pmt, int gain
410 , float ener, float time, unsigned char iqual, unsigned char qbit) const {
411//************************************************************************
412
413// Merge two pmts in one cell if needed
414// and apply corrections
415
416 switch (correction) {
417 case 1: // first pmt for this cell
418 pCell->addEnergy(ener, pmt, gain);
419 pCell->setTime(time); // overwrite time completely
420 pCell->setQuality(iqual, qbit, pmt);
421 pCell->setQuality(0, 0, 1 - pmt);
422 break;
423 case 2: // second pmt for this cell
424 pCell->addEnergy(ener, pmt, gain);
425 pCell->setTime(time, pmt); // calculate average time and timeDiff
426 pCell->setQuality(iqual, qbit, pmt);
427 break;
428 }
429}
430
432 int ros, int drawer, bool count_over
433 , bool good_time, bool good_ener, bool overflow, bool underflow, bool overfit) const {
434
435 ++drawerEvtStatus[ros][drawer].nChannels;
436 // new feature in rel 17.2.7 - count underflows and overflows
437 if (count_over) {
438 if (overflow) ++drawerEvtStatus[ros][drawer].nOverflow;
439 if (underflow) ++drawerEvtStatus[ros][drawer].nUnderflow;
440 }
441#ifdef ALLOW_DEBUG_COUT
442 if (overflow) std::cout << "channel with overflow " << ((count_over)?"":"MBTS") << std::endl;
443 if (underflow) std::cout << "channel with underflow " << ((count_over)?"":"MBTS") << std::endl;
444 if (overfit) std::cout << "channel with corrected overflow " << ((count_over)?"":"MBTS") << std::endl;
445#endif
446
447 unsigned char qbit = (overfit) ? (TileFragHash::FitFilter & TileCell::MASK_ALGO)
449 if (good_time) qbit |= TileCell::MASK_TIME;
450 if (overflow || underflow) qbit |= TileCell::MASK_OVER;
451
452 if (good_ener) {
453 qbit |= TileCell::MASK_AMPL;
454 if (count_over) {
455 ++drawerEvtStatus[ros][drawer].nSomeSignal;
456 }
457 }
458
459 return qbit;
460}
461
462// masking for MBTS with single channel
463bool
465 TileCell* pCell) const
466{
467 Identifier cell_id = pCell->ID();
468
469 HWIdentifier channel_id = m_cabling->s2h_channel_id(cell_id);
470 int ros = m_tileHWID->ros(channel_id);
471 int drawer = m_tileHWID->drawer(channel_id);
472 int channel = m_tileHWID->channel(channel_id);
473 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
474 int gain = pCell->gain1();
475
476 TileBchStatus chStatus = m_tileBadChanTool->getAdcStatus(drawerIdx, channel, gain);
477
478 // check quality first
479 bool bad = ((int) pCell->qual1() > m_qualityCut);
480 if (bad) {
481 ++drawerEvtStatus[ros][drawer].nBadQuality;
482
483 } else {
484 // check bad status in DB
485 bad = chStatus.isBad();
486
487 }
488
489 if (bad) {
490 // only one channel in this cell and it is bad
491 ++drawerEvtStatus[ros][drawer].nMaskedChannels;
492
493 //pCell->setEnergy(m_zeroEnergy,0.0,TileID::LOWGAIN,CaloGain::INVALIDGAIN); // reset energy completely, indicate problem putting low gain
494 //pCell->setTime(0.0); // reset time completely
495 //pCell->setQuality(255,TileCell::MASK_BADCH,0); // reset quality flag for first pmt
496
497 if (gain == CaloGain::INVALIDGAIN) {
498 pCell->setEnergy(0.0, 0.0, TileID::LOWGAIN, CaloGain::INVALIDGAIN); // reset energy completely, indicate problem putting low gain
499 } else {
500 pCell->setEnergy(0.0, 0.0); // reset energy completely without changing the gain
501 }
502 pCell->setTime(-100.0); // reset time to big negative number to distinguish this bad cell from good cells
503 pCell->setQuality(255, (TileCell::MASK_BADCH | (pCell->qbit1() & TileCell::MASK_ALGO)), 0); // reset quality flag for first pmt
504 pCell->setQuality(0, TileCell::MASK_BADCH, 1); // reset quality flag for second pmt
505
506 return true;
507
508 } else if (chStatus.isBadTiming()) {
509 pCell->setTime(0.0); // channel with bad timing - no cell time
510 uint8_t qbit1 = pCell->qbit1() & (~(TileCell::MASK_TIME)); // clear time bit for first pmt
511 pCell->setQuality(pCell->qual1(), qbit1, 0); // update qbits for first pmt
512 }
513
514 return false;
515}
516
517// masking for normal cells
518bool
520 TileCell* pCell, bool single_PMT_C10, bool Ecell) const {
521
522 const CaloDetDescrElement* caloDDE = pCell->caloDDE();
523
524 IdentifierHash hash1 = caloDDE->onl1();
525 IdentifierHash hash2 = caloDDE->onl2();
526
527 int gain1 = pCell->gain1();
528
529 HWIdentifier ch_id1 = m_tileHWID->channel_id(hash1);
530
531 int ros1 = m_tileHWID->ros(ch_id1);
532 int drawer1 = m_tileHWID->drawer(ch_id1);
533 int chan1 = m_tileHWID->channel(ch_id1);
534 int drawerIdx1 = TileCalibUtils::getDrawerIdx(ros1, drawer1);
535 const TileBchStatus& chStatus1 = m_tileBadChanTool->getAdcStatus(drawerIdx1, chan1, (gain1 < 0) ? 1 : gain1);
536
537 // check quality first
538 bool bad1 = ((int) pCell->qual1() > m_qualityCut);
539 if (bad1) {
540 ++drawerEvtStatus[ros1][drawer1].nBadQuality;
541
542 } else {
543 // check bad status in DB
544 bad1 = (gain1 < 0) || chStatus1.isBad();
545
546 }
547
548 if ( Ecell || hash2 == TileHWID::NOT_VALID_HASH) {
549 // gap/crack scintillators with one PMT per cell
550
551 if (bad1) {
552 // only one channel in this cell and it is bad
553 ++drawerEvtStatus[ros1][drawer1].nMaskedChannels;
554
555 if (gain1 == CaloGain::INVALIDGAIN) {
556 pCell->setEnergy(m_zeroEnergy, 0.0, TileID::LOWGAIN, CaloGain::INVALIDGAIN); // reset energy completely, indicate problem putting low gain
557 } else {
558 pCell->setEnergy(m_zeroEnergy, 0.0); // reset energy completely without changing gain
559 }
560 pCell->setTime(0.0); // reset time completely
561 pCell->setQuality(255, (TileCell::MASK_BADCH | (pCell->qbit1() & TileCell::MASK_ALGO)), 0); // reset quality flag for first pmt
562 pCell->setQuality(0, TileCell::MASK_BADCH, 1); // reset quality flag for second pmt
563
564 return true;
565
566 } else if (chStatus1.isBadTiming()) {
567 pCell->setTime(0.0); // channel with bad timing - no cell time
568 uint8_t qbit1 = pCell->qbit1() & (~(TileCell::MASK_TIME)); // clear time bit for first pmt
569 pCell->setQuality(pCell->qual1(), qbit1, 0); // update qbits for first pmt
570 }
571
572 } else { //cell has both PMTs
573
574 int gain2 = pCell->gain2();
575
576 HWIdentifier ch_id2 = m_tileHWID->channel_id(hash2);
577
578 int ros2 = m_tileHWID->ros(ch_id2);
579 int drawer2 = m_tileHWID->drawer(ch_id2);
580 int chan2 = m_tileHWID->channel(ch_id2);
581 int drawerIdx2 = TileCalibUtils::getDrawerIdx(ros2, drawer2);
582 const TileBchStatus& chStatus2 = m_tileBadChanTool->getAdcStatus(drawerIdx2, chan2, (gain2 < 0) ? 1 : gain2);
583
584 // check quality first
585 bool bad2 = ((int) pCell->qual2() > m_qualityCut);
586 if (bad2) {
587 ++drawerEvtStatus[ros2][drawer2].nBadQuality;
588
589 } else {
590 // check bad status in DB
591 bad2 = (gain2 < 0) || chStatus2.isBad();
592
593 }
594
595 if (single_PMT_C10) {
596 // for special C10 disconnected channel might be masked in DB
597 // and energy of good channel is taken twice with correct weight
598 // but if this channel is not masked in DB - set its bad status
599 // equal to bad status of real channel, so that cell is masked correctly
600 // if real channel connected to a cell is bad
601#ifdef ALLOW_DEBUG_COUT
602 static int cnt=0;
603 if (++cnt < 17) {
604 std::cout << "special C10 in " << ((ros2==TileHWID::EXTBAR_POS) ? "EBA" : "EBC")
605 << drawer2+1 << " status " << chan1 << "/" << chan2 << " "
606 << (chStatus1.isBad()?"bad":"good") << "/"
607 << (chStatus2.isBad()?"bad":"good") << "/"
608 << ((m_RUN2plus)?" RUN2+ cabling": "RUN1 cabling")
609 << std::endl;
610 }
611#endif
612 if (chan1 == 4) {
613 if (m_RUN2plus || !chStatus1.isBad()) {
614#ifdef ALLOW_DEBUG_COUT
615 if (cnt < 17) {
616 std::cout << "Ene of chan1 was " << pCell->ene1() << " changing to half of " << pCell->ene2()
617 << " and setting bad1=true" << std::endl;
618 }
619#endif
620 pCell->setEnergy(pCell->ene2()/2., pCell->ene2()/2., gain2, gain2);
621 //bad1 = bad2;
622 bad1 = true;
623 --drawerEvtStatus[ros1][drawer1].nMaskedChannels; // since it's fake masking, decrease counter by 1 in advance
624 }
625 } else {
626 if (m_RUN2plus || !chStatus2.isBad()) {
627#ifdef ALLOW_DEBUG_COUT
628 if (cnt < 17) {
629 std::cout << "Ene of chan2 was " << pCell->ene2() << " changing to half of " << pCell->ene1()
630 << " and setting bad2=true" << std::endl;
631 }
632#endif
633 pCell->setEnergy(pCell->ene1()/2., pCell->ene1()/2., gain1, gain1);
634 //bad2 = bad1;
635 bad2 = true;
636 --drawerEvtStatus[ros2][drawer2].nMaskedChannels; // since it's fake masking, decrease counter by 1 in advance
637 }
638 }
639 }
640 if (bad1 && bad2) {
641 // both channels are bad
642 ++drawerEvtStatus[ros1][drawer1].nMaskedChannels;
643 ++drawerEvtStatus[ros2][drawer2].nMaskedChannels;
644
645 if (gain1 == CaloGain::INVALIDGAIN || gain2 == CaloGain::INVALIDGAIN) {
646 if (gain1 == CaloGain::INVALIDGAIN) gain1 = 0; // this is TileID::LOWGAIN; - commented out to make Coverity happy
647 if (gain2 == CaloGain::INVALIDGAIN) gain2 = 0; // this is TileID::LOWGAIN; - commented out to make Coverity happy
648 pCell->setEnergy(m_zeroEnergy, m_zeroEnergy, gain1, gain2); // reset energy completely, indicate problem putting low gain
649 } else {
650 pCell->setEnergy(m_zeroEnergy, m_zeroEnergy); // reset energy completely without changing gain
651 }
652 pCell->setTime(0.0); // reset time completely
653 pCell->setQuality(255, (TileCell::MASK_BADCH | (pCell->qbit1() & TileCell::MASK_ALGO)), 0); // reset quality flag for first pmt
654 pCell->setQuality(255, (TileCell::MASK_BADCH | (pCell->qbit2() & TileCell::MASK_ALGO)), 1); // reset quality flag for second pmt
655
656 return true;
657
658 } else if (bad1 && !bad2) {
659 // first channel is bad
660 ++drawerEvtStatus[ros1][drawer1].nMaskedChannels;
661
662 float ene2 = pCell->ene2();
663 pCell->setEnergy(ene2, ene2, gain2, gain2); // use energy/gain from second pmt for both pmts
664
665 if (chStatus2.isBadTiming()) {
666 pCell->setTime(0.0); // time in second pmt is bad - no cell time
667 uint8_t qual2 = pCell->qual2();
668 uint8_t qbit2 = pCell->qbit2() & (~(TileCell::MASK_TIME)); // clear time bit for second pmt
669 uint8_t qbit1 = qbit2 | TileCell::MASK_BADCH; // set bad channel bit for first pmt
670 uint8_t qual1 = qual2 + (gain1 - gain2); // if gains are different, qua11 and qual2 will be different
671 if (qual1 > m_qualityCut && gain1 > gain2) qual1 = qual2 - (gain1 - gain2); // new feature in release 17.2
672 pCell->setQuality(qual1, qbit1, 0); // change quality and qbits for first pmt
673 pCell->setQuality(qual2, qbit2, 1); // update qbits for second pmt
674 } else {
675 pCell->setTime(pCell->time2()); // use time from second pmt as cell time
676 pCell->setQuality(pCell->qual2(), (pCell->qbit2() | TileCell::MASK_BADCH), 0); // change quality flag for first pmt
677 }
678
679 return true;
680
681 } else if (!bad1 && bad2) {
682 // second channel is bad
683 ++drawerEvtStatus[ros2][drawer2].nMaskedChannels;
684
685 float ene1 = pCell->ene1();
686 pCell->setEnergy(ene1, ene1, gain1, gain1); // use energy/gain from first pmt for both pmts
687
688 if (chStatus1.isBadTiming()) {
689 pCell->setTime(0.0); // time in first pmt is bad - no cell time
690 uint8_t qual1 = pCell->qual1();
691 uint8_t qbit1 = pCell->qbit1() & (~(TileCell::MASK_TIME)); // clear time bit for first pmt
692 uint8_t qbit2 = qbit1 | TileCell::MASK_BADCH; // set bad channel bit for second pmt
693 uint8_t qual2 = qual1 + (gain2 - gain1); // if gains are different, qua11 and qual2 will be different
694 if (qual2 > m_qualityCut && gain2 > gain1) qual2 = qual1 - (gain2 - gain1); // new feature in release 17.2
695 pCell->setQuality(qual1, qbit1, 0); // update qbits for first pmt
696 pCell->setQuality(qual2, qbit2, 1); // change quality and qbits for second pmt
697 } else {
698 pCell->setTime(pCell->time1()); // use time from first pmt as cell time
699 pCell->setQuality(pCell->qual1(), (pCell->qbit1() | TileCell::MASK_BADCH), 1); // change quality flag for second pmt
700 }
701
702 return true;
703
704 } else {
705
706 if (chStatus1.isBadTiming()) {
707
708 if (chStatus2.isBadTiming()) {
709 pCell->setTime(0.0); // time in both pmts is bad - no cell time
710 uint8_t qbit2 = pCell->qbit2() & (~(TileCell::MASK_TIME)); // clear time bit for second pmt
711 pCell->setQuality(pCell->qual2(), qbit2, 1); // update qbits for second pmt
712 } else {
713 pCell->setTime(pCell->time2()); // use time from second pmt as cell time
714 }
715 uint8_t qbit1 = pCell->qbit1() & (~(TileCell::MASK_TIME)); // clear time bit for first pmt
716 pCell->setQuality(pCell->qual1(), qbit1, 0); // update qbits for first pmt
717
718 } else if (chStatus2.isBadTiming()) {
719
720 pCell->setTime(pCell->time1()); // use time from first pmt as cell time
721 uint8_t qbit2 = pCell->qbit2() & (~(TileCell::MASK_TIME)); // clear time bit for second pmt
722 pCell->setQuality(pCell->qual2(), qbit2, 1); // update qbits for second pmt
723 }
724 }
725
726 }
727
728 return single_PMT_C10;
729}
730
731
732template<class ITERATOR, class COLLECTION>
734 TileDrawerEvtStatusArray& drawerEvtStatus,
735 const ITERATOR & begin, const ITERATOR & end, COLLECTION * coll,
736 TileCellContainer* MBTSCells,
737 TileCellContainer* E4prCells,
738 const TileSamplingFraction* samplingFraction) const
739{
740 static const std::string rngname = name() + "-" + ClassName<COLLECTION>::name();
741 const EventContext& ctx = Gaudi::Hive::currentContext();
742 ATHRNG::RNGWrapper* wrapper = m_rndmSvc->getEngine(this);
743 wrapper->setSeed (rngname, ctx);
744 CLHEP::HepRandomEngine* engine = wrapper->getEngine (ctx);
745
747
748 /* zero all counters and sums */
749 int nTwo = 0;
750 int nCell = 0;
751 int nFake = 0;
752 int nMBTS = 0;
753 int nE4pr = 0;
754 int nChan = 0;
755 float eCh = 0.0;
756 float eCellTot = 0.0;
757 float eMBTSTot = 0.0;
758 float eE4prTot = 0.0;
759 bool EBdrawerPresent[128];
760 memset(EBdrawerPresent, 0, sizeof(EBdrawerPresent));
761#ifdef USE_TILECELLS_DATAPOOL
762 DataPool<TileCell> tileCellsP(5217);
763#endif
764 //**
765 //* Iterate over hits, creating new TileCells (or incrementing
766 //* existing ones). Add each new TileCell to the output collection
767 //**
768
769 bool overflow = false;
770 bool underflow = false;
771 bool overfit = false;
772 float ener_min = (!m_caloNoiseKey.empty()) ? 1.0E-30F : 0.0;
773
774 std::vector<TileCell*> allCells (m_tileID->cell_hash_max(), nullptr);
775 std::vector<TileCell*> MBTSVec;
776 if (MBTSCells) {
777 MBTSVec.resize (NCELLMBTS);
778 }
779 std::vector<TileCell*> E4prVec;
780 if (E4prCells) {
781 E4prVec.resize (NCELLE4PR);
782 }
783
784 for (ITERATOR hitItr = begin; hitItr != end; ++hitItr) {
785
786 const TileHit* pHit = (*hitItr);
787
788 // Get hit id (logical pmt id)
789 Identifier cell_id = pHit->identify();
790
791 double ehit = 0.;
792 double thit = 0.;
793
794 int hitsize = pHit->size();
795 for (int ind = 0; ind < hitsize; ++ind) { // loop over sub-hits
796 float tim = pHit->time(ind);
797 if (m_minTime < tim && tim < m_maxTime) {
798 float ene = pHit->energy(ind);
799 ehit += ene;
800 thit += tim*ene;
801 }
802 }
803
804 float ener = ener_min;
805 float time = 0.;
806 float qual = 0.;
807 int gain = TileID::HIGHGAIN;
808 bool good_time = false;
809 bool non_zero_time = (ehit!=0.0);
810
811 HWIdentifier channel_id = m_cabling->s2h_channel_id(cell_id);
812 int ros = m_tileHWID->ros(channel_id);
813 int drawer = m_tileHWID->drawer(channel_id);
814 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
815 int channel = m_tileHWID->channel(channel_id);
816
817 if (non_zero_time) {
818 time = thit / ehit;
819 // Convert hit energy deposit to cell energy
820 ener = ehit * samplingFraction->getSamplingFraction(drawerIdx, channel);
821 if (ener > 10000. * MeV) { // very simple check - if above 10 GeV assume low gain
822 gain = TileID::LOWGAIN;
823 }
824 good_time = (fabs(time) < 25.);
825 }
826
827 bool MBTS = false, E4pr = false, E1_CELL = false;
828 int section,side,tower,sample,pmt,index;
829
830 // Get logical ID of cell
831 if (m_tileTBID->is_tiletb(cell_id)) {
832
833 pmt = 0;
834 side = m_tileTBID->type(cell_id);
835 int phi = m_tileTBID->module(cell_id);
836 int eta = m_tileTBID->channel(cell_id);
837 if (eta<2) {
838 MBTS = true;
839 index = mbts_index(std::max(0,side),phi,eta);
840 } else {
841 E4pr = true;
843 }
844
845 } else {
846
847 MBTS = false;
848 E4pr = false;
849
850 pmt = m_tileID->pmt(cell_id); // 0 or 1 - first or second PMT of the cell
851
852 cell_id = m_tileID->cell_id(cell_id); // remove pmt field from cell_id
853 index = m_tileID->cell_hash(cell_id);
854
855 section = m_tileID->section(cell_id);
856 side = m_tileID->side(cell_id);
857 drawer = m_tileID->module(cell_id);
858 tower = m_tileID->tower(cell_id);
859 sample = m_tileID->sample(cell_id);
860
861 // instead of using cabling (which might be wrong for upgrade geometry
862 // try to figure out ros/drawer/channel
863 ros = ( TileID::POSITIVE == side ) ? 1 : 2;
864 if ( TileID::BARREL != section ) ros += 2;
865 else if (tower == 0 && sample == TileID::SAMP_D && pmt == 1) ros = 2; // Cell D0, second PMT in LBC
866 channel = -1; // don't know channel
867 E1_CELL = (section == TileID::GAPDET && sample == TileID::SAMP_E && tower == m_E1_TOWER);
868 }
869
870 ++nChan;
871 eCh += ener;
872
873 if (E4pr) { // E4' cells
874
875 if (E4prCells) { // do something with them only if contaier existst
876 ++nE4pr;
877
878 eE4prTot += ener;
879 unsigned char iqual = iquality(qual);
880 // for E4' cell qbit use only non_zero_time flag and check that energy is above standatd energy threshold in MeV
881 unsigned char qbit = qbits(drawerEvtStatus,
882 ros, drawer, true, non_zero_time, (fabs(ener) > m_eneForTimeCut)
883 , overflow, underflow, overfit);
884 CaloGain::CaloGain cgain = (gain == TileID::HIGHGAIN)
887
888 TileCell* pCell = NEWTILECELL();
889 // no CaloDDE
890 // Cell ID is set explicitly
891 pCell->set(NULL, cell_id);
892 pCell->setEnergy_nonvirt(ener, 0, cgain, 3);
893 pCell->setTime_nonvirt(time);
894 pCell->setQual1(iqual);
895 pCell->setQual2(0);
896 pCell->setQbit1(qbit);
897 pCell->setQbit2(0);
898
899 if (msgLvl(MSG::VERBOSE)) {
900 msg(MSG::VERBOSE) << " E4' cell_id=" << m_tileTBID->to_string(cell_id)
901 << " adc_id=" << "5/0/" << ros << "/" << drawer << "/" << channel << "/" << gain
902 << " ene= " << ener
903 << " ehit= " << ehit
904 << " time= " << time
905 << " iqual= " << (int) iqual
906 << " qbit = 0x" << MSG::hex << (int) qbit << MSG::dec << endmsg;
907 }
908
909 if (E4prVec[index]) {
910 msg(MSG::WARNING) << " double E4' cell_id=" << m_tileTBID->to_string(cell_id)
911 << " ignoring previous value" << endmsg;
912 }
913 E4prVec[index] = pCell;
914 }
915
916 } else if (MBTS) { // MBTS cells
917
918 if (MBTSCells) { // do something with them only if contaier existst
919 ++nMBTS;
920
921 // convert energy to pCb
922 ener /= emScale->calibrateChannel(drawerIdx, channel, gain, 1.,
925 gain = (ener>12.) ? TileID::LOWGAIN : TileID::HIGHGAIN; // assume low gain above 12 pC
926 eMBTSTot += ener;
927 unsigned char iqual = iquality(qual);
928 // for MBTS qbit use AND of good_time and non_zero_time and check that energy is above MBTS energy threshold in pC
929 unsigned char qbit = qbits(drawerEvtStatus,
930 ros, drawer, false, (good_time && non_zero_time)
931 , (fabs(ener) > m_eneForTimeCutMBTS), overflow, underflow, overfit);
932 CaloGain::CaloGain cgain = (gain == TileID::HIGHGAIN)
935
936 TileCell* pCell = NEWTILECELL();
937 // MBTS CaloDDE
938 // Cell ID is set explicitly
939 pCell->set((m_mbtsMgr) ? m_mbtsMgr->get_element(cell_id) : NULL, cell_id);
940 pCell->setEnergy_nonvirt(ener, 0, cgain, 3);
941 pCell->setTime_nonvirt(time);
942 pCell->setQual1(iqual);
943 pCell->setQual2(0);
944 pCell->setQbit1(qbit);
945 pCell->setQbit2(0);
946
947 if (msgLvl(MSG::VERBOSE)) {
948 msg(MSG::VERBOSE) << " MBTS cell_id=" << m_tileTBID->to_string(cell_id)
949 << " adc_id=" << "5/0/" << ros << "/" << drawer << "/" << channel << "/" << gain
950 << " ene= " << ener
951 << " ehit= " << ehit
952 << " time= " << time
953 << " iqual= " << (int) iqual
954 << " qbit = 0x" << MSG::hex << (int) qbit << MSG::dec << endmsg;
955 }
956
957 if (MBTSVec[index]) {
958 msg(MSG::WARNING) << " double MBTS cell_id=" << m_tileTBID->to_string(cell_id)
959 << " ignoring previous value" << endmsg;
960 }
961 MBTSVec[index] = pCell;
962 }
963 } else {
964
965 eCellTot += ener;
966
967 unsigned char iqual = iquality(qual);
968 // for normal cell qbit use only non_zero_time flag and check that energy is above standard energy threshold in MeV
969 unsigned char qbit = qbits(drawerEvtStatus, ros, drawer, true, non_zero_time,
970 (fabs(ener) > m_eneForTimeCut), overflow, underflow, overfit);
971
972 if (E1_CELL && m_RUN2plus) {
973
974 int drawer2 = m_cabling->E1_merged_with_run2plus(ros,drawer);
975 if (drawer2 != 0) { // Raw channel split into two E1 cells for Run 2.
976 Identifier cell_id2 = m_tileID->cell_id(TileID::GAPDET, side, drawer2, m_E1_TOWER, TileID::SAMP_E);
977 int index2 = m_tileID->cell_hash(cell_id2);
978 TileCell* pCell2 = NEWTILECELL();
979 ++nCell;
980 allCells[index2] = pCell2;
981 const CaloDetDescrElement* dde2 = m_tileMgr->get_cell_element(index2);
982 pCell2->set(dde2, cell_id2);
984 int pmt2(0);
985 ener *= 0.5F;
986 correctCell(pCell2, 1, pmt2, gain, ener, time, iqual, qbit);
987
988 ATH_MSG_DEBUG("E1 cell Id => " << m_tileID->to_string(cell_id)
989 << " split into " << m_tileID->to_string(cell_id2));
990 }
991 }
992
993 TileCell* pCell = allCells[index];
994 if (pCell) {
995 ++nTwo;
996 correctCell(pCell, 2, pmt, gain, ener, time, iqual, qbit); // correct & merge 2 PMTs in one cell
997 } else {
998 ++nCell;
999 allCells[index] = pCell = NEWTILECELL();
1000 const CaloDetDescrElement* dde = m_tileMgr->get_cell_element(index);
1001 pCell->set(dde, cell_id);
1003 correctCell(pCell, 1, pmt, gain, ener, time, iqual, qbit); // correct & save e,t,q in new cell
1004 }
1005
1006 if (msgLvl(MSG::VERBOSE)) {
1007 float calib1 = (ehit != 0.0) ? ener / ehit : 0.0;
1008 msg(MSG::VERBOSE) << " cell_id=" << m_tileID->to_string(cell_id, -2)
1009 << " adc_id=" << "5/0/" << ros << "/" << drawer << "/" << channel << "/" << gain
1010 << " calib=" << calib1
1011 << " nCell=" << nCell
1012 << " energy=" << ener << " (" << pCell->energy() << ", " << pCell->eneDiff() << ")" << endmsg;
1013
1014 msg(MSG::VERBOSE) << " ehit= " << ehit
1015 << " time= " << time
1016 << " iqual= " << (int) iqual
1017 << " qbit = 0x" << MSG::hex << (int) qbit << MSG::dec << endmsg;
1018 }
1019 }
1020 }
1021
1022
1023
1024 unsigned char iqual = 0;
1025 unsigned char qbit = m_RChType;
1026
1027 //**
1028 // Now store all TileCells
1029 //**
1030 for (unsigned int index = 0; index < allCells.size(); ++index) {
1031
1032 TileCell * pCell = allCells[index];
1033 const CaloDetDescrElement* dde = m_tileMgr->get_cell_element(index);
1034 if(!dde)
1035 {
1036 ATH_MSG_VERBOSE ("skipping dummy tower with id=" << m_tileID->to_string(m_tileID->cell_id((IdentifierHash)index), -2) << " hash " << index);
1037 continue;
1038 }
1039 Identifier cell_id = dde->identify();
1040
1041 int section = m_tileID->section(cell_id);
1042 int side = m_tileID->side(cell_id);
1043 int module = m_tileID->module(cell_id);
1044 int sample = m_tileID->sample(cell_id);
1045
1046 bool single_PMT_C10 = ( section == TileID::GAPDET && sample == TileID::SAMP_B && !m_cabling->C10_connected(module) );
1047 bool missing_D4 = ( section == TileID::GAPDET && sample == TileID::SAMP_D && (module == ((side>0)?14:17)) );
1048 bool Ecell = (sample == TileID::SAMP_E);
1049 bool single_PMT = Ecell || single_PMT_C10;
1050
1051 if (!pCell) {
1052
1053 if ( ! missing_D4 ) {
1054
1055 ++nCell;
1056 if (!single_PMT) ++nTwo;
1057
1058 allCells[index] = pCell = NEWTILECELL();
1059 pCell->set(dde, cell_id);
1060
1061 pCell->setEnergy_nonvirt(ener_min, 0.0, TileID::HIGHGAIN, (Ecell)?3:TileID::HIGHGAIN); // reset energy completely
1062 pCell->setTime_nonvirt(0.0); // reset time completely
1063 pCell->setQuality(iqual, qbit, 0); // reset quality flag for first pmt
1064 pCell->setQuality(iqual, qbit, 1); // reset quality flag for second pmt
1065
1066 ATH_MSG_VERBOSE ( "adding cell with no signal with id=" << m_tileID->to_string(pCell->ID(), -2));
1067 }
1068 }
1069
1070 if (pCell) { // cell exists
1071
1073 if (maskBadChannels (drawerEvtStatus, pCell,single_PMT_C10,Ecell))
1074 ATH_MSG_VERBOSE ( "cell with id=" << m_tileID->to_string(pCell->ID(), -2)
1075 << " bad channels masked, new energy=" << pCell->energy() );
1076
1077 bool bad1=pCell->badch1();
1078 bool bad2=pCell->badch2();
1079
1080 if (! (bad1 && bad2) ) {
1081
1082 float noiseSigma = m_noiseSigma;
1083 if (caloNoise) {
1084 noiseSigma = caloNoise->getEffectiveSigma (pCell->ID(), pCell->gain(), pCell->energy());
1085 }
1086
1087 if (bad1 || bad2 || single_PMT) {
1088
1089 float ene = RandGaussQ::shoot(engine, 0.0, noiseSigma);
1090
1091 ATH_MSG_VERBOSE ( "Cell noise for cell id=" << m_tileID->to_string(pCell->ID(), -2)
1092 << " sigma " << noiseSigma << " noise " << ene );
1093 if (Ecell)
1094 pCell->addEnergy(ene,0,pCell->gain1());
1095 else
1096 pCell->addEnergy(ene);
1097
1098 } else {
1099
1100 int gain1=pCell->gain1();
1101 int gain2=pCell->gain2();
1102
1103 if (gain1!=gain2) {
1104
1105 float ene = RandGaussQ::shoot(engine, 0.0, noiseSigma);
1106 ATH_MSG_VERBOSE ( "Cell noise for cell id=" << m_tileID->to_string(pCell->ID(), -2)
1107 << " sigma " << noiseSigma << " noise " << ene );
1108
1109 if (gain1==TileID::LOWGAIN)
1110 pCell->addEnergy(ene,0,gain1);
1111 else
1112 pCell->addEnergy(ene,1,gain2);
1113
1114 } else {
1115
1116 noiseSigma *= M_SQRT1_2;
1117 float ene1 = RandGaussQ::shoot(engine, 0.0, noiseSigma);
1118 float ene2 = RandGaussQ::shoot(engine, 0.0, noiseSigma);
1119
1120 ATH_MSG_VERBOSE ( "Cell noise for cell id=" << m_tileID->to_string(pCell->ID(), -2)
1121 << " sigma " << noiseSigma*M_SQRT2 << " noise " << ene1+ene2 << " noise1 " << ene1 << " noise2 " << ene2 );
1122
1123 pCell->addEnergy(ene1,0,gain1);
1124 pCell->addEnergy(ene2,0,gain2);
1125 }
1126 }
1127 }
1128 coll->push_back(pCell); // store cell in container
1129 allCells[index] = 0; // clear pointer for next event
1130 }
1131 }
1132
1133
1134 if (MBTSCells) {
1135
1136 for (int side = 0; side < NSIDE; ++side) {
1137 for (int phi = 0; phi < NPHI; ++phi) {
1138 for (int eta = 0; eta < NETA; ++eta) {
1139
1140 int index=mbts_index(side,phi,eta);
1141 TileCell * pCell = MBTSVec[index];
1142
1143 bool merged_MBTS = ( eta == 1 && (phi&1) == 1 && m_RUN2); // in RUN2 every second outer MBTS does not exist
1144
1145 if (!pCell && !merged_MBTS) {
1146
1147 ++nMBTS;
1148 MBTSVec[index] = pCell = NEWTILECELL();
1149
1150 Identifier cell_id = m_tileTBID->channel_id((side > 0) ? 1 : -1, phi, eta);
1151 pCell->set((m_mbtsMgr) ? m_mbtsMgr->get_element(cell_id) : NULL, cell_id);
1152 pCell->setEnergy_nonvirt(0.0, 0.0, CaloGain::TILEONEHIGH, CaloGain::INVALIDGAIN); // reset energy completely
1153 pCell->setTime_nonvirt(0.0); // reset time completely
1154 pCell->setQuality(iqual, qbit, 0); // reset quality flag for first pmt
1155 pCell->setQuality(iqual, qbit, 1); // reset quality flag for second pmt
1156 }
1157
1158 if (pCell) {
1159 if (m_maskBadChannels && maskBadChannel (drawerEvtStatus, pCell))
1160 ATH_MSG_VERBOSE ( "MBTS cell with id=" << m_tileTBID->to_string(pCell->ID())
1161 << " bad channel masked, new energy=" << pCell->energy() );
1162
1163 MBTSCells->push_back(pCell); // store cell in container
1164 MBTSVec[index] = 0; // clear pointer for next event
1165 }
1166 }
1167 }
1168 }
1169 }
1170
1171 if (E4prCells) {
1172
1173 for (int phi = 0; phi < E4NPHI; ++phi) {
1174
1175 int index = e4pr_index(phi);
1176 TileCell * pCell = E4prVec[index];
1177
1178 if (!pCell) {
1179
1180 ++nE4pr;
1181 E4prVec[index] = pCell = NEWTILECELL();
1182
1183 pCell->set(NULL, m_tileTBID->channel_id(E4SIDE, phi, E4ETA));
1184 pCell->setEnergy_nonvirt(0.0, 0.0, CaloGain::TILEONEHIGH, CaloGain::INVALIDGAIN); // reset energy completely
1185 pCell->setTime_nonvirt(0.0); // reset time completely
1186 pCell->setQuality(iqual, qbit, 0); // reset quality flag for first pmt
1187 pCell->setQuality(iqual, qbit, 1); // reset quality flag for second pmt
1188 }
1189
1190 if (pCell) {
1191 if (m_maskBadChannels && maskBadChannel (drawerEvtStatus, pCell))
1192 ATH_MSG_VERBOSE ( "E4pr cell with id=" << m_tileTBID->to_string(pCell->ID())
1193 << " bad channel masked, new energy=" << pCell->energy() );
1194
1195 E4prCells->push_back(pCell); // store cell in container
1196 E4prVec[index] = 0; // clear pointer for next event
1197 }
1198 }
1199 }
1200
1201 if (msgLvl(MSG::DEBUG)) {
1202 msg(MSG::DEBUG) << " nChan=" << nChan
1203 << " RawChSum=" << eCh
1204 << " nCell=" << nCell
1205 << " n2=" << nTwo
1206 << " nFake=" << nFake
1207 << " eneTot=" << eCellTot;
1208
1209 if (MBTSCells)
1210 msg(MSG::DEBUG) << " nMBTS=" << nMBTS
1211 << " eMBTS=" << eMBTSTot;
1212 if (E4prCells)
1213 msg(MSG::DEBUG) << " nE4pr=" << nE4pr
1214 << " eE4pr=" << eE4prTot;
1215
1216 msg(MSG::DEBUG) << endmsg;
1217 }
1218}
1219
1220#undef NEWTILECELL
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_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
An interface for getting the name of a class as a string.
Helpers for checking error return status codes and reporting errors.
SelectAllObjectMT< DCC, OBJECT > SelectAllObject
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
void section(const std::string &sec)
#define NEWTILECELL
static const InterfaceID IID_ITileCellBuilderFromHit("TileCellBuilderFromHit", 1, 0)
TileContainer< TileCell > TileCellContainer
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
Container class for CaloCell.
bool hasCalo(const CaloCell_ID::SUBCALO caloNum) const
tell wether it has been filled with cells (maybe none) of a given calo
void setHasCalo(const CaloCell_ID::SUBCALO caloNum)
set which calo has been filled.
CaloCell_Base_ID::SUBCALO SUBCALO
Definition CaloCell_ID.h:50
double energy() const
get energy (data member)
Definition CaloCell.h:327
const CaloDetDescrElement * caloDDE() const
get pointer to CaloDetDescrElement (data member)
Definition CaloCell.h:321
void set(const CaloDetDescrElement *caloDDE, const Identifier &ID)
Fast method to change the identity of a cell.
Definition CaloCell.h:511
CaloGain::CaloGain gain() const
get gain (data member )
Definition CaloCell.h:361
Identifier ID() const
get ID (from cached data member) non-virtual and inline for fast access
Definition CaloCell.h:295
This class groups all DetDescr information related to a CaloCell.
Identifier identify() const override final
cell identifier
IdentifierHash onl2() const
cell online identifier 2
IdentifierHash onl1() const
cell online identifier 1
float getEffectiveSigma(const Identifier id, const int gain, const float energy) const
Definition CaloNoise.h:55
static std::string name()
Return the name of class T as a string.
a typed memory pool that saves time spent allocation small object.
Definition DataPool.h:63
value_type push_back(value_type pElem)
This is a "hash" representation of an Identifier.
const_pointer_type cptr()
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.
const_iterator end()
const_iterator begin()
Class holding bad channel problems.
bool isBadTiming() const
bool isBad() const
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
const MbtsDetDescrManager * m_mbtsMgr
Pointer to MbtsDetDescrManager.
unsigned char iquality(float qual) const
int m_qualityCut
cut on channel quality (set energy to m_zeroEnergy for them)
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
static const InterfaceID & interfaceID()
float m_zeroEnergy
energy to store in every PMT if both PMT are bad
bool maskBadChannel(TileDrawerEvtStatusArray &drawerEvtStatus, TileCell *pCell) const
method to check if channels are good or bad.
TileCellBuilderFromHit(const std::string &type, const std::string &name, const IInterface *parent)
Contructor.
virtual StatusCode initialize() override
Initializer.
TileDrawerEvtStatus TileDrawerEvtStatusArray[5][64]
status of every drawer
float m_maxTime
maximum time for the PMTs in the cels
const TileTBID * m_tileTBID
Pointer to TileTBID.
virtual StatusCode process(CaloCellContainer *theCellContainer, const EventContext &ctx) const override
method to process all raw channels and store them in container
unsigned char qbits(TileDrawerEvtStatusArray &drawerEvtStatus, int ros, int drawer, bool count_over, bool good_time, bool good_ener, bool overflow, bool underflow, bool good_overflowfit) const
method to compute the cell quality bits
SG::ReadCondHandleKey< TileEMScale > m_emScaleKey
Name of TileEMScale in condition store.
const TileDetDescrManager * m_tileMgr
Pointer to TileDetDescrManager.
SG::ReadHandleKey< TileHitContainer > m_hitContainerKey
SG::ReadCondHandleKey< TileSamplingFraction > m_samplingFractionKey
Name of TileSamplingFraction in condition store.
void build(const CaloNoise *caloNoise, TileDrawerEvtStatusArray &drawerEvtStatus, const ITERATOR &begin, const ITERATOR &end, COLLECTION *coll, TileCellContainer *MBTSCells, TileCellContainer *E4prCells, const TileSamplingFraction *samplingFraction) const
const TileID * m_tileID
Pointer to TileID.
float m_minTime
minimum time for the PMTs in the cels
void correctCell(TileCell *pCell, int correction, int pmt, int gain, float ener, float time, unsigned char iqual, unsigned char qbit) const
Compute calibrated energy, time, etc.
virtual StatusCode finalize() override
const TileHWID * m_tileHWID
Pointer to TileHWID.
const TileCablingService * m_cabling
Pointer to TileCabling.
bool m_maskBadChannels
if true=> bad channels are masked
SG::WriteHandleKey< TileCellContainer > m_E4prContainerKey
virtual ~TileCellBuilderFromHit()
Destructor.
TileFragHash::TYPE m_RChType
Type of TileRawChannels (Fit, OF2, etc.)
float m_eneForTimeCutMBTS
similar cut for MBTS in pC
ToolHandle< ITileBadChanTool > m_tileBadChanTool
SG::ReadCondHandleKey< CaloNoise > m_caloNoiseKey
float m_noiseSigma
cell electronic noise if CaloNoise is switched off
bool maskBadChannels(TileDrawerEvtStatusArray &drawerEvtStatus, TileCell *pCell, bool single_PMT_C10, bool Ecell) const
int mbts_index(int side, int phi, int eta) const
ServiceHandle< TileCablingSvc > m_cablingSvc
Name of Tile cabling service.
ServiceHandle< IAthRNGSvc > m_rndmSvc
< Random number service to use
float m_eneForTimeCut
keep time for channels with energy above cut
SG::WriteHandleKey< TileCellContainer > m_MBTSContainerKey
uint8_t qual1(void) const
get quality of first PMT (data member)
Definition TileCell.h:197
void addEnergy(float e, int pmt, int gain)
set energy and gain for one PMT
Definition TileCell.cxx:145
float time1(void) const
get time of first PMT
Definition TileCell.h:192
void setEnergy_nonvirt(float e1, float e2, int gain1, int gain2)
Definition TileCell.h:257
void setQual2(unsigned char qual)
set quality of second PMT
Definition TileCell.h:165
void setTime_nonvirt(float t)
Definition TileCell.h:244
float eneDiff(void) const
all get methods
Definition TileCell.h:182
virtual void setEnergy(float ene) override final
set total energy, reset eneDiff to zero (final override of CaloCell method)
Definition TileCell.cxx:123
int gain2(void) const
get gain of second PMT
Definition TileCell.cxx:175
bool badch1(void) const
check if first PMT is in bad channel list and masked
Definition TileCell.h:209
uint8_t qbit2(void) const
get quality bits of second PMT (data member)
Definition TileCell.h:206
int gain1(void) const
get gain of first PMT
Definition TileCell.cxx:168
uint8_t qual2(void) const
get quality of second PMT (data member)
Definition TileCell.h:200
void setQbit1(unsigned char qbit)
set quality bits of first PMT
Definition TileCell.h:168
void setQbit2(unsigned char qbit)
set quality bits of second PMT
Definition TileCell.h:171
void setQuality(unsigned char qual, unsigned char qbit, int pmt)
set quality value and quality bits for one PMT (TileCell specific overloads)
Definition TileCell.h:280
void setQual1(unsigned char qual)
set quality of first PMT
Definition TileCell.h:162
float ene1(void) const
get energy of first PMT
Definition TileCell.h:187
virtual void setTime(float t) override final
set cell time, reset timeDiff
Definition TileCell.h:251
bool badch2(void) const
check if second PMT is in bad channel list and masked
Definition TileCell.h:212
float time2(void) const
get time of second PMT
Definition TileCell.h:194
@ MASK_AMPL
Definition TileCell.h:65
@ MASK_TIME
Definition TileCell.h:67
@ MASK_OVER
Definition TileCell.h:64
@ MASK_ALGO
Definition TileCell.h:62
@ MASK_BADCH
Definition TileCell.h:63
uint8_t qbit1(void) const
get quality bits of first PMT (data member)
Definition TileCell.h:203
float ene2(void) const
get energy of second PMT
Definition TileCell.h:189
This class keep detailed status info about one drawer in a given event.
Hash table for Tile fragments (==drawers ==collections in StoreGate)
@ EXTBAR_POS
Definition TileHWID.h:70
@ NOT_VALID_HASH
Definition TileHWID.h:314
float time(int ind=0) const
Return time of ind-th sub-hit.
float energy(int ind=0) const
Return energy of ind-th sub-hit.
Identifier identify(void) const
Return logical ID of the pmt.
int size(void) const
Return length of energy/time vectors.
Condition object to keep and provide Tile Calorimeter sampling fraction and number of photoelectrons.
float getSamplingFraction(unsigned int drawerIdx, unsigned int channel) const
Return Tile Calorimeter sampling fraction.
@ Tile
The Tile calorimeter.
EventFlagErrorState
States that a given sub-detector could be in.
@ Warning
The sub-detector issued a warning.
@ NotSet
The flag was not set to anything.
@ Error
The sub-detector issued an error.
@ INVALIDGAIN
Definition CaloGain.h:18
@ TILEONEHIGH
Definition CaloGain.h:17
@ TILEONELOW
Definition CaloGain.h:16
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
Definition index.py:1
MsgStream & msg
Definition testRead.cxx:32