ATLAS Offline Software
Loading...
Searching...
No Matches
TileHitToTTL1.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// Filename : TileHitToTTL1.cxx
7// Author : F. Merritt
8// Created : Feb, 2003
9//
10// DESCRIPTION:
11// Created to simulate the Tile Level 1 Trigger Towers (TTL1), which are
12// hardware sums of the Tile channels, about 5 channels per tower.
13// The towers are read out in N time slices, with N=9 as a default.
14// Noise can be added to every sample and threshold can be applied
15//
16// HISTORY:
17// August 2009: M. Dunford: Adding saturation of the MBTS pulses
18// March 2009: M. Dunford: Adding in bad channels. Now using the standard
19// pulse shape routines (instead of ascii files)
20//
21// BUGS:
22//
23//*****************************************************************************
24
25// Tile includes
32
33// Calo includes
37
38// Atlas includes
43// For the Athena-based random numbers.
46
47// Gaudi includes
48#include "GaudiKernel/ISvcLocator.h"
49
50//CLHEP includes
51#include <CLHEP/Random/Randomize.h>
52
53//C++ STL includes
54#include <vector>
55#include <algorithm>
56
57
58using CLHEP::RandGaussQ;
59
60
61
62//
63// Alg standard initialize function
64//
66
67 // retrieve CaloLVL1_ID, TileID, TileHWID helpers and TileIfno from det store
68
69 ATH_CHECK( detStore()->retrieve(m_TT_ID) );
70
71 ATH_CHECK( detStore()->retrieve(m_tileID) );
72
73 ATH_CHECK( detStore()->retrieve(m_tileTBID) );
74
75 ATH_CHECK( detStore()->retrieve(m_tileHWID) );
76
77 //=== Get Tile Info
78 ATH_CHECK( detStore()->retrieve(m_tileInfo, m_infoName) );
79
81
82 ATH_CHECK( m_emScaleKey.initialize() );
83
84 //=== Get rndm number service
85 ATH_CHECK( m_rndmSvc.retrieve() );
86
87 ATH_CHECK( m_samplingFractionKey.initialize() );
88
89 ATH_CHECK( m_cablingSvc.retrieve() );
90 m_cabling = m_cablingSvc->cablingService();
91
92 // The 'cosmics' setting refers to running with the
93 // Tile/Chicago Cosmic boards instead of the L1Calo
94 // This is a pre-2009 configuration
95 // The 'standard' setting is the L1Calo configuration
96 m_cosmicsType = (m_TileTTL1Type == "Cosmics");
97
98 if (m_TileTTL1Type == "Cosmics") {
99 ATH_MSG_INFO( "Cosmics TTL1 type selected" );
100
101 } else if (m_TileTTL1Type == "Standard") {
102 ATH_MSG_INFO( "Standard TTL1 type selected" );
103
104 } else {
105 ATH_MSG_INFO( "TileHitToTTL1 failed to recognize the TileTTL1Type: " << m_TileTTL1Type );
106 return StatusCode::FAILURE;
107 }
108
109 if (m_mbtsTTL1ContainerKey.key().empty()) {
110 ATH_MSG_INFO( "TileTTL1 from MBTS will not be produced" );
111 } else {
112 ATH_MSG_INFO( "Storing MBTS TileTTL1 in separate container " << m_mbtsTTL1ContainerKey.key() );
113 }
115
116 if (m_maskBadChannels) {
117 ATH_MSG_INFO( "Bad Channel trigger status will be applied" );
118 } else {
119 ATH_MSG_INFO( "Bad Channel trigger status will be ignored" );
120 }
121
122 /*............................................................................*/
123 // Get all global parameters that will be needed for processing
124 // For Cosmics, convolute sub-hits with full shape, producing a fine-grained
125 // vector for each tower. After noise/pedestal, calculate peak value and
126 // put only that in TileTTL1 object, otherwise TileTTL1 will be too large.
127 // For now, use the same shape for L1 and cosmics, but the latter should
128 // be wider, will change soon.
129 // For Standard L1, also convolute sub-hits with fine-grained shape, but
130 // produce sample-grained vector in TileTTL1.*/
131 // Load the pulse shape (so as to not perform this on every execution)
132 // The pulse shape for the MBTS, L1Calo (standard) config and the
133 // cosmics config is the same
134 // Right now the phase is set to zero (the pulse is centered)
135 m_nSamples = m_tileInfo->NdigitSamples(); // number of time slices for each chan
136 m_iTrig = m_tileInfo->ItrigSample(); // index of the triggering time slice
137 double phase = 0.0;
138 std::vector<double> ttl1Shape(m_nSamples, 0.);
139 m_tileInfo->ttl1Shape(m_nSamples, m_iTrig, phase, ttl1Shape);
140 if (msgLvl(MSG::DEBUG)) {
141 for (int jsamp = 0; jsamp < m_nSamples; ++jsamp) {
142 msg(MSG::DEBUG) << "jsamp=" << jsamp << " ttl1shape=" << ttl1Shape[jsamp] << endmsg;
143 } // end of pulse shape loading
144 }
145
146 // Data for MBTS
147 // The MBTS have a special hardware configuration. The trigger uses the tower
148 // output but the high gain from the 3&1 card
149 m_MBTSiTrig = m_tileInfo->ItrigSample();
150 m_MBTSnSamples = m_tileInfo->NdigitSamples();
151
152 // Get TileNoise flag from TileInfo (true => generate noise in TileDigits)
153 m_tileNoise = m_tileInfo->TileNoise();
154 // Get TileZeroSuppress flag from TileInfo (true => apply threshold to Digits)
155 m_tileThresh = m_tileInfo->TileZeroSuppress();
156
157 if (msgLvl(MSG::DEBUG)) {
158 msg(MSG::DEBUG) << " TTL1Shape[" << m_iTrig << "]=" << ttl1Shape[m_iTrig] << endmsg;
159
160 msg(MSG::DEBUG) << " nSamples=" << m_nSamples
161 << ", iTrig=" << m_iTrig
162 << ", tileNoise=" << ((m_tileNoise) ? "true" : "false")
163 << ", tileThresh=" << ((m_tileThresh) ? "true" : "false") << endmsg;
164 }
165
166 ATH_CHECK( m_hitContainerKey.initialize() );
167 ATH_CHECK( m_ttl1ContainerKey.initialize() );
168
169 ATH_MSG_INFO( "TileHitToTTL1 initialization completed" );
170
171 return StatusCode::SUCCESS;
172}
173/*==========================================================================*/
174//
175// Begin Execution Phase.
176//
177StatusCode TileHitToTTL1::execute(const EventContext &ctx) const {
178
179 ATH_MSG_DEBUG( "Executing TileHitToTTL1" );
180
181 // declare array for random number generation for noise in samples.
182 double Rndm[16]; // Can't use variable size array
183
184 // Prepare RNG Service
185 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
186 rngWrapper->setSeed( m_randomStreamName, ctx );
187
189 ATH_CHECK( emScale.isValid() );
190
191 const TileBadChannels* badChannels = nullptr;
192 if (m_maskBadChannels) {
194 ATH_CHECK( badChannelsHandle.isValid() );
195 badChannels = *badChannelsHandle;
196 }
197
198 /*........................................................................*/
199 // Get hit container from TES and create TTL1 and MBTS container
200 // Note that hit container has 256 collections (one for each drawer),
201 // but TTL1 container has no collections and no structure
202 /*........................................................................*/
203
205 ATH_CHECK( hitContainer.isValid() );
206
208 // Register the TTL1 container in the TES
209 ATH_CHECK( ttl1Container.record(std::make_unique<TileTTL1Container>()) );
210 ATH_MSG_DEBUG( "TileTTL1Container registered successfully (" << m_ttl1ContainerKey.key() << ")" );
211
212 std::unique_ptr<TileTTL1Container> mbtsTTL1Container;
213 if (!m_mbtsTTL1ContainerKey.key().empty()) {
214 mbtsTTL1Container = std::make_unique<TileTTL1Container>();
215 }
216
218 ATH_CHECK( samplingFraction.isValid() );
219
220 /*........................................................................*/
221 // Create temporary arrays for processing signals.
222 // Create array for all TT amplitudes in a single drawer
223 /*........................................................................*/
224 Identifier ttId[16]; // array of TT identifiers in a single drawer
225 std::vector<double> ttAmp[16]; // array of all TT amplitudes in a single drawer
226 std::vector<double> MBTSAmp; // MBTS amplitudes in a single drawer
227 bool ttHit[16]; // array of TT occupancy in a single drawer
228 bool MBTSHit; // MBTS occupancy in a single drawer
229 int nTT; // number of hit towers in this drawer.
230 int nHit; // number of hits in this drawer.
231 int nIgnore; // number of ignored hits in this drawer.
232 int nTTTot = 0; // total number of hit towers.
233 int nHitTot = 0; // total number of hits.
234 int nIgnoreTot = 0; // total number of ignored hits.
235 double ttAmpTot = 0; // total energy in good level-1 towers.
236 double ttAmpTotIg = 0.; // total energy in "ignored" level-1 towers.
237 int minieta, maxieta, posneg;
238
239 for (int ieta = 0; ieta < 16; ++ieta)
240 ttAmp[ieta].resize(m_nSamples);
241 MBTSAmp.resize(m_MBTSnSamples);
242
243 // temporary array to make sub of all subhits in one channel
244 std::vector<double> hitSamples(m_nSamples);
245
246 // Create array for the nSamples time-samples of a single tower.
247 // If running the Cosmics configuration, put out only the peak value
248 std::vector<float> ttL1samples;
249 std::vector<float> MBTSsamples;
250 if (m_cosmicsType) ttL1samples.resize(1);
251 else ttL1samples.resize(m_nSamples);
252 MBTSsamples.resize(m_MBTSnSamples);
253
254 std::vector<double> ttl1Shape(m_nSamples, 0.);
255 std::vector<double> ttl1MBTSShape(m_MBTSnSamples, 0.);
256 /*........................................................................*/
257 // Begin loop over all collections (collection = electronic drawer).
258 /*........................................................................*/
259
260 for (const TileHitCollection* hitCollection : *hitContainer) {
261
262 // get drawer and ros number
263 HWIdentifier drawer_id = m_tileHWID->drawer_id(hitCollection->identify());
264 int ros = m_tileHWID->ros(drawer_id);
265 int drawer = m_tileHWID->drawer(drawer_id);
266 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
267
268 // check that this drawer is connected, if not skip it
269 if (m_cosmicsType || m_cabling->connected(ros, drawer)) {
270 ATH_MSG_VERBOSE( "ROS " << ros
271 << " drawer " << drawer
272 << " is connected");
273 } else {
274 continue;
275 }
276
277 // Find the partition for this drawer
278 // Also set the min and max eta range for the towers in this partition
279 switch (ros) {
281 posneg = +1;
282 minieta = 0;
283 maxieta = 8;
284 break;
286 posneg = -1;
287 minieta = 0;
288 maxieta = 8;
289 break;
291 posneg = +1;
292 minieta = 9;
293 maxieta = m_lastTower;
294 break;
296 posneg = -1;
297 minieta = 9;
298 maxieta = m_lastTower;
299 break;
300 default:
301 posneg = minieta = maxieta = 0;
302 break;
303 }
304
305 // Zero temporary array of trigger tower amplitudes (TTL1amp) for this collection
306 for (int ieta = 0; ieta < 16; ++ieta) {
307 for (int js = 0; js < m_nSamples; ++js)
308 ttAmp[ieta][js] = 0.0;
309 }
310 for (int js = 0; js < m_MBTSnSamples; ++js)
311 MBTSAmp[js] = 0.0;
312
313 MBTSHit = false;
314 memset(ttHit, 0, sizeof(ttHit));
315 nTT = nIgnore = nHit = 0;
316
317 /*........................................................................*/
318 // Iterate over all hits in this collection, summing amps for each tower.
319 /*........................................................................*/
320 for (const TileHit* tile_hit : *hitCollection) {
321
322 // Get hit Identifier (= pmt_id)
323 Identifier pmt_id = tile_hit->pmt_ID();
324 // Get hit HWIdentifier (= channel_id)
325 HWIdentifier pmt_HWid = tile_hit->pmt_HWID();
326 // Get channel and ADC number
327 int channel = m_tileHWID->channel(pmt_HWid);
328
329 // conversion to hit energy after EMscale correction
330 double hit_calib = samplingFraction->getSamplingFraction(drawerIdx, channel);
331 hit_calib = std::round(hit_calib * 1000) / 1000;
332 // conversion to charge measured by digitizer
333 // The trigger always uses the low gain
334 double qfactor = hit_calib / emScale->calibrateChannel(drawerIdx, channel
335 , TileID::LOWGAIN, 1.
338
339 // determine if the channel is good from the channel status DB
340 bool is_good = true;
341 if (m_maskBadChannels) {
342 HWIdentifier adc_id = m_tileHWID->adc_id(pmt_HWid, TileID::LOWGAIN);
343 TileBchStatus status = badChannels->getAdcStatus(adc_id);
344
345 // if channel is bad, set qfactor to zero
346 if (status.isNoGainL1()) {
347 is_good = false;
348 qfactor = 0.0;
349 }
350
351 // check if channel is half gain, scale the qfactor by 50%
352 if (status.isHalfGainL1()) {
353 is_good = false;
354 qfactor *= 0.5;
355 }
356
357 } // end of bad channel status
358
359 // Treat signal from MBTS differently
360 if (m_tileTBID->is_tiletb(pmt_id)) {
361
362 if (mbtsTTL1Container) {
363
364 // Loop over the subhits for this channel. For each one,
365 // convolute with shaping function and add to digitSamples.
366 for (int js = 0; js < m_MBTSnSamples; ++js)
367 hitSamples[js] = 0.0;
368
369 int n_hits = tile_hit->size();
370 for (int ihit = 0; ihit < n_hits; ++ihit) {
371 // Need to pass the negative of t_hit, this is because ttl1Shape returns the amplitude at
372 // a given phase, whereas the t_hit from t=0 when the hit took place
373 double t_hit = -(tile_hit->time(ihit));
374 m_tileInfo->ttl1Shape(m_MBTSnSamples, m_MBTSiTrig, t_hit, ttl1MBTSShape);
375
376 double e_hit = tile_hit->energy(ihit);
377 for (int js = 0; js < m_MBTSnSamples; ++js) {
378 hitSamples[js] += e_hit * ttl1MBTSShape[js];
379 } // end of loop over MBTS samples
380 } // end loop over sub-hits
381
382 if (MBTSHit) {
383 for (int js = 0; js < m_MBTSnSamples; ++js)
384 MBTSAmp[js] += qfactor * hitSamples[js];
385
386 } else {
387 MBTSHit = true;
388 for (int js = 0; js < m_MBTSnSamples; ++js)
389 MBTSAmp[js] = qfactor * hitSamples[js];
390 }
391
392 if (msgLvl(MSG::VERBOSE)) {
393
394 // Diagnostic checks
395 int side = m_tileTBID->type(pmt_id);
396 int phi = m_tileTBID->module(pmt_id);
397 int eta = m_tileTBID->channel(pmt_id);
398 int channel = m_tileHWID->channel(pmt_HWid);
399
400 msg(MSG::VERBOSE) << "New MBTS Hit:"
401 << " ros=" << ros
402 << ", drawer=" << drawer
403 << ", ch=" << channel
404 << ", side=" << side
405 << ", phi=" << phi
406 << ", eta=" << eta
407 << ", e0=" << hitSamples[m_MBTSiTrig] * hit_calib
408 << ", chan is good=" << is_good << endmsg;
409 }
410 }
411 continue;
412 } // end of MBTS loop
413
414 // Get TT Identifier for this pmt
415 Identifier tt_id = tile_hit->tt_ID();
416
417 // Get eta-phi indices of TTL1 for this channel.
418 int ieta = m_TT_ID->eta(tt_id);
419 int iphi = m_TT_ID->phi(tt_id); // (same as module number).
420 if (iphi != drawer && m_tileID->sample(pmt_id) != TileID::SAMP_E)
421 ATH_MSG_ERROR( "drawer=" << drawer << ", iphi=" << iphi );
422
423 // Loop over the subhits for this channel. For each one,
424 // convolute with shaping function and add to digitSamples.
425 for (int js = 0; js < m_nSamples; ++js)
426 hitSamples[js] = 0.0;
427 int n_hits = tile_hit->size();
428 for (int ihit = 0; ihit < n_hits; ++ihit) {
429 // Need to pass the negative of t_hit, this is because ttl1Shape returns the amplitude at
430 // a given phase, whereas the t_hit from t=0 when the hit took place
431 double t_hit = -(tile_hit->time(ihit));
432 m_tileInfo->ttl1Shape(m_nSamples, m_iTrig, t_hit, ttl1Shape);
433
434 double e_hit = tile_hit->energy(ihit);
435 for (int js = 0; js < m_nSamples; ++js) {
436 hitSamples[js] += e_hit * ttl1Shape[js];
437 } // end of loop over samples
438 } // end loop over sub-hits
439
440 // check if TT already exists, if so just add energy
441 if (ttHit[ieta]) {
442 for (int js = 0; js < m_nSamples; ++js)
443 ttAmp[ieta][js] += qfactor * hitSamples[js];
444
445 // if not create new TT
446 } else {
447 ttId[ieta] = tt_id;
448 ttHit[ieta] = true;
449 for (int js = 0; js < m_nSamples; ++js)
450 ttAmp[ieta][js] = qfactor * hitSamples[js];
451
452 if (ieta >= minieta && ieta <= maxieta)
453 ++nTT; // count only valid TT
454 }
455 ++nHit;
456 if (ieta < minieta || ieta > maxieta || !is_good)
457 ++nIgnore;
458
459 //Sum cell energy for comparison to other algos.
460 if (ieta >= minieta && ieta <= maxieta && is_good) {
461 ttAmpTot += hitSamples[m_iTrig] * hit_calib;
462 } else {
463 ttAmpTotIg += hitSamples[m_iTrig] * hit_calib;
464 }
465
466 if (msgLvl(MSG::VERBOSE)) {
467
468 // Diagnostic checks:
469 int side = m_tileID->side(pmt_id);
470 int tower = m_tileID->tower(pmt_id);
471 int sample = m_tileID->sample(pmt_id);
472 int pmt = m_tileID->pmt(pmt_id);
473 int channel = m_tileHWID->channel(pmt_HWid);
474
475 msg(MSG::VERBOSE) << "New Hit:"
476 << " ros=" << ros
477 << ", drawer=" << drawer
478 << ", ch=" << channel
479 << ", side=" << side
480 << ", tower=" << tower
481 << ", sample=" << sample
482 << ", pmt=" << pmt
483 << ", e0=" << hitSamples[m_iTrig] * hit_calib
484 << ", ie=" << ieta
485 << ", ip=" << iphi
486 << ", chan is good= " << is_good;
487
488 if (ieta >= minieta && ieta <= maxieta)
489 msg(MSG::VERBOSE) << endmsg;
490 else
491 msg(MSG::VERBOSE) << " Outside limits" << endmsg;
492 } // end of verbose printing
493
494 } // end loop over hits in this drawer.
495
496 nTTTot += nTT;
497 nHitTot += nHit;
498 nIgnoreTot += nIgnore;
499
500 ATH_MSG_VERBOSE( " Statistics for"
501 << " ROS=" << ros
502 << ", drawer=" << drawer
503 << "; posneg=" << posneg
504 << ", minieta=" << minieta
505 << ", maxieta=" << maxieta
506 << "; nTT=" << nTT
507 << ", nHit=" << nHit
508 << ", nIgnore=" << nIgnore );
509
510
511 /*........................................................................*/
512 // We now have all the TTL1 amplitudes for this drawer.
513 // Loop over towers to produce the electronics signals (= time samples).
514 // If tileNoise is requested, generate random numbers to give noise
515 // For Cosmics configuration, only calculate peak value.
516 // (no ADC on Chicago custom board, only discriminator)
517 /*........................................................................*/
518
519 if (mbtsTTL1Container) {
520 Identifier MBTS_id = m_cabling->drawer2MBTS_id(drawer_id);
521 if (MBTS_id.is_valid()) {
522 bool Good = m_tileNoise || MBTSHit;
523 if (Good) {
524 double ttL1NoiseSigma = m_tileInfo->MBTSL1NoiseSigma(MBTS_id);
525 double ttL1Thresh = m_tileInfo->MBTSL1Thresh(MBTS_id);
526 double ttL1Ped = m_tileInfo->MBTSL1Ped(MBTS_id);
527 double ttL1Calib = m_tileInfo->MBTSL1Calib(MBTS_id);
528 double ttL1Max = m_tileInfo->MBTSL1Max(MBTS_id);
529
530 if (m_tileNoise)
531 RandGaussQ::shootArray(rngWrapper->getEngine(ctx), m_MBTSnSamples, Rndm);
532 for (int jsamp = 0; jsamp < m_MBTSnSamples; ++jsamp) {
533 MBTSAmp[jsamp] *= ttL1Calib; // convert pCb to mV
534 MBTSsamples[jsamp] = MBTSAmp[jsamp] + ttL1Ped;
535 if (m_tileNoise)
536 MBTSsamples[jsamp] += ttL1NoiseSigma * Rndm[jsamp];
537
538 // check if the voltage is above the saturation point,
539 // if so, set the pulse value to the saturation point
540 if (MBTSsamples[jsamp] > ttL1Max)
541 MBTSsamples[jsamp] = ttL1Max;
542
543 } // end loop over samples
544
545 if (m_tileThresh)
546 if (MBTSsamples[m_MBTSiTrig] - ttL1Ped < ttL1Thresh)
547 Good = false;
548
549 if (Good) {
550 std::unique_ptr<TileTTL1> mbtsTTL1 = std::make_unique<TileTTL1>(MBTS_id, MBTSsamples);
551 mbtsTTL1Container->push_back(mbtsTTL1.release());
552 ATH_MSG_DEBUG( "mbtsTTL1 saved. Is MBTS hit " << MBTSHit
553 << " Is noise " << m_tileNoise );
554 }
555 }
556 }
557 }
558
559 for (int ieta = minieta; ieta <= maxieta; ++ieta) {
560 int iphi = drawer;
561 bool Good = m_tileNoise || ttHit[ieta];
562 if (Good) {
563 if (!ttHit[ieta])
564 ttId[ieta] = m_TT_ID->tower_id(posneg, 1, 0, ieta, drawer);
565
566 /* Include shaping fuction, pedestal, and noise. */
567
568 // Chicago cosmic Trigger board
569 if (m_cosmicsType) {
570 double ttL1NoiseSigma = m_tileInfo->TTL1CosmicsNoiseSigma(ttId[ieta]);
571 double ttL1Thresh = m_tileInfo->TTL1CosmicsThresh(ttId[ieta]);
572 double ttL1Ped = m_tileInfo->TTL1CosmicsPed(ttId[ieta]);
573 double ttL1Calib = m_tileInfo->TTL1CosmicsCalib(ttId[ieta]);
574
575 double peakAmp = 0.0;
576 int peakSamp = 0;
577 for (int jsamp = 0; jsamp < m_nSamples; ++jsamp) {
578 ttAmp[ieta][jsamp] *= ttL1Calib; // convert pCb to mV
579 ttAmp[ieta][jsamp] += ttL1Ped;
580 if (ttAmp[ieta][jsamp] > peakAmp) {
581 peakAmp = ttAmp[ieta][jsamp];
582 peakSamp = jsamp;
583 }
584 } // end loop over samples
585
586 if (m_tileNoise)
587 peakAmp += ttL1NoiseSigma * RandGaussQ::shoot(rngWrapper->getEngine(ctx));
588 ttL1samples[0] = peakAmp;
589 if (m_tileThresh) {
590 if (ttL1samples[0] - ttL1Ped < ttL1Thresh)
591 Good = false;
592 }
593 if (msgLvl(MSG::DEBUG) && Good) {
594 msg(MSG::DEBUG) << " TTL1: "
595 << " ros=" << ros
596 << ", ieta=" << ieta
597 << ", iphi=" << iphi
598 << ", hitTrue=" << ttHit[ieta]
599 << ", Good=" << Good
600 << ", peak Amp=" << ttAmp[ieta][peakSamp]
601 << ", with noise=" << ttL1samples[0] << endmsg;
602 }
603
604 // ATLAS Level1 Calo Trigger
605 } else {
606 double ttL1NoiseSigma = m_tileInfo->TTL1NoiseSigma(ttId[ieta]);
607 double ttL1Thresh = m_tileInfo->TTL1Thresh(ttId[ieta]);
608 double ttL1Ped = m_tileInfo->TTL1Ped(ttId[ieta]);
609 double ttL1Calib = m_tileInfo->TTL1Calib(ttId[ieta]);
610 double ttL1Max = m_tileInfo->TTL1Max(ttId[ieta]);
611
612 if (m_tileNoise)
613 RandGaussQ::shootArray(rngWrapper->getEngine(ctx), m_nSamples, Rndm);
614 for (int jsamp = 0; jsamp < m_nSamples; ++jsamp) {
615 ttAmp[ieta][jsamp] *= ttL1Calib; // convert pCb to mV
616 ttL1samples[jsamp] = ttAmp[ieta][jsamp] + ttL1Ped;
617 if (m_tileNoise)
618 ttL1samples[jsamp] += ttL1NoiseSigma * Rndm[jsamp];
619
620 // check if the voltage is above the saturation point,
621 // if so, set the pulse value to the saturation point
622 if (ttL1samples[jsamp] > ttL1Max)
623 ttL1samples[jsamp] = ttL1Max;
624
625 } // end loop over samples
626
627 if (m_tileThresh) {
628 if (ttL1samples[m_iTrig] - ttL1Ped < ttL1Thresh)
629 Good = false;
630 }
631 if (msgLvl(MSG::DEBUG) && Good) {
632 msg(MSG::DEBUG) << " TTL1: "
633 << " ros=" << ros
634 << ", ieta=" << ieta
635 << ", iphi=" << iphi
636 << ", hitTrue=" << ttHit[ieta]
637 << ", Good=" << Good
638 << ", amp0=" << ttAmp[ieta][m_iTrig]
639 << ", digitIn=" << ttL1samples[m_iTrig] << endmsg;
640 }
641 }
642 } // end first "Good" section.
643
644 /* Create the new TTL1 object and store in TTL1Container. */
645 if (Good) {
646 std::unique_ptr<TileTTL1> ttl1 = std::make_unique<TileTTL1>(ttId[ieta], ttL1samples);
647 ttl1Container->push_back(ttl1.release());
648 } // end second "Good" section.
649 } // end loop over towers
650 } // end loop over collections
651
652 // sort all trigger towers according to identifier
653 if (m_cosmicsType) {
654 ATH_MSG_DEBUG( "Sorting container of size " << ttl1Container->size() );
656 ttl1Container->sort(order);
657 }
658
659 if (mbtsTTL1Container) {
661 ATH_CHECK( mbtsContainer.record(std::move(mbtsTTL1Container)));
662
663 ATH_MSG_DEBUG( "MBTS TileTTL1Container registered successfully (" << m_mbtsTTL1ContainerKey.key() << ")" );
664 }
665
666 // Execution completed.
667 if (msgLvl(MSG::DEBUG)) {
668 msg(MSG::DEBUG) << "TileHitToTTL1 execution completed." << endmsg;
669 msg(MSG::DEBUG) << " nTTTot=" << nTTTot
670 << " nHitTot=" << nHitTot
671 << " nIgnoreTot=" << nIgnoreTot
672 << " ttAmpTot=" << ttAmpTot
673 << " ttAmpTotIg=" << ttAmpTotIg
674 << " =>eneTot=" << ttAmpTot + ttAmpTotIg << endmsg;
675 }
676
677 return StatusCode::SUCCESS;
678}
679
681
682 ATH_MSG_INFO( "TileHitToTTL1::finalize() end" );
683
684 return StatusCode::SUCCESS;
685}
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_DEBUG(x)
Helpers for checking error return status codes and reporting errors.
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
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 ServiceHandle< StoreGateSvc > & detStore() const
bool msgLvl(const MSG::Level lvl) const
bool is_valid() const
Check if id is in a valid state.
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.
@ BARREL_POS
Definition TileHWID.h:68
@ EXTBAR_NEG
Definition TileHWID.h:71
@ BARREL_NEG
Definition TileHWID.h:69
@ EXTBAR_POS
Definition TileHWID.h:70
Gaudi::Property< bool > m_maskBadChannels
ServiceHandle< TileCablingSvc > m_cablingSvc
Name of Tile cabling service.
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number generator engine to use.
SG::ReadHandleKey< TileHitContainer > m_hitContainerKey
bool m_tileThresh
If true => apply threshold on the conversion to TileTTL1.
const TileID * m_tileID
Pointer to TileID helper.
SG::WriteHandleKey< TileTTL1Container > m_mbtsTTL1ContainerKey
bool m_tileNoise
If true => generate noise for the TileTTL1 creation.
virtual StatusCode finalize() override
finalize method
const TileCablingService * m_cabling
Pointer to the TileCablingService instance.
virtual StatusCode initialize() override
initialize method
int m_MBTSiTrig
index of the triggering time slice for MBTS TTL1
const TileInfo * m_tileInfo
Pointer to TileInfo.
SG::ReadCondHandleKey< TileEMScale > m_emScaleKey
Name of TileEMScale in condition store.
SG::WriteHandleKey< TileTTL1Container > m_ttl1ContainerKey
const TileTBID * m_tileTBID
Pointer to TileID helper.
SG::ReadCondHandleKey< TileBadChannels > m_badChannelsKey
Name of TileBadChannels in condition store.
int m_MBTSnSamples
number of time slices for each chan for MBTS TTL1
Gaudi::Property< std::string > m_infoName
Gaudi::Property< std::string > m_TileTTL1Type
Gaudi::Property< std::string > m_randomStreamName
Random Stream Name.
const CaloLVL1_ID * m_TT_ID
Pointer to TT Identifier.
int m_lastTower
total number of towers in TileCal
int m_iTrig
index of the triggering time slice
int m_nSamples
number of time slices for each channel
const TileHWID * m_tileHWID
Pointer to TileHWID helper.
virtual StatusCode execute(const EventContext &ctx) const override
execute method
bool m_cosmicsType
if true => use dediated cosmcis TTL1
SG::ReadCondHandleKey< TileSamplingFraction > m_samplingFractionKey
Name of TileSamplingFraction in condition store.
class for ordering any TileData Objects according to logical (offline) identifier To be used with sor...