ATLAS Offline Software
Loading...
Searching...
No Matches
TilePulseForTileMuonReceiver.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//
7// Filename : TilePulseForTileMuonReceiver.cxx
8// Author : Joao Gentil Mendes Saraiva (jmendes@cern.ch)
9// Created : October 2013
10//
11// DESCRIPTION:
12//
13// The algorithm will do:
14// Create a digitized pulse with 7 samples based in a measured pulse.
15// The pulse is reconstructed using the matched filter alogtrithm.
16// Digits and reconstructed pulse parameters (e,t,qf) are saved in contaienrs in TES.
17//
18// This is part of the tile-d project (2015).
19//
20// HISTORY:
21//
22// 10.dec.2013 ready for submission in svn
23// 16.jan.2014 fixed coverity errors
24// 06.oct.2015 including the barrel cells
25// 21.jun.2020 MC pileup overlay
26//
27// BUGS:
28//
29//
30//
31//****************************************************************************************
32
33// Tile includes
43
44
45// Calo includes
47
48// Atlas includes
56
57
58// external
59#include <CLHEP/Random/Randomize.h>
60#include <CLHEP/Units/SystemOfUnits.h>
61
62using CLHEP::RandGaussQ;
63using CLHEP::RandFlat;
64using CLHEP::MeV;
65
66#include "cmath"
67
68// constructor
69//
70TilePulseForTileMuonReceiver::TilePulseForTileMuonReceiver(const std::string& name, ISvcLocator* pSvcLocator)
71 : AthAlgorithm(name, pSvcLocator)
72 , m_tileID(nullptr)
73 , m_tileHWID(nullptr)
74 , m_tileInfo(nullptr)
75 , m_cablingService(nullptr)
76 , m_nSamples(0)
77 , m_iTrig(0)
78 , m_adcMax(0)
79 , m_tileThresh(0.0)
80 , m_nShape(0)
81 , m_nBinsPerX(0)
82 , m_binTime0(0)
83 , m_timeStep(0.0)
84 , m_runPeriod(0)
85{
86}
87
88// destructor
89//
92
93// initialize
94//
96
97 // Check cabling RUN>=RUN2 OK
98 //
99 ATH_CHECK( m_cablingSvc.retrieve() );
100 m_cablingService = m_cablingSvc->cablingService();
101 m_runPeriod = m_cablingService->runPeriod();
102
103 // Handles must always be initialised
104 ATH_CHECK( m_hitContainerKey.initialize(m_runPeriod != 0) );
108 ATH_CHECK( m_samplingFractionKey.initialize(m_runPeriod != 0) );
109 ATH_CHECK( m_emScaleKey.initialize(m_runPeriod != 0) );
111
112 if ( m_runPeriod == 0) {
113 ATH_MSG_INFO("TilePulseForTileMuonReceiver should not be used for RUN1 simulations");
114 return StatusCode::SUCCESS;
115 } else {
116 ATH_MSG_INFO("Initializing TilePulseForTileMuonReceiver");
117 }
118
119 //=== retrieve TileID helper and TileInfo from det store
120 ATH_CHECK(detStore()->retrieve(m_tileID));
121 ATH_CHECK(detStore()->retrieve(m_tileHWID));
123
124 ATH_CHECK(m_MuRcvBuildTool.retrieve());
125
126 m_nSamples = m_tileInfo->NdigitSamples(); // number of time slices for each chan
127 m_iTrig = m_tileInfo->ItrigSample(); // index of the triggering time slice
128 m_adcMax = m_tileInfo->ADCmax(); // adc saturation value
129 m_tileThresh = m_tileInfo->ThresholdDigits(TileID::LOWGAIN);
130
131 ATH_MSG_VERBOSE("Cabling Services: " << m_cablingService
132 << " Number of Samples: " << m_nSamples
133 << " Triggering tile slice: " << m_iTrig
134 << " ADC saturation value: " << m_adcMax
135 << " TileCal Threshold LOW GAIN: " << m_tileThresh);
136
137 ATH_CHECK(m_rndmSvc.retrieve());
138
139 m_nShape = m_tileInfo->MuRcvNBins();
140 m_nBinsPerX = m_tileInfo->MuRcvBinsPerX();
141 m_binTime0 = m_tileInfo->MuRcvTime0Bin();
142 m_timeStep = 25.0 / m_nBinsPerX;
143
144 ATH_MSG_VERBOSE( "Pulse info : "
145 << "shape " << m_nShape
146 <<" nbins " << m_nBinsPerX
147 <<" time " << m_binTime0
148 <<" time step " << m_timeStep
149 <<" Triggering tile sample " << m_iTrig);
150
151 // decrease by 1, now it is the position of lastest element in a vector
152 //
153 --m_nShape;
154
157 ATH_MSG_INFO( "Using pulse from database.");
158 } else {
159 ATH_MSG_INFO( "Using pulse from TileInfo.");
160
161 m_shapeMuonReceiver = m_tileInfo->MuRcvFullShape();
162 m_shapeMuonReceiver.push_back(0.0);
163 }
164
166
167 ATH_MSG_INFO( "Integer digits: \t" << ((m_integerDigits)?"true":"false"));
168 ATH_MSG_INFO( "Tile Pedestal: \t" << ((m_tilePedestal)?"true":"false"));
169 ATH_MSG_INFO( "Tile Noise: \t" << ((m_tileNoise)?"true":"false"));
170 ATH_MSG_INFO( "Event Overlay: \t" << ((m_rndmEvtOverlay)?"true":"false"));
171 ATH_MSG_INFO( "Masking Channels: \t" << ((m_maskBadChannels)?"true":"false"));
172 ATH_MSG_INFO( "Pulse shapes from COOL: \t" << ((m_useCoolPulseShapes)?"true":"false"));
173
175
176 if (m_rndmEvtOverlay) {
177 ATH_MSG_INFO( "Pileup and/or noise added by overlaying digits of random events");
178 // locate the PileUpMergeSvc and initialize our local ptr
180 ATH_CHECK( m_mergeSvc.retrieve() );
181 ATH_MSG_INFO( "PileUpMergeSvc successfully initialized");
182 }
183 }
184
185 ATH_MSG_VERBOSE("TilePulseForTileMuonReceiver initialization completed");
186 return StatusCode::SUCCESS;
187}
188
189// execute
190//
192
193 if (m_runPeriod==0) {
194 ATH_MSG_VERBOSE( "ATT: RUN1 settings TilePulseForTileMuonReceiver will end now" );
195 return StatusCode::SUCCESS;
196 } else {
197 ATH_MSG_DEBUG( "Executing TilePulseForTileMuonReceiver" );
198 }
199
200 const EventContext& ctx = Gaudi::Hive::currentContext();
201
202 // Conversion from TMDB channel number to channel number in a drawer: EB (0-3) LB (0-8)
203 // Including the cells used in the "The potential of using the ATLAS Tile calorimeter in Phase-II for the
204 // Level-0 muon trigger" (ATL-COM-TILECAL-2015-007.pdf): ALL D-layer + BC-8.
205 //
206#define nEBchan 6
207#define nLBchan 9
208 // EB: D5(L,R),D6(L,R),D4(L,R)
209 int EBchan[nEBchan]={17,16,37,38,3,2};
210 // LB: D0,D1(L,R),D2(L,R),D3(L,R),BC8(L,R)
211 int LBchan[nLBchan]={0,13,14,25,24,41,44,39,40};
212 // Set to maximum possible index
213#if (nEBchan > nLBchan)
214 double pDigitSamplesArray[nEBchan][7];
215 double pDigitSamplesRndmArray[nEBchan][7];
216#else
217 double pDigitSamplesArray[nLBchan][7];
218 double pDigitSamplesRndmArray[nLBchan][7];
219#endif
220
221 // PULSE
222
223 // Random generators output arrays
224 //
225 double Rndm[16];
226 double Rndm_dG[1];
227
228 // Noise and pedestal from db
229 //
230 double pedSim = 0.;
231 double sigma_Hfn1 = 0.;
232 double sigma_Hfn2 = 0.;
233 double sigma_Norm = 0.;
234 double sigmaSim(0.0);
235
236 // Measured parameters: noise, pedestal and calibration
237 //
238 double muRcv_NoiseSigma;
239 double muRcv_Ped;
240 double muRcv_Calib;
241 double muRcv_Max;
242
244 ATH_CHECK( emScale.isValid() );
245
246 const TileBadChannels* badChannels = nullptr;
247 if (m_maskBadChannels) {
249 ATH_CHECK( badChannelsHandle.isValid() );
250 badChannels = *badChannelsHandle;
251 }
252
253 const TilePulse* pulse = nullptr;
256 ATH_CHECK( pulseShape.isValid() );
257 pulse = pulseShape.retrieve();
258 }
259
260 const TileSampleNoise* sampleNoise = nullptr;
263 ATH_CHECK( sampleNoiseHandle.isValid() );
264 sampleNoise = sampleNoiseHandle.retrieve();
265 }
266
267 // Get hit container from TES
268 //
270 ATH_CHECK( hitContainer.isValid() );
271
272 // Set up buffers for handling information in a single collection.
273 //
274 IdentifierHash idhash;
275 IdContext drawer_context = m_tileHWID->drawer_context();
276
277 // Get a container for the digits
278 //
279 auto muRcvDigitsContainer = std::make_unique<TileMutableDigitsContainer>(true,
282 ATH_CHECK( muRcvDigitsContainer->status() );
283
284 // Get a container for the raw channels
285 //
286 auto muRcvRawChannelContainer = std::make_unique<TileMutableRawChannelContainer>(true,
290 ATH_CHECK( muRcvRawChannelContainer->status() );
291
292 // Prepare container for MC Overlay procedure
293 //
296 std::unique_ptr<TileMutableDigitsContainer> backgroundDigitContainer{};
297
298 if (m_rndmEvtOverlay) {
299
300 ATH_MSG_DEBUG("Prepare background container for MC Overlay procedure");
301
302 backgroundDigitContainer = std::make_unique<TileMutableDigitsContainer>(true,
305 ATH_CHECK( backgroundDigitContainer->status() );
306
309 TimedDigitContList digitContList;
310 ATH_CHECK( m_mergeSvc->retrieveSubEvtsData(m_inputDigitContainerName, digitContList));
311 ATH_MSG_DEBUG( "TileDigitsCnt successfully retrieved ");
312
313 if (digitContList.size() == 0) {
314 ATH_MSG_WARNING( "No overlay done ... ");
315 return StatusCode::SUCCESS;
316 }
317
318 TimedDigitContList::iterator iTzeroDigitCont(digitContList.begin());
319 for (const auto* digitCollection : *(iTzeroDigitCont->second)) {
320 for (const auto* digit : *digitCollection) {
321 auto pDigits = std::make_unique<TileDigits>(*digit);
322 ATH_CHECK(backgroundDigitContainer->push_back(std::move(pDigits)));
323 }
324 }
325 } else {
327 if (tileDigitsContainerHandle.isValid()) {
328 for (const auto* digitCollection : *tileDigitsContainerHandle) {
329 for (const auto* digit : *digitCollection) {
330 auto pDigits = std::make_unique<TileDigits>(*digit);
331 ATH_CHECK(backgroundDigitContainer->push_back(std::move(pDigits)));
332 }
333 }
334 } else {
335 ATH_MSG_ERROR("ReadHandle to Background Digits is invalid.");
336 return StatusCode::FAILURE;
337 }
338 }
339
340 collItrRndm = backgroundDigitContainer->begin();
341 lastCollRndm = backgroundDigitContainer->end();
342 }
343
344 // Vector of digits to set into the container
345 //
346 std::vector<float> digitsBuffer(m_nSamples);
347
348 // Vector(s) for MC Overlay procedure
349 //
350 std::vector<float> digitsBuffer_rndm(m_nSamples);
351 std::vector<bool> good_bkg( 9 , false );
352
353 // Prepare RNG service
354 //
355 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
356 rngWrapper->setSeed( m_randomStreamName, Gaudi::Hive::currentContext() );
357
359 // (a.0) iterate over collections in the HIT container: access 'ros' and 'drawer'
360 //
362 ATH_CHECK( samplingFraction.isValid() );
363
364 for (const TileHitCollection* hitCollection : *hitContainer) {
365
366 // Get array of HWID's for this drawer (stored locally).
367 //
368 HWIdentifier drawer_id = m_tileHWID->drawer_id(hitCollection->identify());
369 int ros = m_tileHWID->ros(drawer_id);
370 int drawer = m_tileHWID->drawer(drawer_id);
371 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
372 bool eb_ros = ((ros == TileHWID::EXTBAR_POS) || (ros == TileHWID::EXTBAR_NEG));
373 int upperLim = (eb_ros) ? nEBchan : nLBchan;
374
375 ATH_MSG_VERBOSE("(A.00) Looping over all collections for TMDB in the HIT container");
376 memset(pDigitSamplesArray, 0, sizeof(pDigitSamplesArray));
377
378 ATH_MSG_VERBOSE("(A.01) Going through collection ROS/DRAWER : "<< ros <<"/"<< drawer);
379 ATH_MSG_DEBUG(" Going through collection ROS/DRAWER : "<< ros <<"/"<< drawer);
380
381 if (m_cablingService->connected(ros, drawer)) {
382 ATH_MSG_VERBOSE("(A.02) ROS: "<< ros << " drawer: " << drawer << " is connected");
383 } else {
384 ATH_MSG_VERBOSE("(A.02) ROS: "<< ros << " drawer: " << drawer << " is NOT connected");
385 continue;
386 }
387
388 // Get drawer idhash for later access to the database to get ped and noise
389 //
390 m_tileHWID->get_hash(drawer_id, idhash, &drawer_context);
391
392 // **************************************************************
393 //
394 // Prepare buffer for MC Overlay procedure: pileup digits
395 //
396
397 memset(pDigitSamplesRndmArray, 0, sizeof(pDigitSamplesRndmArray));
398
399 if (m_rndmEvtOverlay && collItrRndm != lastCollRndm) {
400
401 const TileDigitsCollection *bkgDigitCollection(*collItrRndm);
402
403 if (hitCollection->identify() != bkgDigitCollection->identify()) {
404 ATH_MSG_ERROR ( "Frag IDs for hit collection and digits overlay collection do not match "
405 << MSG::hex << hitCollection->identify() << " != " << bkgDigitCollection->identify()
406 << MSG::dec );
407 return StatusCode::FAILURE;
408 }
409
410 ATH_MSG_DEBUG("Prepare buffer (digitsBuffer_rndm) for MC Overlay procdure: pileup digits");
411
412 for (const auto* bkgDigit : *bkgDigitCollection) {
413 bool good_channel = true;
414 /* Get digit HWIdentifier (= adc_id) */
415 HWIdentifier adc_id_rndm = (*bkgDigit).adc_HWID();
416 int channel = m_tileHWID->channel(adc_id_rndm);
417 ATH_MSG_VERBOSE ( "check channels from adc id in rndm container (TMDB channel): "<< channel );
418 /* Get digits */
419 digitsBuffer_rndm = (*bkgDigit).samples();
420 /* Get number of sample and compare with nSamples */
421 int nsamp_rndm = digitsBuffer_rndm.size();
422 if (nsamp_rndm != m_nSamples) {
423 digitsBuffer_rndm.resize(m_nSamples);
424 if (nsamp_rndm>0) {
425 for (int js=nsamp_rndm; js<m_nSamples; ++js) {
426 digitsBuffer_rndm[js] = digitsBuffer_rndm[js-1];
427 }
428 }
429 }
430 /* Fill the background digits array for the current channel and set a flag if any digit is NULL */
431 for (int j=0; j< m_nSamples;j++) {
432 pDigitSamplesRndmArray[channel][j] = digitsBuffer_rndm[j];
433 // If any digit is 0 something should be wrong so flag it in order to use during overlay the standard
434 // path to fill the expected background level for that channel
435 if (pDigitSamplesRndmArray[channel][j]==0) good_channel = false;
436 }
437 good_bkg[channel] = good_channel;
438
439 if (msgLvl(MSG::VERBOSE)){
440 msg(MSG::VERBOSE) << " Digits from pileup background " << channel << " " << ros << " " << drawer << " " << m_tileHWID->to_string(adc_id_rndm)<<" | ";
441 for (int j=0; j< (int) digitsBuffer_rndm.size(); j++) msg(MSG::VERBOSE) << digitsBuffer_rndm[j] <<" | ";
442 msg(MSG::VERBOSE) << "---> | ";
443 for (int j=0; j< (int) digitsBuffer_rndm.size(); j++) msg(MSG::VERBOSE) << pDigitSamplesRndmArray[channel][j] << " | ";
444 msg(MSG::VERBOSE) << endmsg;
445 }
446 }
447 ++collItrRndm; // skip to next digi collection
448 }
449
451 // (a.1) Iterate over all hits in a collection : access 'channel'
452 //
453
454 if ( hitCollection->empty() ) ATH_MSG_DEBUG("-- No hits in this drawer! Filling channels with either noise and pedestal or MC pileup overlay. --");
455
456 for (const TileHit* tile_hit : *hitCollection) {
457
458 // Get the pmt ID
459 //
460 Identifier pmt_id = tile_hit->pmt_ID();
461
462 // keep only D-cells and in addition cell BC8
463 //
464 int tower = m_tileID->tower(pmt_id);
465 int sample = m_tileID->sample(pmt_id);
466 if ( ! ((sample == TileID::SAMP_D) || (sample == TileID::SAMP_BC && tower == 7)) ) continue;
467
468 ATH_MSG_VERBOSE("(B.00) ++ Iterate over all the D layer channels with hits");
469
470 // In COOL database data will be organized acoording to TMDB channel (TMDBchan): 0..n with n=5 in EB and n=8 in LB
471 int TMDBchan;
472 // In here we need to access the real TILE HW channel (TILEchan) that it has a correspondance with TMDB chan given by EBchan and LBNchan
473 int TILEchan;
474
475 if (eb_ros) {
476 // cells D5, D6 and then D4 at the end
477 if (m_tileID->side(pmt_id) > 0)
478 TMDBchan = 1 - m_tileID->pmt(pmt_id) + ((tower>9) ? (tower - 10) : 4);
479 else
480 TMDBchan = m_tileID->pmt(pmt_id) + ((tower>9) ? (tower - 10) : 4);
481
482 TILEchan=EBchan[TMDBchan];
483 } else {
484 // Barrel (extension for HL-LHC)
485 if (tower == 0) {
486 TMDBchan = 0; // cell D0, channel 0 always
487 } else {
488 // cells D1. D2, D3 and BC8
489 if (m_tileID->side(pmt_id) > 0)
490 TMDBchan = 1 - m_tileID->pmt(pmt_id) + ((tower<7) ? (tower-1) : 7);
491 else
492 TMDBchan = m_tileID->pmt(pmt_id) + ((tower<7) ? (tower-1) : 7);
493 }
494
495 TILEchan=LBchan[TMDBchan];
496 }
497
498 double* pDigitSamples = pDigitSamplesArray[TMDBchan];
499
500 if (msgLvl(MSG::VERBOSE)){
501 HWIdentifier adc_id = m_tileHWID->adc_id(drawer_id, TMDBchan, TileID::LOWGAIN);
502
503 ATH_MSG_VERBOSE( "(B.01) Correct pmt being transported in XXchan[]: "<<TMDBchan<<" "<<TILEchan<< "=?"
504 << m_tileHWID->channel(m_cablingService->s2h_channel_id(pmt_id))
505 << " For reference get TMDB adc_id: " << m_tileHWID->to_string(adc_id) );
506 ATH_MSG_VERBOSE( "(B.02) New hit in ROS/DRAWER/PMT "<<ros<<"/"<<drawer<<"/"<<TMDBchan<<" ("<<TILEchan<<")"
507 << " pmt_id "<< m_tileID->to_string(pmt_id,-1)
508 << " adc_id "<< m_tileHWID->to_string(adc_id) );
509 }
510
511 // Scintillator Energy -> Cell Energy (uses sampling fraction)
512 //
513 int channel = m_tileHWID->channel(m_cablingService->s2h_channel_id(pmt_id));
514 double hit_calib = samplingFraction->getSamplingFraction(drawerIdx, channel);
515 hit_calib = std::round(hit_calib * 1000) / 1000;
516
517 ATH_MSG_VERBOSE("------ Sampling fraction: " << hit_calib);
518
520 // (a.2) Loop over the hits of this channel
521 // Calibrations are applied per subhit and energy added per subhit of a channel
522 //
523
524 int n_hits = tile_hit->size();
525
526 ATH_MSG_VERBOSE("------ Number of hits in channel: " << n_hits);
527
528 for (int ihit = 0; ihit < n_hits; ++ihit) {
529
530 ATH_MSG_VERBOSE("(C.00) ++ Iterating over the hits of channel " << TILEchan <<": hit " << ihit <<"/"<< n_hits);
531
532 double e_hit = tile_hit->energy(ihit); // [MeV] energy deposited in scintillator
533 double e_pmt = e_hit * hit_calib; // [MeV] true cell energy
534
535 ATH_MSG_VERBOSE("(C.01) Energy in scintillator [MeV]: " << e_hit << " true cell energy [MeV]: " << e_pmt);
536
537 double t_hit = tile_hit->time(ihit);
538
539 ATH_MSG_VERBOSE("(C.02.01) Phase " << t_hit);
540
541 // Load pulse
542 //
543 int k = 0;
544 float phase = 0.0;
545 float y = 0.0;
546 float dy = 0.0;
547 double shape = 0.0;
548
549 int ishift = (int) (t_hit / m_timeStep + 0.5);
550
551 ATH_MSG_VERBOSE( "(C.02.02) ishift :" << t_hit << "/" << m_timeStep << "+0.5 = " << ishift);
552
554 for (int js = 0; js < m_nSamples; ++js) {
555 k = m_binTime0 + (js - m_iTrig) * m_nBinsPerX - ishift;
556 if (k < 0) k = 0;
557 else if (k > m_nShape) k = m_nShape;
558
559 ATH_MSG_VERBOSE( "(C.02.03) k : " << m_binTime0 << "+(" << js << "-" << m_iTrig << ")*" << m_nBinsPerX << "-" << ishift << " = " << k);
560
561 phase = (k - m_binTime0) * m_timeStep;
562
563 ATH_MSG_VERBOSE( "(C.02.04) phase : " << k << "-" << m_binTime0 << "*" << m_timeStep << " = " << phase);
564
565 pulse->getPulseShapeYDY(drawerIdx, TMDBchan, TileID::LOWGAIN, phase, y, dy);
566 shape = (double) y;
567 pDigitSamples[js] += e_pmt * shape; // MeV
568
569 ATH_MSG_VERBOSE( "(C.03.0) Sample no.= " << js
570 << " idx= " << k
571 << " Shape wt. = " << shape
572 << " Amp = " << pDigitSamples[js] << " [MeV]");
573 } //END loop over samples
574 } else {
575 for (int js = 0; js < m_nSamples; ++js) {
576 k = m_binTime0 + (js - m_iTrig) * m_nBinsPerX - ishift;
577 if (k < 0) k = 0;
578 else if (k > m_nShape) k = m_nShape;
579
580 ATH_MSG_VERBOSE( "(C.02.03) k : " << m_binTime0 << "+(" << js << "-" << m_iTrig << ")*" << m_nBinsPerX << "-" << ishift << " = " << k);
581
582 pDigitSamples[js] += e_pmt * m_shapeMuonReceiver[k]; // MeV
583
584 ATH_MSG_VERBOSE( "(C.03.0) Sample no.= " << js
585 << " idx= " << k
586 << " Shape wt. = " << m_shapeMuonReceiver[k]
587 << " Amp = " << pDigitSamples[js]
588 << "[MeV] Energy: " << e_pmt << " LOGAIN from TileInfo");
589 } //END loop over samples
590 } // END if (m_useCoolPulseShapes)
591 } // END loop over sub-HITS
592
593 ATH_MSG_VERBOSE("++ ENDED Loop over hits for a channel");
594 ATH_MSG_DEBUG("(C.04) Went over " << n_hits << " hits for channel"
595 << m_tileHWID->to_string(drawer_id,-2) << "/" << TMDBchan << " (" << TILEchan << ")"
596 << " digits [MeV] "<< pDigitSamples[0]
597 << "/" << pDigitSamples[1]
598 << "/" << pDigitSamples[2]
599 << "/" << pDigitSamples[3]
600 << "/" << pDigitSamples[4]
601 << "/" << pDigitSamples[5]
602 << "/" << pDigitSamples[6]);
603 ATH_MSG_VERBOSE("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
604 } // END loop over a HIT collection
605
606 ATH_MSG_VERBOSE("++ END loop over a HIT collection");
607
609 // (a.3) The pulse has a shape and a amplitude in MeV now it is converted into ADC
610 // counts and either add NOISE and PEDESTAL or the OVERLAY digits
611 //
612 // PEDESTAL [ADC counts] and NOISE [ADC counts] as stored in Tile
613 // Conditions (FIXED values but also flag for collection from COOL)
614 //
615 // Keep containers for each module (each partition) the same size
616 // between events i.e. ALL channels are filled even with ZERO energy
617 //
618
619 ATH_MSG_VERBOSE("++ START filling of channels with background either noise+pedestal or overlay");
620
621 for (int TMDBchan = 0; TMDBchan < upperLim; ++TMDBchan) {
622
623 double* pDigitSamples=pDigitSamplesArray[TMDBchan];
624 int TILEchan = (eb_ros) ? EBchan[TMDBchan] : LBchan[TMDBchan];
625
626 HWIdentifier adc_id = m_tileHWID->adc_id(drawer_id, TMDBchan, TileID::LOWGAIN);
627
628 ATH_MSG_DEBUG( "(D.) Going now to channel " << " TMDBchan: " << TMDBchan << " TILEchan: " << TILEchan);
629 ATH_MSG_DEBUG( "(D.00) Add noise and pedestal in "
630 << " TMDBchan: " << TMDBchan << " TILEchan: " << TILEchan
631 << " ROS: " << ros
632 << " drawer: " << drawer
633 << " drawer idx: " << drawerIdx
634 << " drawer_id: " << m_tileHWID->to_string(drawer_id,-2)
635 << " channel: " << m_tileHWID->to_string(adc_id,-1));
636 // adc/pCb / MeV/pCb = adc/MeV
637 //
638 muRcv_Max = m_tileInfo->MuRcvMax(adc_id); // [adc]
639 muRcv_Calib = m_tileInfo->MuRcvCalib(adc_id); // pCb->[adc]
640 double mev2ADC_factor = muRcv_Calib / emScale->calibrateChannel(drawerIdx,TILEchan,TileID::LOWGAIN, 1.
643 ATH_MSG_VERBOSE( "(D.01) Channel: "<<ros<<'/'<<drawer<<'/'<< TMDBchan
644 << " adc/pCb: "<< muRcv_Calib
645 << " Mev/pCb: "<< emScale->calibrateChannel( drawerIdx,
646 TILEchan,
648 1.,
651 << " final calibration factor adc/MeV: "<< mev2ADC_factor);
652
653 ATH_MSG_VERBOSE( "(D.02) Pulse digits [MeV]:"
654 << " " << pDigitSamples[0]
655 << " " << pDigitSamples[1]
656 << " " << pDigitSamples[2]
657 << " " << pDigitSamples[3]
658 << " " << pDigitSamples[4]
659 << " " << pDigitSamples[5]
660 << " " << pDigitSamples[6]
661 << " [All ZERO if there is no hit in channel.] ");
662
663 if ( good_bkg[TMDBchan] ) {
664 // Collecting digits for MC Overlay procedure from overlay container
665 // IF good digits ere collected (no ZEROS <> good_bkg[TMDBchan]==true) then add the background to the simulated digits
666 // ELSE bad digits (any ZEROS <> good_bkg[TMDBchan]==false) then follow the standard path adding muRcv_Ped and muRvc_NoiseSigma
667
668 ATH_MSG_DEBUG("++ Adding to signal digits -- The MC PILE-UP OVERLAY digits " << m_rndmEvtOverlay << " " << m_integerDigits);
669
670 for (int js = 0; js < m_nSamples; ++js) {
671 // Signal
672 //
673 ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" E_{Signal} [adc]: "<< pDigitSamples[js] * mev2ADC_factor <<" -- Overlay");
674 digitsBuffer[js] = pDigitSamples[js] * mev2ADC_factor;
675 // Pileup
676 //
677 ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" E_{PileUp} [adc]: "<< pDigitSamplesRndmArray[TMDBchan][js] <<" -- Overlay");
678 digitsBuffer[js] += pDigitSamplesRndmArray[TMDBchan][js];
679 // Simulated pulse above allowed maximum
680 //
681 if (digitsBuffer[js] > muRcv_Max) digitsBuffer[js] = muRcv_Max;
682 // Rounding the ADC counts
683 //
684 if (m_integerDigits) digitsBuffer[js] = round(digitsBuffer[js]);
685 ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" calibration [adc/MeV] "<< mev2ADC_factor <<"-> E_{Signal+PileUp} [adc]: "<< digitsBuffer[js] <<" -- Overlay");
686 }
687 } else {
688 if (m_rndmEvtOverlay) ATH_MSG_INFO("At least one digit is zero in background file using the stadart path to fill pedestal and noise in digits");
689 // Different for each channel_id might be the case in the future (now a const. in TileInfoLoader.cxx)
690 //
691 muRcv_NoiseSigma = m_tileInfo->MuRcvNoiseSigma(adc_id); // [adc]
692 muRcv_Ped = m_tileInfo->MuRcvPed(adc_id); // [adc]
693
694 ATH_MSG_VERBOSE( "(D.03) Tile Muon Receiver parameters:"
695 << " noi " << muRcv_NoiseSigma
696 << " ped " << muRcv_Ped
697 << " cal " << muRcv_Calib
698 << " max " << muRcv_Max);
699
700 // Collecting digits for standard procedure NO OVERLAY: pedestal+noise
701 // ADD digitsBuffer[m_nSamples] WITH Ped and Noise from COOLDB/ATHENA
702 //
703 ATH_MSG_DEBUG("++ Adding to signal digits -- The PEDESTAL + NOISE digits "<< m_tilePedestal <<" "<< m_tileNoise << " " << m_integerDigits);
704 // Collecting pedestal from the database
705 //
706 if (m_tilePedestal) {
707 pedSim = sampleNoise->getPed(idhash, TMDBchan, TileID::LOWGAIN);
708 // As in TileDigitsMaker bug fix for wrong ped value in DB
709 //
710 if (pedSim == 0.0) pedSim = 30.;
711 } else {
712 pedSim = muRcv_Ped;
713 }
714 // Collecting noise from the database
715 //
716 if (m_tileNoise) {
717 // Generate an array to randomize the noise for each digit
718 //
719 RandGaussQ::shootArray(*rngWrapper, m_nSamples, Rndm, 0.0, 1.0);
720 RandFlat::shootArray(*rngWrapper, 1, Rndm_dG, 0.0, 1.0);
721 sigma_Hfn1 = sampleNoise->getHfn1(idhash, TMDBchan, TileID::LOWGAIN);
722 sigma_Hfn2 = sampleNoise->getHfn2(idhash, TMDBchan, TileID::LOWGAIN);
723 if (sigma_Hfn1 > 0 || sigma_Hfn2) {
724 sigma_Norm = sigma_Hfn1 / (sigma_Hfn1 + sigma_Hfn2 * sampleNoise->getHfnNorm(idhash, TMDBchan, TileID::LOWGAIN));
725 } else {
726 sigma_Hfn1 = sampleNoise->getHfn(idhash, TMDBchan, TileID::LOWGAIN);
727 sigma_Norm = 1.;
728 }
729 if (Rndm_dG[0] < sigma_Norm) sigmaSim = sigma_Hfn1;
730 else sigmaSim = sigma_Hfn2;
731 } else {
732 sigmaSim = muRcv_NoiseSigma;
733 }
734 // Loop over samples and either use noise and ped from db or user location (TileInfoLoader.cxx)
735 //
736 for (int js = 0; js < m_nSamples; ++js) {
737 // Signal
738 //
739 ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" E [MeV]: "<< pDigitSamples[js]);
740 digitsBuffer[js] = pDigitSamples[js] * mev2ADC_factor;
741 ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" calibration [adc/MeV] "<< mev2ADC_factor <<"-> E [adc]: "<< digitsBuffer[js]);
742 // Pedestal (amp)
743 //
744 digitsBuffer[js] += pedSim;
745 ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" adding pedestal "<< pedSim <<"-> E [adc]: "<< digitsBuffer[js]);
746 // Noise (rms)
747 //
748 if (m_tileNoise) {
749 digitsBuffer[js] += sigmaSim * Rndm[js];
750 ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" adding noise "<< sigmaSim * Rndm[js] <<"-> E [adc]: "<< digitsBuffer[js]);
751 }
752 // Simulated pulse above allowed maximum
753 //
754 if (digitsBuffer[js] > muRcv_Max) digitsBuffer[js] = muRcv_Max;
755 // Rounding the ADC counts
756 //
757 if (m_integerDigits) digitsBuffer[js] = round(digitsBuffer[js]);
758 }
759 }
760
761 // If channel is good, create TileDigits object and store in container.
762 //
763 bool chanIsBad = false;
764
765 if (m_maskBadChannels) {
766 TileBchStatus status = badChannels->getAdcStatus( m_tileHWID->adc_id(drawer_id, TILEchan, TileID::LOWGAIN) );
767 chanIsBad = status.isBad();
768 }
769
770 if (chanIsBad) {
771 for (int js = 0; js < m_nSamples; ++js) {
772 digitsBuffer[js] = 255;// in TMDB we have 8-bit ADCs
773 }
774 ATH_MSG_VERBOSE( "(D.03) Masking Channel: "<< ros << '/' << drawer << '/' << TILEchan <<" ("<< TMDBchan <<") LowGain" );
775 } else {
776 ATH_MSG_VERBOSE( "(D.03) Good Channel : "<< ros << '/' << drawer << '/' << TILEchan <<" ("<< TMDBchan <<") LowGain" );
777 }
778
779 ATH_MSG_VERBOSE( "++ Changed to TMDB adc_id: " << m_tileHWID->to_string(adc_id) << " and save a TileDigits object into a container." );
780 std::unique_ptr<TileDigits> muonReceiverDigits = std::make_unique<TileDigits>(adc_id, digitsBuffer);
781 ATH_MSG_VERBOSE( "++ Create a TileRawChannelObject object and set it into a container " );
782 TileRawChannel* muRcvRawChannel = m_MuRcvBuildTool->rawChannel(muonReceiverDigits.get(), ctx);
783 ATH_CHECK( muRcvDigitsContainer->push_back(std::move(muonReceiverDigits)) );
784 ATH_CHECK( muRcvRawChannelContainer->push_back(muRcvRawChannel) );
785 if (msgLvl(MSG::DEBUG)){
786 ATH_MSG_DEBUG( "++ Channel " << m_tileHWID->to_string(adc_id,-1)
787 << " Digitized pulse [ADC] "<< digitsBuffer[0]
788 << "/" << digitsBuffer[1]
789 << "/" << digitsBuffer[2]
790 << "/" << digitsBuffer[3]
791 << "/" << digitsBuffer[4]
792 << "/" << digitsBuffer[5]
793 << "/" << digitsBuffer[6] );
794 ATH_MSG_DEBUG( "++ Raw channel reconstruction Ch: "<< m_tileHWID->to_string(adc_id,-1)
795 <<" E [ADC]: "<< muRcvRawChannel->amplitude()
796 <<" Time [ns]: "<< muRcvRawChannel->time()
797 <<" Qf: "<< muRcvRawChannel->quality() );
798 }
799 }
800 } // END loop over all HIT collections in container
801 if (msgLvl(MSG::VERBOSE)) muRcvDigitsContainer->print();
802
804 // (a.4) Register the digits container in the TES
805 //
806
807 ATH_MSG_VERBOSE ( "(A.05) Send to event store all collected objects " );
808
810 ATH_CHECK( muRcvDigitsCnt.record(std::move(muRcvDigitsContainer)) );
811
813 ATH_CHECK( muRcvRawChannelCnt.record(std::move(muRcvRawChannelContainer)) );
814
815 ATH_MSG_VERBOSE( "TilePulseForTileMuonReceiver execution completed" );
816
817 return StatusCode::SUCCESS;
818}
819
820// finalize
821//
823 ATH_MSG_VERBOSE("Finalizing TilePulseForTileMuonReceiver");
824
825 ATH_MSG_INFO("TilePulseForTileMuonReceiver finalized successfully");
826 return StatusCode::SUCCESS;
827}
#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.
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
#define nLBchan
#define nEBchan
Helper for holding non-const raw data prior to recording in SG.
Helper for holding non-const raw data prior to recording in SG.
#define y
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
AthAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor with parameters:
const ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
MsgStream & msg() const
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.
const_pointer_type retrieve()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
Condition object to keep Tile channel and ADC status.
const TileBchStatus & getAdcStatus(const HWIdentifier adc_id) const
Return Tile ADC status.
Class holding bad channel problems.
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
@ EXTBAR_NEG
Definition TileHWID.h:71
@ EXTBAR_POS
Definition TileHWID.h:70
ServiceHandle< TileCablingSvc > m_cablingSvc
Name of Tile cabling service.
SG::WriteHandleKey< TileDigitsContainer > m_muRcvDigitsContainerKey
int m_iTrig
Index of the triggering time slice.
SG::ReadHandleKey< TileHitContainer > m_hitContainerKey
double m_tileThresh
Actual threshold value.
ServiceHandle< PileUpMergeSvc > m_mergeSvc
double m_timeStep
Time step in pulse shape: 25.0 / nBinsPerX.
SG::ReadCondHandleKey< TilePulse > m_pulseShapeKey
Name of TilePulseShape in condition store.
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number service to use.
int m_nShape
Number of bins in pulse shape.
Gaudi::Property< std::string > m_infoName
const TileCablingService * m_cablingService
TileCabling instance.
SG::WriteHandleKey< TileRawChannelContainer > m_muRcvRawChannelContainerKey
virtual StatusCode initialize() override
initialize method
virtual StatusCode execute() override
execute method
int m_binTime0
Index of time=0 bin for pulse shape.
ToolHandle< TileRawChannelBuilderMF > m_MuRcvBuildTool
TilePulseForTileMuonReceiver(const std::string &name, ISvcLocator *pSvcLocator)
SG::ReadCondHandleKey< TileBadChannels > m_badChannelsKey
Name of TileBadChannels in condition store.
SG::ReadCondHandleKey< TileEMScale > m_emScaleKey
Name of TileEMScale in condition store.
int m_nBinsPerX
Number of bins per bunch crossing in pulse shape.
Gaudi::Property< std::string > m_randomStreamName
Random Stream Name.
int m_nSamples
Number of time slices for each channel.
SG::ReadHandleKey< TileDigitsContainer > m_inputDigitContainerKey
SG::ReadCondHandleKey< TileSamplingFraction > m_samplingFractionKey
Name of TileSamplingFraction in condition store.
SG::ReadCondHandleKey< TileSampleNoise > m_sampleNoiseKey
Name of TileSampleNoise in condition store.
virtual StatusCode finalize() override
finalize method
std::vector< double > m_shapeMuonReceiver
Muon receiver pulse shape.
Condition object to keep and provide Tile pulse shape.
Definition TilePulse.h:15
bool getPulseShapeYDY(unsigned int drawerIdx, unsigned int channel, unsigned int adc, float time, float &y, float &dy) const
Definition TilePulse.h:35
float time(int ind=0) const
float quality(int ind=0) const
float amplitude(int ind=0) const
Condition object to keep and provide Tile sample noise.
float getPed(unsigned int drawerIdx, unsigned int channel, unsigned int adc) const
float getHfn2(unsigned int drawerIdx, unsigned int channel, unsigned int adc) const
float getHfn1(unsigned int drawerIdx, unsigned int channel, unsigned int adc) const
float getHfn(unsigned int drawerIdx, unsigned int channel, unsigned int adc) const
float getHfnNorm(unsigned int drawerIdx, unsigned int channel, unsigned int adc) const
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
std::list< value_t > type
type of the collection of timed data object