ATLAS Offline Software
Loading...
Searching...
No Matches
TileDigitsMaker.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5//****************************************************************************
6// Filename : TileDigitsMaker.cxx
7// Author : Zhifang
8// Created : Feb 2006 from TileHitToDigits
9//
10// DESCRIPTION:
11// Created to simulate the digits information (amplitudes of N time-slices,
12// with N about 9) received by the ROD's.)
13//
14// HISTORY:
15//
16// BUGS:
17//
18//*****************************************************************************
19
20// Tile includes
29
30// Calo includes
33
34// Atlas include
36// For the Athena-based random numbers.
39
40#include "AthenaKernel/Units.h"
44
45// Gaudi includes
46
47//CLHEP includes
48#include <CLHEP/Random/Randomize.h>
49
50
51#include "TMatrixF.h"
52#include "TDecompChol.h"
53#include "cmath"
54
55#include <algorithm>
56
57using CLHEP::RandGaussQ;
58using CLHEP::RandFlat;
59using Athena::Units::MeV;
60
61
62//
63// Alg standard initialize function
64//
66 // retrieve TileID helper and TileInfo from det store
67
68 ATH_CHECK( detStore()->retrieve(m_tileID) );
69
70 ATH_CHECK( detStore()->retrieve(m_tileTBID) );
71
72 ATH_CHECK( detStore()->retrieve(m_tileHWID) );
73
74 ATH_CHECK( detStore()->retrieve(m_tileInfo, m_infoName) );
75
76 //=== intialize TileEMScale condtion object
77 ATH_CHECK( m_emScaleKey.initialize() );
78
79 //=== initialize TileSampleNoise condition object
80 ATH_CHECK( m_sampleNoiseKey.initialize() );
81
82 ATH_CHECK( m_cablingSvc.retrieve() );
83 m_cabling = m_cablingSvc->cablingService();
84
85 /* Get needed parameters from tileInfo. */
86 m_nSamples = m_tileInfo->NdigitSamples(); // number of time slices for each chan
87 m_iTrig = m_tileInfo->ItrigSample(); // index of the triggering time slice
88 m_i_ADCmax = m_tileInfo->ADCmax(); // adc saturation value used in assignment
89 m_f_ADCmax = m_i_ADCmax; // adc saturation value used in assignment
90 m_f_ADCmaxHG = m_f_ADCmax - 0.5; // value of switch from high to low gain
93 m_f_ADCmaskValue = m_tileInfo->ADCmaskValue(); // indicates channels which were masked in background dataset
94 m_tileNoise = m_tileInfo->TileNoise(); // (true => generate noise in TileDigits)
95 m_tileCoherNoise = m_tileInfo->TileCoherNoise(); // (true => generate coherent noise in TileDigits)
96 m_tileThresh = m_tileInfo->TileZeroSuppress(); // (true => apply threshold to Digits)
97 m_tileThreshHi = m_tileInfo->ThresholdDigits(TileID::HIGHGAIN);
98 m_tileThreshLo = m_tileInfo->ThresholdDigits(TileID::LOWGAIN);
99
101 ATH_CHECK( m_rndmSvc.retrieve());
102 }
103
104 ATH_MSG_DEBUG( "Event Overlay: " << ((m_rndmEvtOverlay)?"true":"false"));
105 ATH_MSG_DEBUG( "Masking Channels: " << ((m_maskBadChannels)?"true":"false"));
106 ATH_MSG_DEBUG( "Using pulse shapes from COOL: " << ((m_useCoolPulseShapes)?"true":"false"));
107
109 ATH_CHECK( m_samplingFractionKey.initialize() );
110
112 ATH_MSG_DEBUG( "Initializing pulse shape conditions object");
113 } else {
114 /* Get fine-grained shaping profile (0.5-ns bins) for both gains*/
115 m_digitShapeHi = m_tileInfo->digitsFullShapeHi();
116 m_digitShapeHi.push_back(0.0);
117 m_digitShapeLo = m_tileInfo->digitsFullShapeLo();
118 m_digitShapeLo.push_back(0.0);
119 }
120
121 //=== Initialize bad channels key
123
124 m_nShapeHi = m_tileInfo->digitsNBinsHi();
125 m_nBinsPerXHi = m_tileInfo->digitsBinsPerXHi();
126 m_binTime0Hi = m_tileInfo->digitsTime0BinHi();
128
129 m_nShapeLo = m_tileInfo->digitsNBinsLo();
130 m_nBinsPerXLo = m_tileInfo->digitsBinsPerXLo();
131 m_binTime0Lo = m_tileInfo->digitsTime0BinLo();
133
136
137 if (m_rndmEvtOverlay) {
138 m_tileNoise = false;
139 m_tileCoherNoise = false;
140 m_tileThresh = false;
141 m_calibRun = false;
142 if (m_allChannels<0) m_allChannels = 2; // create all channels with noise in overlay by default
143
144 ATH_MSG_DEBUG( "Pileup and/or noise added by overlaying digits of random events");
145
146 // locate the PileUpMergeSvc and initialize our local ptr
148 ATH_CHECK( m_mergeSvc.retrieve() );
149 ATH_MSG_DEBUG( "PileUpMergeSvc successfully initialized");
150 }
151
152 ATH_CHECK( m_DQstatusKey.initialize() );
153
154 } else {
155 ATH_CHECK( m_DQstatusKey.initialize(!m_DQstatusKey.empty()) );
156
157 if (m_allChannels<0) m_allChannels = 0; // do not create all channels by default
158 if (m_tileNoise || m_tileCoherNoise) m_allChannels = 2; // unless noise is set to True
159 if (msgLvl(MSG::DEBUG)) {
160 msg(MSG::DEBUG) << "Obtained info from TileInfo" << endmsg;
161 msg(MSG::DEBUG) << "tileNoise=" << ((m_tileNoise) ? "true" : "false")
162 << ", tileCoherNoise=" << ((m_tileCoherNoise) ? "true" : "false")
163 << ", tileThresh=" << ((m_tileThresh) ? "true" : "false");
164 if (m_tileThresh)
165 msg(MSG::DEBUG) << ", thresh(hi,lo)=" << m_tileThreshHi << "," << m_tileThreshLo << endmsg;
166 else
167 msg(MSG::DEBUG) << endmsg;
168 }
169 }
170
171 if (m_allChannels>1)
172 ATH_MSG_DEBUG( "Create all channels with noise: true");
173 else if (m_allChannels>0)
174 ATH_MSG_DEBUG( "Create all channels without noise: true");
175 else
176 ATH_MSG_DEBUG( "Create all channels: false");
177
178 if (m_calibRun) {
180 }
181
182 if (!m_filteredDigitsContainerKey.key().empty()) {
183 ATH_MSG_DEBUG( "Keep digits with hit energy above " << m_filterThreshold / MeV
184 << " MeV in " << m_filteredDigitsContainerKey.key() << " container");
185 ATH_MSG_DEBUG( "Keep digits from MBTS with original G4 hit energy above "
186 << m_filterThresholdMBTS / MeV << " MeV ");
187
189
190 } else {
191 m_filterThreshold = HUGE_VALL;
192 m_filterThresholdMBTS = HUGE_VALL;
193 }
194
195 ATH_MSG_DEBUG( "nShapeHi=" << m_nShapeHi
196 << " nBinsPerXHi=" << m_nBinsPerXHi
197 << " timeStepHi=" << m_timeStepHi
198 << " binTime0Hi=" << m_binTime0Hi);
199
200 ATH_MSG_DEBUG( "nShapeLo=" << m_nShapeLo
201 << " nBinsPerXLo=" << m_nBinsPerXLo
202 << " timeStepLo=" << m_timeStepLo
203 << " binTime0Lo=" << m_binTime0Lo);
204
205 // decrease by 1, now they are indexes of last element in a vector
206 --m_nShapeHi;
207 --m_nShapeLo;
208
209 /* ==================================*/
210 // Store HWID's for all 12288 channels (48 channels in each of 64 drawers).
211 IdContext drawer_context = m_tileHWID->drawer_context();
212 int ndrawers = m_tileHWID->drawer_hash_max();
213 const int nchMax = 48; // number of channels per drawer
214
215 ATH_MSG_DEBUG( "ndrawers=" << ndrawers
216 << " nchMax=" << nchMax
217 << " HIGAIN=" << TileID::HIGHGAIN
218 << " LOWGAIN=" << TileID::LOWGAIN);
219
220 /* Store all (12288) Identifiers for the calorimeter adc's for HIGHAIN */
221 m_all_ids.reserve(ndrawers);
222 for (int dr = 0; dr < ndrawers; ++dr) {
223 HWIdentifier drawer_id;
224 m_tileHWID->get_id(dr, drawer_id, &drawer_context);
225
226 m_all_ids.push_back(std::make_unique<HWIdentifier[]>(nchMax));
227 std::unique_ptr<HWIdentifier[]>& adc_ids = m_all_ids.back();
228
229 int ros = m_tileHWID->ros(drawer_id);
230 if (ros > 0) {
231 int drawer = m_tileHWID->drawer(drawer_id);
232 IdentifierHash idhash;
233 m_tileHWID->get_hash(drawer_id, idhash, &drawer_context);
234 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
235 if (drawerIdx != (int)idhash) {
236 ATH_MSG_ERROR("drawer " << m_tileHWID->to_string(drawer_id, -2)
237 << " hash " << idhash << " NOT EQUAL to idx " << drawerIdx);
238 } else if (msgLvl(MSG::VERBOSE) && m_cabling->connected(ros, drawer)) {
239 msg(MSG::VERBOSE) << "drawer " << m_tileHWID->to_string(drawer_id, -2)
240 << " hash " << idhash << endmsg;
241 }
242
243 for (int ch = 0; ch < nchMax; ++ch) {
244 adc_ids[ch] = m_tileHWID->adc_id(drawer_id, ch, TileID::HIGHGAIN);
245 }
246 }
247 }
248
251
252 ATH_CHECK( m_hitContainerKey.initialize() );
253 ATH_CHECK( m_digitsContainerKey.initialize() );
254
255 ATH_MSG_DEBUG( "TileDigitsMaker initialization completed");
256
257 return StatusCode::SUCCESS;
258}
259
260
261StatusCode TileDigitsMaker::execute(const EventContext &ctx) const {
262 ATH_MSG_DEBUG( "Executing TileDigitsMaker");
263
264 // Prepare RNG service
265 ATHRNG::RNGWrapper* rngWrapper = nullptr;
266 CLHEP::HepRandomEngine* rngEngine = nullptr;
268 rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName);
269 rngWrapper->setSeed( m_randomStreamName, ctx );
270 rngEngine = rngWrapper->getEngine(ctx);
271 }
272
274 ATH_CHECK( sampleNoise.isValid() );
275
276 bool first = (msgLvl(MSG::VERBOSE) && ctx.evt() == 0 && !m_rndmEvtOverlay );
277 if (first) {
278 ATH_MSG_VERBOSE( "Dumping 2G noise parameters");
279 first = false;
280 IdContext drawer_context = m_tileHWID->drawer_context();
281 int ndrawers = m_tileHWID->drawer_hash_max();
282 const int nchMax = 48; // number of channels per drawer
283 for (int dr = 0; dr < ndrawers; ++dr) {
284 HWIdentifier drawer_id;
285 m_tileHWID->get_id(dr, drawer_id, &drawer_context);
286 int ros = m_tileHWID->ros(drawer_id);
287 int drawer = m_tileHWID->drawer(drawer_id);
288 if (m_cabling->connected(ros, drawer)) {
289 IdentifierHash idhash;
290 m_tileHWID->get_hash(drawer_id, idhash, &drawer_context);
291 for (int ch = 0; ch < nchMax; ++ch) {
292 double pedSimHi = sampleNoise->getPed(idhash, ch, TileID::HIGHGAIN);
293 double sigmaHi_Hfn1 = sampleNoise->getHfn1(idhash, ch, TileID::HIGHGAIN);
294 double sigmaHi_Hfn2 = sampleNoise->getHfn2(idhash, ch, TileID::HIGHGAIN);
295 double sigmaHi_Norm = sampleNoise->getHfnNorm(idhash, ch, TileID::HIGHGAIN);
296 double pedSimLo = sampleNoise->getPed(idhash, ch, TileID::LOWGAIN);
297 double sigmaLo_Hfn1 = sampleNoise->getHfn1(idhash, ch, TileID::LOWGAIN);
298 double sigmaLo_Hfn2 = sampleNoise->getHfn2(idhash, ch, TileID::LOWGAIN);
299 double sigmaLo_Norm = sampleNoise->getHfnNorm(idhash, ch, TileID::LOWGAIN);
300 ATH_MSG_VERBOSE( "Channel " << m_tileHWID->to_string(drawer_id,-2) << "/" << ch
301 << " pedHi="<< pedSimHi
302 << " pedLo="<< pedSimLo
303 << " rmsHi="<< sigmaHi_Hfn1 << "," << sigmaHi_Hfn2 << "," << sigmaHi_Norm
304 << " rmsLo="<< sigmaLo_Hfn1 << "," << sigmaLo_Hfn2 << "," << sigmaLo_Norm);
305
306 }
307 }
308 }
309 }
310
311 // declare array for random number generation
312 double Rndm[16]; // Can't use variable size array,
313 double RndmLo[16]; // Can't use variable size array,
314 double Rndm_dG[1]; // uniform random number for the double gaussian
315 double RndmLo_dG[1]; // uniform random number for the double gaussian
316
317 // step1: Get hit container from TES
319 ATH_CHECK( hitContainer.isValid() );
320
321 SG::ReadHandle<TileHitContainer> hitContainer_DigiHSTruth;
322 if(m_doDigiTruth){
323 hitContainer_DigiHSTruth = SG::ReadHandle<TileHitContainer> (m_hitContainer_DigiHSTruthKey, ctx);
324 ATH_CHECK( hitContainer_DigiHSTruth.isValid() );
325 }
326
327 // Zero sums for monitoring.
328 int nChSum = 0;
329 int nChHiSum = 0;
330 int nChLoSum = 0;
331 int nChHiAcc = 0;
332 int nChLoAcc = 0;
333 int nChHiFlt = 0;
334 int nChLoFlt = 0;
335 int nChHiCut = 0;
336 int nChLoCut = 0;
337 double echtot_Acc = 0.;
338 double echint_Acc = 0.;
339 double echtot_Cut = 0.;
340 double echint_Cut = 0.;
341 double HitSum = 0.;
342 double EneSum = 0.;
343 double RChSum = 0.;
344
345 /* step2: Set up Digits container */
346
347 auto digitsContainer = std::make_unique<TileMutableDigitsContainer>(true,
350 ATH_CHECK( digitsContainer->status() );
351
352 std::unique_ptr<TileMutableDigitsContainer> digitsContainer_DigiHSTruth;
353 if(m_doDigiTruth){
354 digitsContainer_DigiHSTruth = std::make_unique<TileMutableDigitsContainer>(true,
357 ATH_CHECK( digitsContainer_DigiHSTruth->status() );
358 }
359
360 std::unique_ptr<TileMutableDigitsContainer> filteredContainer;
361 if (!m_filteredDigitsContainerKey.key().empty()) {
362 filteredContainer = std::make_unique<TileMutableDigitsContainer>(true,
366 ATH_CHECK( filteredContainer->status() );
367 }
368
369 /* Set up buffers for handling information in a single collection. */
370 IdentifierHash idhash;
371 IdContext drawer_context = m_tileHWID->drawer_context();
372 const int nchMax = 48; // number of channels per drawer
373 std::vector<int> igain(nchMax, -1);
374 std::vector<int> ntot_ch(nchMax, 0);
375 std::vector<double> ech_tot(nchMax, 0.0);
376 std::vector<double> ech_int(nchMax, 0);
377 std::vector<double> ech_int_DigiHSTruth(nchMax, 0);
378 std::vector<int> over_gain(nchMax, -1);
379
380 /* Make a vector of digits (to be filled at the end from m_drawerBuffer arrays) */
381 std::vector<float> digitsBuffer(m_nSamples);
382 std::vector<float> digitsBufferLo(m_nSamples); // for calib runs
383 std::vector<float> digitsBuffer_DigiHSTruth(m_nSamples);
384 std::vector<float> digitsBufferLo_DigiHSTruth(m_nSamples); // for calib runs
385
386 std::vector<double> emptyBuffer;
387 std::vector<std::vector<double>> drawerBufferHi(nchMax, std::vector<double>(m_nSamples));
388 std::vector<std::vector<double>> drawerBufferLo(nchMax, std::vector<double>(m_nSamples));
389
390 std::vector<std::vector<double>> drawerBufferHi_DigiHSTruth;
391 std::vector<std::vector<double>> drawerBufferLo_DigiHSTruth;
392 if (m_doDigiTruth) {
393 drawerBufferHi_DigiHSTruth.resize(nchMax, std::vector<double>(m_nSamples));
394 drawerBufferLo_DigiHSTruth.resize(nchMax, std::vector<double>(m_nSamples));
395 }
396
397
398 /* everything for calculation of coherent noise */
399 // booleans for coherent noise
400 Bool_t coherNoiseHi = false;
401 Bool_t coherNoiseLo = false;
402 TMatrixD CorrWeightHi;
403 TMatrixD CorrWeightLo;
404 std::vector<std::unique_ptr<double[]>> CorrRndmVec;
405 std::vector<std::unique_ptr<double[]>> CorrRndmVecLo;
406 if (m_tileCoherNoise) {
407 for (int k = 0; k < m_nSamples; ++k) {
408 CorrRndmVec.push_back(std::make_unique<double[]>(nchMax));
409 }
410 if (m_calibRun) {
411 for (int k = 0; k < m_nSamples; ++k) {
412 CorrRndmVecLo.push_back(std::make_unique<double[]>(nchMax));
413 }
414 }
415 }
416
419 std::unique_ptr<TileMutableDigitsContainer> backgroundDigitContainer{};
420 if (m_rndmEvtOverlay) {
421 backgroundDigitContainer = std::make_unique<TileMutableDigitsContainer>(true,
424 ATH_CHECK( backgroundDigitContainer->status() );
425
428 TimedDigitContList digitContList;
429 ATH_CHECK( m_mergeSvc->retrieveSubEvtsData(m_inputDigitContainerName, digitContList));
430 ATH_MSG_DEBUG( "TileDigitsCnt successfully retrieved ");
431
432
433 if (digitContList.size() == 0) {
434 ATH_MSG_WARNING( "No overlay done ... ");
435 return StatusCode::SUCCESS;
436 }
437
438 TimedDigitContList::iterator iTzeroDigitCont(digitContList.begin());
439 for (const auto* digitCollection : *(iTzeroDigitCont->second)) {
440 for (const auto* digit : *digitCollection) {
441 auto pDigits = std::make_unique<TileDigits>(*digit);
442 ATH_CHECK(backgroundDigitContainer->push_back(std::move(pDigits)));
443 }
444 }
445 }
446 else if (!m_inputDigitContainerKey.empty()) {
448 if (tileDigitsContainerHandle.isValid()) {
449 for (const auto* digitCollection : *tileDigitsContainerHandle) {
450 for (const auto* digit : *digitCollection) {
451 auto pDigits = std::make_unique<TileDigits>(*digit);
452 ATH_CHECK(backgroundDigitContainer->push_back(std::move(pDigits)));
453 }
454 }
455 }
456 else {
457 ATH_MSG_ERROR("ReadHandle to Background Digits is invalid.");
458 return StatusCode::FAILURE;
459 }
460 }
461
462 collItrRndm = backgroundDigitContainer->begin();
463 lastCollRndm = backgroundDigitContainer->end();
464 }
465
467 ATH_CHECK( emScale.isValid() );
468
469 const TilePulse* pulse = nullptr;
472 ATH_CHECK( pulseShape.isValid() );
473 pulse = pulseShape.retrieve();
474 }
475
477 ATH_CHECK( samplingFraction.isValid() );
478
479 const TileDQstatus* dqStatus = nullptr;
480 if (m_rndmEvtOverlay) {
481 SG::ReadHandle<TileDQstatus> DQstatusHandle(m_DQstatusKey, ctx);
482 ATH_CHECK( DQstatusHandle.isValid() );
483 dqStatus = DQstatusHandle.get();
484 }
485
486 const TileBadChannels* badChannels = nullptr;
489 ATH_CHECK( badChannelsHandle.isValid() );
490 badChannels = badChannelsHandle.retrieve();
491 }
492
493 // iterate over all collections in a container
494 // Hit Container and signal hit container are the same size (1 entry per channel)
495 TileHitContainer::const_iterator collItr_DigiHSTruth;
496 if(m_doDigiTruth) collItr_DigiHSTruth = hitContainer_DigiHSTruth->begin();
497
498 /* ----------------------------------------------------------------- */
499 /* Begin loop over the Hit collections. All collections are defined */
500 /* (even if they have no hits), and all the digit information */
501 /* including pileup events are contained in the collection. */
502 /*-------------------------------------------------------------------*/
503 for (const TileHitCollection* hitCollection : *hitContainer) {
504 /* Get array of HWID's for this drawer (stored locally). */
505 HWIdentifier drawer_id = m_tileHWID->drawer_id(hitCollection->identify());
506 int ros = m_tileHWID->ros(drawer_id);
507 int drawer = m_tileHWID->drawer(drawer_id);
508 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
509 if (m_cabling->connected(ros, drawer)) {
510 ATH_MSG_VERBOSE( "ROS "<< ros << " drawer " << drawer << " is connected");
511 } else {
512 if (m_rndmEvtOverlay && collItrRndm != lastCollRndm) {
513 ++collItrRndm; // skip also one drawer in digi overlay container
514 }
515 if (m_doDigiTruth) {
516 ++collItr_DigiHSTruth;
517 } // End DigiHSTruth stuff
518 continue;
519 }
520
521 m_tileHWID->get_hash(drawer_id, idhash, &drawer_context);
522 const std::unique_ptr<HWIdentifier[]>& adc_ids = m_all_ids[idhash];
523
524 /* Initialize gain settings. If noise is requested, all channels are */
525 /* set to be active. If not, set them all to be inactive (gain=-1). */
526 /* Only those which contain actual hits will be set active when the */
527 /* hits are read in. */
528 int igainch = (m_allChannels) ? TileID::HIGHGAIN : -1;
529 if (m_rndmEvtOverlay) {
530 std::fill(over_gain.begin(), over_gain.end(), -1);
531 } else if (m_tileNoise || m_tileCoherNoise) {
532 igainch = TileID::HIGHGAIN;
533 }
534
535 std::fill(ech_tot.begin(), ech_tot.end(), 0.0);
536 std::fill(ech_int.begin(), ech_int.end(), 0.0);
537 std::fill(ntot_ch.begin(), ntot_ch.end(), 0);
538 std::fill(igain.begin(), igain.end(), igainch);
539
540 std::vector<std::reference_wrapper<std::vector<std::vector<double>>>> drawerBuffers{drawerBufferHi, drawerBufferLo};
541 if (m_doDigiTruth) {
542 drawerBuffers.push_back(drawerBufferHi_DigiHSTruth);
543 drawerBuffers.push_back(drawerBufferLo_DigiHSTruth);
544 }
545 for (std::vector<std::vector<double>>& drawerBuffer : drawerBuffers) {
546 for (std::vector<double>& digitsBuffer : drawerBuffer) {
547 std::fill(digitsBuffer.begin(), digitsBuffer.end(), 0);
548 }
549 }
550
551 if (m_rndmEvtOverlay && collItrRndm != lastCollRndm) {
552 const TileDigitsCollection *bkgDigitCollection(*collItrRndm);
553 ATH_CHECK(overlayBackgroundDigits(bkgDigitCollection, hitCollection, drawerBufferLo, drawerBufferHi,
554 igain, ros, drawer, drawerIdx, over_gain, *emScale, *sampleNoise, dqStatus, badChannels));
555 ++collItrRndm; // skip to next digi collection
556 }
557
558 std::vector<bool> signal_in_channel(nchMax, false);
559 std::vector<bool> signal_in_channel_DigiHSTruth(nchMax, false);
560 ATH_CHECK(fillDigitCollection( hitCollection, drawerBufferLo, drawerBufferHi,
561 igain, over_gain, ech_int, signal_in_channel, *emScale, *samplingFraction, pulse));
562 if(m_doDigiTruth){
563 ATH_CHECK(fillDigitCollection( *collItr_DigiHSTruth, drawerBufferLo_DigiHSTruth, drawerBufferHi_DigiHSTruth,
564 igain, over_gain, ech_int_DigiHSTruth, signal_in_channel_DigiHSTruth, *emScale, *samplingFraction, pulse));
565 } // End DigiHSTruth stuff
566
567 /* Now all signals for this collection are stored in m_drawerBuffer,
568 accessed with digitSamplesHi and digitSampleLo. */
569 if (msgLvl(MSG::VERBOSE)) {
570 for (int ich = 0; ich < nchMax; ++ich) {
571 if (igain[ich] > -1) {
572 std::vector<double>& digitSamplesHi = drawerBufferHi[ich];
573 std::vector<double>& digitSamplesLo = drawerBufferLo[ich];
574 msg(MSG::VERBOSE) << "total: ADC " << m_tileHWID->to_string(adc_ids[ich],-1) << "/" << igain[ich]
575 << " nhit=" << ntot_ch[ich]
576 << " e_ch=" << ech_tot[ich]
577 << " AinTHi=" << digitSamplesHi[m_iTrig]
578 << " AinTLo=" << digitSamplesLo[m_iTrig] << endmsg;
579 }
580 }
581 }
582
583 /* --------------------------------------------------------------- */
584 /* Now all signals for this drawer are stored in m_drawerBuffer arrays, */
585 /* and we are finished with TileHits for this collection. Loop over */
586 /* channels to add noise and pedestal. Check for saturation for */
587 /* each channel, and in case of saturation convert to low gain. */
588 /* -------------------------------------------------------------- */
589
590 // =============CORRELATION MODIFICATION (F Spano)==============
591 //
592 // Define CoVariance Matrix corresponding to noise.
593 // TO UPDATE:: Such Matrix will have to be loaded from database in the future; 1 matrix per drawer.
594 // NOW:
595 // a) define one covariance matrix
596 // b) find Cholesky decomposition use for corrlation building
597 // if this is set load the matrix
598 if (m_tileCoherNoise) {
599 ATH_MSG_VERBOSE( "Coherent noise for ROS " << ros
600 << " drawer " << drawer
601 << " with " << nchMax << " channels and "
602 << m_nSamples << "samples ");
603
604 // get decomposed covariance matrix for hi gain
605 coherNoiseHi = 1;
606 if (coherNoiseHi) {
607 CorrWeightHi.ResizeTo(*(m_tileInfo->DecoCovariance(ros, drawer, TileID::HIGHGAIN)));
608 CorrWeightHi = *(m_tileInfo->DecoCovariance(ros, drawer, TileID::HIGHGAIN));
609 }
610
611 // get decomposed covariance matrix for low gain
612 coherNoiseLo = 1;
613 if (coherNoiseLo) {
614 CorrWeightLo.ResizeTo(*(m_tileInfo->DecoCovariance(ros, drawer, TileID::LOWGAIN)));
615 CorrWeightLo = *(m_tileInfo->DecoCovariance(ros, drawer, TileID::LOWGAIN));
616 }
617
618 //NOTE: ShootArray's inputs are : the engine, the size, the vector, the mean, the standard dev
619 for (int k = 0; k < m_nSamples; ++k) {
620 double* RndmVec = CorrRndmVec[k].get();
621 RandGaussQ::shootArray(rngEngine, nchMax, RndmVec, 0.0, 1.0);
622 }
623
624 if (m_calibRun) {
625 for (int k = 0; k < m_nSamples; ++k) {
626 double * RndmVecLo = CorrRndmVecLo[k].get();
627 RandGaussQ::shootArray(rngEngine, nchMax, RndmVecLo, 0.0, 1.0);
628 }
629 }
630 }
631 // =============CORRELATION MODIFICATION (F Spano)============== end
632
633 // looping over channels
634 for (int ich = 0; ich < nchMax; ++ich) {
635 /* If igain<0, channel is inactive => skip it. */
636 if (igain[ich] < 0)
637 continue;
638
639 /* Generate the nSamp Digits for high gain. Check each for saturation. */
640 ++nChHiSum;
641 HWIdentifier adc_id = adc_ids[ich];
642 HWIdentifier adc_id_lo; // for calib runs
643 Identifier pmt_id = m_cabling->h2s_pmt_id(adc_id);
644 ATH_MSG_DEBUG( "Ch " << m_tileHWID->to_string(adc_id,-1)
645 << " PMT " << (pmt_id.is_valid() ? m_tileID->to_string(pmt_id,-1) : (signal_in_channel[ich] ? "fake gap" : "not connected"))
646 << " gain=" << igain[ich]);
647
649 adc_id_lo = m_tileHWID->adc_id(drawer_id, ich, TileID::LOWGAIN);
650 if (m_calibRun) {
651 ++nChLoSum;
652 }
653 }
654
655 bool chanLoIsBad = false;
656 bool chanHiIsBad = false;
657 if (m_maskBadChannels) {
658 TileBchStatus statusLo = badChannels->getAdcStatus(adc_id_lo);
659 TileBchStatus statusHi = badChannels->getAdcStatus(adc_id);
660 chanLoIsBad = statusLo.isBad();
661 chanHiIsBad = statusHi.isBad();
662 }
663
664 /* Get pedestal and noise values */
665 double pedSimHi(0.), sigmaHi_Hfn1(0.), sigmaHi_Hfn2(0.), sigmaHi_Norm(0.), pedSimLo(0.),
666 sigmaLo_Hfn1(0.), sigmaLo_Hfn2(0.), sigmaLo_Norm(0.);
667 bool good_ch = (over_gain[ich]<9);
668 bool overNoiseHG(over_gain[ich]!=TileID::HIGHGAIN && good_ch); // it's always true if no overlay
669 bool overNoiseLG(over_gain[ich]!=TileID::LOWGAIN && good_ch); // it's always true if no overlay
670 bool tileNoiseHG(false),tileNoiseLG(false);
671
672 if (overNoiseHG) {
673 overNoiseHG &= (m_rndmEvtOverlay && m_allChannels>1); // set it to true only for overlay
674 tileNoiseHG = m_tileNoise || overNoiseHG;
675
676 pedSimHi = sampleNoise->getPed(idhash, ich, TileID::HIGHGAIN);
677 // bug fix for wrong ped value in DB
678 if (pedSimHi == 0.0 && (signal_in_channel[ich] || pmt_id.is_valid()))
679 pedSimHi = 50.;
680
681 sigmaHi_Hfn1 = sampleNoise->getHfn1(idhash, ich, TileID::HIGHGAIN);
682 sigmaHi_Hfn2 = sampleNoise->getHfn2(idhash, ich, TileID::HIGHGAIN);
683 if (sigmaHi_Hfn1>0 || sigmaHi_Hfn2) {
684 sigmaHi_Norm = sigmaHi_Hfn1 / (sigmaHi_Hfn1
685 + sigmaHi_Hfn2 * sampleNoise->getHfnNorm(idhash, ich, TileID::HIGHGAIN));
686 } else {
687 sigmaHi_Hfn1 = sampleNoise->getHfn(idhash, ich, TileID::HIGHGAIN);
688 sigmaHi_Norm = 1.;
689 }
690 }
691
692 if (overNoiseLG) {
693 overNoiseLG &= (m_rndmEvtOverlay && m_allChannels>1); // set it to true only for overlay
694 tileNoiseLG = m_tileNoise || overNoiseLG;
695
696 pedSimLo = sampleNoise->getPed(idhash, ich, TileID::LOWGAIN);
697 // bug fix for wrong ped value in DB
698 if (pedSimLo == 0.0 && (signal_in_channel[ich] || pmt_id.is_valid()))
699 pedSimLo = 30.;
700
701 sigmaLo_Hfn1 = sampleNoise->getHfn1(idhash, ich, TileID::LOWGAIN);
702 sigmaLo_Hfn2 = sampleNoise->getHfn2(idhash, ich, TileID::LOWGAIN);
703 if (sigmaLo_Hfn1 > 0 || sigmaLo_Hfn2) {
704 sigmaLo_Norm = sigmaLo_Hfn1 / (sigmaLo_Hfn1
705 + sigmaLo_Hfn2 * sampleNoise->getHfnNorm(idhash, ich, TileID::LOWGAIN));
706 } else {
707 sigmaLo_Hfn1 = sampleNoise->getHfn(idhash, ich, TileID::LOWGAIN);
708 sigmaLo_Norm = 1.;
709 }
710 }
711
712 /* If tileNoise is requested, generate array of random numbers. */
713 if (tileNoiseLG) { // true if tileNoise is set or noise is needed for low gain in overlay
714 RandGaussQ::shootArray(rngEngine, m_nSamples, Rndm, 0.0, 1.0);
715 RandFlat::shootArray(rngEngine, 1, Rndm_dG, 0.0, 1.0);
716 if (m_calibRun) {
717 RandGaussQ::shootArray(rngEngine, m_nSamples, RndmLo, 0.0, 1.0);
718 RandFlat::shootArray(rngEngine, 1, RndmLo_dG, 0.0, 1.0);
719 }
720 }
721
722 std::vector<double>& digitSamplesHi = drawerBufferHi[ich];
723 std::vector<double>& digitSamplesLo = drawerBufferLo[ich];
724 std::vector<double>& digitSamplesHi_DigiHSTruth = (m_doDigiTruth) ? drawerBufferHi_DigiHSTruth[ich] : emptyBuffer;
725 std::vector<double>& digitSamplesLo_DigiHSTruth = (m_doDigiTruth) ? drawerBufferLo_DigiHSTruth[ich] : emptyBuffer;
726
727 ATH_MSG_DEBUG(" Channel " << ros << '/' << drawer << '/' << ich
728 << " sampHi=" << digitSamplesHi[m_iTrig]
729 << " pedHi=" << pedSimHi
730 << " sampLo=" << digitSamplesLo[m_iTrig]
731 << " pedLo=" << pedSimLo);
732
733 // looping over samples
734 for (int js = 0; js < m_nSamples; ++js) {
735
736 digitsBuffer[js] = digitSamplesHi[js] + pedSimHi;
737 if(m_doDigiTruth) {
738 digitsBuffer_DigiHSTruth[js] = digitSamplesHi_DigiHSTruth[js] + pedSimHi;
739 }
740
741 double noiseHi(0.0);
742 // Full noise pattern, including coherent noise has priority over normal noise //F Spano'
743 if (coherNoiseHi) {
744 // get the js-th correct random vector of 48 elements for the jsth sample k //F Spano'
745 std::unique_ptr<double[]>& CorVec = CorrRndmVec[js];
746 // apply Y=C*Z where Z is the random vector of 48 normal indep variables, and C is the Cholesky decomposition //F Spano'
747 for (int i = 0; i < nchMax; ++i) noiseHi += CorrWeightHi(i, ich) * CorVec[i];
748 } else if (tileNoiseHG) {
749 //using the same gaussian(sigma) for all samples in one channel in one event
750 if (Rndm_dG[0] < sigmaHi_Norm) noiseHi = sigmaHi_Hfn1 * Rndm[js];
751 else noiseHi = sigmaHi_Hfn2 * Rndm[js];
752 }
753
754 if (digitsBuffer[js] + noiseHi >= 0.0) {
755 digitsBuffer[js] += noiseHi;
756 if(m_doDigiTruth) digitsBuffer_DigiHSTruth[js] += noiseHi;
757 } else {
758 digitsBuffer[js] -= noiseHi;
759 if(m_doDigiTruth) digitsBuffer_DigiHSTruth[js] -= noiseHi;
760 }
761
762
763 if (m_integerDigits) {
764 digitsBuffer[js] = round(digitsBuffer[js]);
765 if(m_doDigiTruth) digitsBuffer_DigiHSTruth[js] = round(digitsBuffer_DigiHSTruth[js]);
766 }
767
768 if (m_calibRun) { //Calculate also low gain
769 digitsBufferLo[js] = digitSamplesLo[js] + pedSimLo;
770 if(m_doDigiTruth) digitsBufferLo_DigiHSTruth[js] = digitSamplesLo_DigiHSTruth[js] + pedSimLo;
771 double noiseLo(0.0);
772 // Full noise pattern, including coherent noise has priority over normal noise //F Spano'
773 if (coherNoiseLo) {
774 // get the js-th correct random vector of 48 elements for the jsth sample // F Spano'
775 std::unique_ptr<double[]>& CorVecLo = CorrRndmVecLo[js];
776 // apply Y=C*Z where Z is the random vector of 48 normal indep variables, and C is the Cholesky decomposition // F Spano'
777 for (int i = 0; i < nchMax; ++i) noiseLo += CorrWeightLo(i, ich) * CorVecLo[i];
778 } else if (tileNoiseLG) {
779 //using the same gaussian (sigma) for all samples in one channel in one event
780 if (RndmLo_dG[0] < sigmaLo_Norm) noiseLo = sigmaLo_Hfn1 * RndmLo[js];
781 else noiseLo = sigmaLo_Hfn2 * RndmLo[js];
782 }
783
784 if (digitsBufferLo[js] + noiseLo >= 0.0) {
785 digitsBufferLo[js] += noiseLo;
786 if(m_doDigiTruth) digitsBufferLo_DigiHSTruth[js] += noiseLo;
787 } else {
788 digitsBufferLo[js] -= noiseLo;
789 if(m_doDigiTruth) digitsBufferLo_DigiHSTruth[js] -= noiseLo;
790 }
791
792 if (m_integerDigits) {
793 digitsBufferLo[js] = round(digitsBufferLo[js]);
794 if(m_doDigiTruth) digitsBufferLo_DigiHSTruth[js] = round(digitsBufferLo_DigiHSTruth[js]);
795 }
796
797
798 } else if ((digitsBuffer[js] >= m_f_ADCmaxHG && good_ch) || igain[ich] == TileID::LOWGAIN) { // saturation of high gain in non-calib run
799 // or low gain in digi overlay
800 --nChHiSum;
801 ++nChLoSum;
802 igain[ich] = TileID::LOWGAIN;
803 adc_id = m_tileHWID->adc_id(drawer_id, ich, TileID::LOWGAIN);
804
805 // reset all samples in digitsBuffer[] to Low Gain values
806 for (js = 0; js < m_nSamples; ++js) {
807 digitsBuffer[js] = digitSamplesLo[js] + pedSimLo;
808 if(m_doDigiTruth) digitsBuffer_DigiHSTruth[js] = digitSamplesLo_DigiHSTruth[js] + pedSimLo;
809 double noiseLo(0.0);
810 // Full noise pattern, including coherent noise has priority over normal noise //F Spano'
811 if (coherNoiseLo) {
812 // get the js-th correct random vector of 48 elements for the jsth sample // F Spano'
813 double* CorVec = CorrRndmVec[js].get(); // reuse the same rndm as for high gain
814 // apply Y=C*Z where Z is the random vector of 48 normal indep variables, and C is the Cholesky decomposition // F Spano'
815 for (int i = 0; i < nchMax; ++i) noiseLo += CorrWeightLo(i, ich) * CorVec[i];
816 } else if (tileNoiseLG) {
817 //using the same gaussian (sigma) for all samples in one channel in one event
818 // reuse the same rndm as for high gain
819 if (Rndm_dG[0] < sigmaLo_Norm) noiseLo = sigmaLo_Hfn1 * Rndm[js];
820 else noiseLo = sigmaLo_Hfn2 * Rndm[js];
821 }
822
823 if (digitsBuffer[js] + noiseLo >= 0.0) {
824 digitsBuffer[js] += noiseLo;
825 if(m_doDigiTruth) digitsBuffer_DigiHSTruth[js] += noiseLo;
826 } else {
827 digitsBuffer[js] -= noiseLo;
828 if(m_doDigiTruth) digitsBuffer_DigiHSTruth[js] -= noiseLo;
829 }
830
831 if (digitsBuffer[js] > m_f_ADCmax && good_ch) {
832 digitsBuffer[js] = m_f_ADCmax;
833 if(m_doDigiTruth) digitsBuffer_DigiHSTruth[js] = m_f_ADCmax;
834 }
835 if (m_integerDigits) {
836 digitsBuffer[js] = round(digitsBuffer[js]);
837 if(m_doDigiTruth) digitsBuffer_DigiHSTruth[js] = round(digitsBuffer_DigiHSTruth[js]);
838 }
839 }
840
841 overNoiseHG = false;
842
843 if (msgLvl(MSG::VERBOSE)) {
844 msg(MSG::VERBOSE) << "Channel " << ros << '/' << drawer << '/' << ich << "/" << igain[ich]
845 << " Switch to low gain Amp(lo)=" << digitsBuffer[m_iTrig] << endmsg;
846 if (overNoiseLG) {
847 if (sigmaLo_Norm<1.0) {
848 msg(MSG::VERBOSE) << "LG Ped & noise from DB "
849 << pedSimLo << " " << sigmaLo_Hfn1 << " " << sigmaLo_Hfn2 << " " << sigmaLo_Norm
850 << ((Rndm_dG[0] < sigmaLo_Norm)?(" sig1 used"):(" sig2 used")) << endmsg;
851 } else {
852 msg(MSG::VERBOSE) << "LG Ped & noise from DB "
853 << pedSimLo << " " << sigmaLo_Hfn1 << endmsg;
854 }
855 }
856 }
857 break;
858 }
859 }
860 if (msgLvl(MSG::VERBOSE)) {
861 if (overNoiseHG) {
862 if (sigmaHi_Norm<1.0) {
863 msg(MSG::VERBOSE) << "HG Ped & noise from DB "
864 << pedSimHi << " " << sigmaHi_Hfn1 << " " << sigmaHi_Hfn2 << " " << sigmaHi_Norm
865 << ((Rndm_dG[0] < sigmaHi_Norm)?(" sig1 used"):(" sig2 used")) << endmsg;
866 } else {
867 msg(MSG::VERBOSE) << "HG Ped & noise from DB "
868 << pedSimHi << " " << sigmaHi_Hfn1 << endmsg;
869 }
870 }
871 if (m_calibRun && overNoiseLG) {
872 if (sigmaLo_Norm<1.0) {
873 msg(MSG::VERBOSE) << "LG Ped & noise from DB "
874 << pedSimLo << " " << sigmaLo_Hfn1 << " " << sigmaLo_Hfn2 << " " << sigmaLo_Norm
875 << ((RndmLo_dG[0] < sigmaLo_Norm)?(" sig1 used"):(" sig2 used")) << endmsg;
876 } else {
877 msg(MSG::VERBOSE) << "LG Ped & noise from DB "
878 << pedSimLo << " " << sigmaLo_Hfn1 << endmsg;
879 }
880 }
881 }
882
883 if (m_calibRun) { // calib run - keep both low and high gain
884
885 if (chanHiIsBad) {
886 std::fill(digitsBuffer.begin(), digitsBuffer.end(), m_f_ADCmaskValue);
887 if (m_doDigiTruth) {
888 std::fill(digitsBuffer_DigiHSTruth.begin(), digitsBuffer_DigiHSTruth.end(), m_f_ADCmaskValue);
889 }
890 ATH_MSG_DEBUG( "Masking Channel " << ros << '/' << drawer << '/' << ich << "/1 HG" );
891 }
892
893 auto pDigits = std::make_unique<TileDigits>(adc_id, digitsBuffer);
894 ATH_CHECK( digitsContainer->push_back(std::move(pDigits)) );
895
896 if(m_doDigiTruth && digitsContainer_DigiHSTruth){
897 auto digits_DigiHSTruth = std::make_unique<TileDigits>(adc_id, digitsBuffer_DigiHSTruth);
898 ATH_CHECK( digitsContainer_DigiHSTruth->push_back(std::move(digits_DigiHSTruth)) );
899 }
900
901 if (chanLoIsBad) {
902 std::fill(digitsBufferLo.begin(), digitsBufferLo.end(), m_f_ADCmaskValue);
903 if(m_doDigiTruth) {
904 std::fill(digitsBufferLo_DigiHSTruth.begin(), digitsBufferLo_DigiHSTruth.end(), m_f_ADCmaskValue);
905 }
906
907 ATH_MSG_DEBUG( "Masking Channel " << ros << '/' << drawer << '/' << ich << "/0 LG");
908 }
909
910 auto pDigitsLo = std::make_unique<TileDigits>(adc_id_lo, digitsBufferLo);
911 ATH_CHECK( digitsContainer->push_back(std::move(pDigitsLo)) );
912
913 if(m_doDigiTruth && digitsContainer_DigiHSTruth){
914 auto pDigitsLo_DigiHSTruth = std::make_unique<TileDigits>(adc_id_lo, digitsBufferLo_DigiHSTruth);
915 ATH_CHECK( digitsContainer_DigiHSTruth->push_back(std::move(pDigitsLo_DigiHSTruth)) );
916 }
917 } else { //normal run
918
919 bool hiGain = (igain[ich] == TileID::HIGHGAIN);
920
921 // If tileThresh, apply threshold cut to the in-time Digits signal
922 bool isChannelGood = true;
923 if (m_tileThresh) {
924 if (hiGain) { // make threshold only on high gain
925 double ampInTime = digitsBuffer[m_iTrig] - pedSimHi;
926 if (m_integerDigits)
927 ampInTime = round(ampInTime);
928 if (m_tileThreshHi < 0) {
929 if (fabs(ampInTime) < fabs(m_tileThreshHi))
930 isChannelGood = false;
931 } else {
932 if (ampInTime < m_tileThreshHi)
933 isChannelGood = false;
934 }
935 }
936 }
937 // If channel is good, create TileDigits object and store in container.
938 if (isChannelGood) {
939 echtot_Acc += ech_tot[ich];
940 echint_Acc += fabs(ech_int[ich]);
941 if (hiGain) {
942 ++nChHiAcc;
943 } else {
944 ++nChLoAcc;
945 }
946
947 if (hiGain) {
948 //if (m_rndmEvtOverlay // not needed, because DQstatus have been already checked before
949 // && !(theDQstatus->isAdcDQgood(ros, drawer, ich, TileID::HIGHGAIN))) {
950 // chanHiIsBad = true;
951 // ATH_MSG_DEBUG( "BAD DQ Channel " << ros << '/' << drawer << '/' << ich << "/1 HG");
952 //}
953 if (chanHiIsBad) {
954 if (pmt_id.is_valid()) {
955 std::fill(digitsBuffer.begin(), digitsBuffer.end(), m_f_ADCmaskValue);
956 if (m_doDigiTruth) {
957 std::fill(digitsBuffer_DigiHSTruth.begin(), digitsBuffer_DigiHSTruth.end(), m_f_ADCmaskValue);
958 }
959 } else if (good_ch) {
960 ATH_MSG_DEBUG( "Disconnected Channel " << ros << '/' << drawer << '/' << ich);
961 std::fill(digitsBuffer.begin(), digitsBuffer.end(), 0.);
962 if (m_doDigiTruth) {
963 std::fill(digitsBuffer_DigiHSTruth.begin(), digitsBuffer_DigiHSTruth.end(), 0.);
964 }
965 }
966 ATH_MSG_DEBUG( "Masking Channel " << ros << '/' << drawer << '/' << ich << "/1 HG");
967 }
968 } else {
969 //if (m_rndmEvtOverlay // not needed, because DQstatus have been already checked before
970 // && !(theDQstatus->isAdcDQgood(ros, drawer, ich, TileID::LOWGAIN))) {
971 // chanLoIsBad = true;
972 // ATH_MSG_DEBUG( "BAD DQ Channel " << ros << '/' << drawer << '/' << ich << "/0 LG");
973 //}
974 if (chanLoIsBad) {
975 if (pmt_id.is_valid()) {
976 std::fill(digitsBuffer.begin(), digitsBuffer.end(), m_f_ADCmaskValue);
977 if (m_doDigiTruth) {
978 std::fill(digitsBuffer_DigiHSTruth.begin(), digitsBuffer_DigiHSTruth.end(), m_f_ADCmaskValue);
979 }
980 } else if (good_ch) {
981 ATH_MSG_DEBUG( "Disconnected Channel " << ros << '/' << drawer << '/' << ich);
982 std::fill(digitsBuffer.begin(), digitsBuffer.end(), 0.);
983 if (m_doDigiTruth) {
984 std::fill(digitsBuffer_DigiHSTruth.begin(), digitsBuffer_DigiHSTruth.end(), 0.);
985 }
986 }
987 ATH_MSG_DEBUG( "Masking Channel " << ros << '/' << drawer << '/' << ich << "/0 LG");
988 }
989 }
990
991 auto pDigits = std::make_unique<TileDigits>(adc_id, digitsBuffer);
992
993 if (ech_int[ich] > m_filterThreshold || ech_int[ich] < -m_filterThresholdMBTS) {
994 if (filteredContainer) ATH_CHECK( filteredContainer->push_back(pDigits.get()) );
995 if (hiGain) {
996 ++nChHiFlt;
997 } else {
998 ++nChLoFlt;
999 }
1000 }
1001
1002 ATH_CHECK( digitsContainer->push_back(std::move(pDigits)) );
1003 if(m_doDigiTruth && digitsContainer_DigiHSTruth){
1004 auto pDigits_DigiHSTruth = std::make_unique<TileDigits>(adc_id, digitsBuffer_DigiHSTruth);
1005 ATH_CHECK( digitsContainer_DigiHSTruth->push_back(std::move(pDigits_DigiHSTruth)) );
1006 }
1007
1008 if (msgLvl(MSG::VERBOSE)) {
1009 double pedSim = ((hiGain) ? pedSimHi : pedSimLo);
1010 double ampInTime = digitsBuffer[m_iTrig] - pedSim;
1011 if (m_integerDigits)
1012 ampInTime = round(ampInTime);
1013 msg(MSG::VERBOSE) << ((ech_int[ich] > m_filterThreshold
1014 || ech_int[ich] < -m_filterThresholdMBTS) ? "AccFlt" : "Accept")
1015 << " ADC " << m_tileHWID->to_string(adc_id)
1016 << " AinT=" << ampInTime
1017 << " ped=" << pedSim
1018 << " Ech=" << ech_tot[ich]
1019 << " EinT=" << ech_int[ich] << endmsg;
1020 msg(MSG::VERBOSE) << "digits";
1021 for (unsigned int i = 0; i < digitsBuffer.size(); ++i)
1022 msg(MSG::VERBOSE) << " " << digitsBuffer[i];
1023 msg(MSG::VERBOSE) << endmsg;
1024 }
1025 } else {
1026 echtot_Cut += ech_tot[ich];
1027 echint_Cut += ech_int[ich];
1028 if (hiGain) {
1029 ++nChHiCut;
1030 } else {
1031 ++nChLoCut;
1032 }
1033
1034 if (msgLvl(MSG::VERBOSE)) {
1035 double pedSim = ((hiGain) ? pedSimHi : pedSimLo);
1036 double ampInTime = digitsBuffer[m_iTrig] - pedSim;
1037 if (m_integerDigits)
1038 ampInTime = round(ampInTime);
1039 msg(MSG::VERBOSE) << "Reject. ADC " << m_tileHWID->to_string(adc_id)
1040 << " AinT=" << ampInTime
1041 << " ped=" << pedSim
1042 << " Ech=" << ech_tot[ich]
1043 << " EinT=" << ech_int[ich] << endmsg;
1044 }
1045 }
1046 }
1047 }
1048 if(m_doDigiTruth) ++collItr_DigiHSTruth;
1049 }
1050
1051 if (msgLvl(MSG::DEBUG)) {
1052 msg(MSG::DEBUG) << "TileDigitsMaker execution completed." << endmsg;
1053 msg(MSG::DEBUG) << " nCh=" << nChSum
1054 << " nChH/L=" << nChHiSum << "/" << nChLoSum
1055 << " nFltH/L=" << nChHiFlt << "/" << nChLoFlt
1056 << " Hit=" << HitSum
1057 << " Ene=" << EneSum
1058 << " RChSum=" << RChSum << endmsg;
1059 if (m_tileThresh) {
1060 msg(MSG::DEBUG) << " Accepted: nChLo/Hi=" << nChLoAcc << "/" << nChHiAcc
1061 << " eTot=" << echtot_Acc
1062 << " eInT=" << echint_Acc << endmsg;
1063 msg(MSG::DEBUG) << " Rejected: nChLo/Hi=" << nChLoCut << "/" << nChHiCut
1064 << " eTot=" << echtot_Cut
1065 << " eInT=" << echint_Cut << endmsg;
1066 }
1067 }
1068
1069
1070 // step3: register the Digit container in the TES
1072 ATH_CHECK( digitsCnt.record(std::move(digitsContainer)) );
1073
1074 if(m_doDigiTruth && digitsContainer_DigiHSTruth){
1076 ATH_CHECK( digits_DigiHSTruth.record(std::move(digitsContainer_DigiHSTruth)) );
1077 }
1078
1079 if (filteredContainer) {
1081 ATH_CHECK( filteredDigitsContainer.record(std::move(filteredContainer)) );
1082 }
1083
1084 return StatusCode::SUCCESS;
1085}
1086
1088 ATH_MSG_DEBUG( "TileDigitsMaker finalized successfully");
1089
1090 return StatusCode::SUCCESS;
1091}
1092
1094 std::vector<std::vector<double>>& drawerBufferLo,
1095 std::vector<std::vector<double>>& drawerBufferHi,
1096 std::vector<int>& igain, std::vector<int>& over_gain, std::vector<double>& ech_int,
1097 std::vector<bool> &signal_in_channel, const TileEMScale* emScale,
1098 const TileSamplingFraction* samplingFraction, const TilePulse* pulse) const{
1099
1100 constexpr int nchMax = 48; // number of channels per drawer
1101 std::array<int, nchMax> ntot_ch; ntot_ch.fill(0);
1102 std::array<double, nchMax> ech_tot; ech_tot.fill(0.0);
1103 //double ech_int[nchMax];
1104
1105 /* Set up buffers for handling information in a single collection. */
1106 HWIdentifier drawer_id = m_tileHWID->drawer_id(hitCollection->identify());
1107 int ros = m_tileHWID->ros(drawer_id);
1108 int drawer = m_tileHWID->drawer(drawer_id);
1109 int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer);
1110
1111
1112 // iterate over all hits in a collection
1113 for (const TileHit* tileHit : *hitCollection) {
1114
1115 /* Get hit Identifier (= pmt_ID) and needed parameters for this channel */
1116 Identifier pmt_id = tileHit->pmt_ID();
1117 double mbts_extra_factor = (m_tileTBID->is_tiletb(pmt_id)) ? -1.0 : 1.0;
1118 HWIdentifier channel_id = tileHit->pmt_HWID();
1119 int ich = m_tileHWID->channel(channel_id);
1120 signal_in_channel[ich] = true;
1121
1122 if (over_gain[ich] > 9) {
1123 if (msgLvl(MSG::DEBUG)) {
1124 int n_hits = tileHit->size();
1125 double e_hit(0.);
1126 for (int ihit = 0; ihit < n_hits; ++ihit) {
1127 e_hit += tileHit->energy(ihit);
1128 }
1129 e_hit *= std::round(samplingFraction->getSamplingFraction(drawerIdx, ich) * 1000) / 1000;
1130 ech_tot[ich] += e_hit;
1131 ntot_ch[ich] += n_hits;
1132 ATH_MSG_VERBOSE("BAD Overlay digits - skip hit in channel " << m_tileHWID->to_string(channel_id,-1));
1133 }
1134 continue;
1135 } else {
1136 ATH_MSG_VERBOSE("new hit in channel " << m_tileHWID->to_string(channel_id,-1));
1137 }
1138
1139 /* Set gain=high and get digitSamples and calibration for this channel. */
1140 if (igain[ich] < 0)
1141 igain[ich] = TileID::HIGHGAIN;
1142 // conversion from scintillator energy to total cell energy (sampling fraction)
1143 double hit_calib = samplingFraction->getSamplingFraction(drawerIdx, ich);
1144 hit_calib = std::round(hit_calib * 1000) / 1000;
1145
1146 // conversion to ADC counts for high gain
1147 double efactorHi = hit_calib / emScale->calibrateChannel(drawerIdx, ich, TileID::HIGHGAIN, 1.
1149 // conversion to ADC counts for low gain
1150 double efactorLo = hit_calib / emScale->calibrateChannel(drawerIdx, ich, TileID::LOWGAIN, 1.
1152
1153 std::vector<double>& digitSamplesHi = drawerBufferHi[ich];
1154 std::vector<double>& digitSamplesLo = drawerBufferLo[ich];
1155 /* Loop over the subhits for this channel. For each one,
1156 convolute with shaping function and add to digitSamples. */
1157 int n_hits = tileHit->size();
1158 for (int ihit = 0; ihit < n_hits; ++ihit) {
1159 /* Get hit energy and convert to amplitude of high-gain and low-gain channel */
1160 double e_hit = tileHit->energy(ihit);
1161 double amp_ch = e_hit * efactorHi;
1162 double amp_ch_lo = e_hit * efactorLo;
1163 double ech_sub = e_hit * hit_calib;
1164 double t_hit = tileHit->time(ihit);
1165
1166 ech_tot[ich] += ech_sub;
1167 if (fabs(t_hit) < 50.0) // ene within +/- 50 ns, used for filtered digits cut
1168 ech_int[ich] += ech_sub * mbts_extra_factor;
1169 ntot_ch[ich] += 1;
1170
1171 // Assume time is in nanoseconds, use fine-grain shaping:
1172 int ishiftHi = (int) (t_hit / m_timeStepHi + 0.5);
1173 for (int js = 0; js < m_nSamples; ++js) {
1174 int k = m_binTime0Hi + (js - m_iTrig) * m_nBinsPerXHi - ishiftHi;
1175 if (k < 0)
1176 k = 0;
1177 else if (k > m_nShapeHi)
1178 k = m_nShapeHi;
1179
1181 float phase = (k - m_binTime0Hi) * m_timeStepHi;
1182 float y, dy;
1183 pulse->getPulseShapeYDY(drawerIdx, ich, 1, phase, y, dy);
1184 double ampl = (double) y;
1185 digitSamplesHi[js] += amp_ch * ampl;
1186 ATH_MSG_VERBOSE( "Sample no.=" << js
1187 << " Pulse index=" << k
1188 << " Shape wt. =" << ampl
1189 << " HIGAIN from COOL");
1190
1191 } else {
1192 digitSamplesHi[js] += amp_ch * m_digitShapeHi[k];
1193 ATH_MSG_VERBOSE( "Sample no.=" << js
1194 << " Pulse index=" << k
1195 << " Shape wt. =" << m_digitShapeHi[k]
1196 << " HIGAIN from TileInfo");
1197 }
1198
1199 }
1200 int ishiftLo = (int) (t_hit / m_timeStepLo + 0.5);
1201 for (int js = 0; js < m_nSamples; ++js) {
1202 int k = m_binTime0Lo + (js - m_iTrig) * m_nBinsPerXLo - ishiftLo;
1203 if (k < 0)
1204 k = 0;
1205 else if (k > m_nShapeLo)
1206 k = m_nShapeLo;
1207
1209 float phase = (k - m_binTime0Lo) * m_timeStepLo;
1210 float y, dy;
1211 pulse->getPulseShapeYDY(drawerIdx, ich, 0, phase, y, dy);
1212 double ampl = (double) y;
1213 digitSamplesLo[js] += amp_ch_lo * ampl;
1214 ATH_MSG_VERBOSE( "Sample no.=" << js
1215 << " Pulse index=" << k
1216 << " Shape wt. =" << ampl
1217 << " LOGAIN from COOL");
1218 } else {
1219 digitSamplesLo[js] += amp_ch_lo * m_digitShapeLo[k];
1220 ATH_MSG_VERBOSE( "Sample no.=" << js
1221 << " Pulse index=" << k
1222 << " Shape wt. =" << m_digitShapeLo[k]
1223 << " LOGAIN from TileInfo");
1224 }
1225
1226 }
1227
1228 if (msgLvl(MSG::VERBOSE)) {
1229 msg(MSG::VERBOSE) << "subHit: ch=" << ich
1230 << " e_hit=" << e_hit
1231 << " t_hit=" << t_hit
1232 << " SamplesHi[" << m_iTrig << "]=" << digitSamplesHi[m_iTrig]
1233 << " SamplesLo[" << m_iTrig << "]=" << digitSamplesLo[m_iTrig] << endmsg;
1234 }
1235 } /* end loop over sub-hits */
1236 } /* end loop over hits for this collection. */
1237
1238
1239 return StatusCode::SUCCESS;
1240
1241}
1242
1244 const TileHitCollection* hitCollection,
1245 std::vector<std::vector<double>>& drawerBufferLo,
1246 std::vector<std::vector<double>>& drawerBufferHi,
1247 std::vector<int>& igain, int ros, int drawer, int drawerIdx,
1248 std::vector<int>& over_gain, const TileEMScale* emScale,
1249 const TileSampleNoise* sampleNoise, const TileDQstatus* dqStatus,
1250 const TileBadChannels* badChannels) const {
1251
1252 if (hitCollection->identify() != bkgDigitCollection->identify()) {
1253 ATH_MSG_ERROR ( "Frag IDs for hit collection and digits overlay collection do not match "
1254 << MSG::hex << hitCollection->identify() << " != " << bkgDigitCollection->identify()
1255 << MSG::dec );
1256 return StatusCode::FAILURE;
1257 }
1258
1259
1260 // iterate over all digits in a collection
1261 for (const auto* bkgDigit : *bkgDigitCollection) {
1262
1263 /* Get digit HWIdentifier (= adc_id) */
1264 HWIdentifier adcId = bkgDigit->adc_HWID();
1265 int channel = m_tileHWID->channel(adcId);
1266 int gain = m_tileHWID->adc(adcId);
1267
1268 igain[channel] = gain;
1269
1270 // get channel status
1271 bool good_dq = dqStatus->isAdcDQgood(ros, drawer, channel, gain);
1272 bool good_ch = (!badChannels->getAdcStatus(adcId).isBad());
1273
1274 // get digits
1275 std::vector<float> digits = bkgDigit->samples();
1276 // get number of time samples & compare with nSamp
1277 int nSamp2 = digits.size();
1278 int goodDigits = nSamp2;
1279 float dig(m_f_ADCmaskValue),digmin(65536.),digmax(-65536.);
1280 if (goodDigits > 0) {
1281 auto minmax = std::minmax_element(digits.begin(), digits.end());
1282 digmin = *minmax.first;
1283 digmax = *minmax.second;
1284 }
1285
1286 if (good_dq) {
1287 if (digmax > m_ADCmaxPlusEps) { // ignore everything in case of invalid digits
1288 dig = m_f_ADCmaskValue;
1289 goodDigits = 0;
1290 } else { // skip zeros or overflows
1291 float ADCmaxMinusEps = m_ADCmaxMinusEps;
1292 int badDigits = std::count_if(digits.begin(), digits.end(), [ADCmaxMinusEps](float dig){
1293 return (dig < 0.01) || (dig > ADCmaxMinusEps);});
1294 goodDigits -= badDigits;
1295 dig = digits.back();
1296 }
1297 } else if (goodDigits>0) {
1298 goodDigits = 0;
1299 dig = digits.back();
1300 }
1301
1302 if (goodDigits>0) {
1303 over_gain[channel] = gain;
1304 if (nSamp2 != m_nSamples) {
1305 float lastDigit = digits.back();
1306 digits.resize(m_nSamples);
1307 // repeat last value in vector (nSamp-nSamp2) times
1308 std::fill(digits.begin() + nSamp2, digits.end(), lastDigit);
1309 }
1310
1311 std::vector<double>& buffer = (gain == TileID::HIGHGAIN) ? drawerBufferHi[channel] : drawerBufferLo[channel];
1312 std::vector<double>& bufferLG = drawerBufferLo[channel];
1313
1314 bool isFilledLG = false;
1315 if (gain == TileID::HIGHGAIN) {
1316 if (digmax - digmin > 5. && good_ch ) {// 5 ADC counts cut - to ignore pure noise in HG (less than 0.1 count effect in LG)
1317 float ratio = emScale->applyOnlineChargeCalibration(drawerIdx, channel, TileID::HIGHGAIN, 1.)
1318 / emScale->applyOnlineChargeCalibration(drawerIdx, channel, TileID::LOWGAIN, 1.); // ratio between low and high gain
1319
1320 dig=std::min(digits[0],std::max(digmin, sampleNoise->getPed(drawerIdx, channel, TileID::HIGHGAIN)));
1321
1322 std::transform(digits.begin(), digits.end(), bufferLG.begin(), [dig,ratio](float digit){return (digit - dig) * ratio;});
1323 isFilledLG = true;
1324 }
1325 }
1326
1327 std::copy(digits.begin(), digits.end(), buffer.begin());
1328
1329 if (msgLvl(MSG::VERBOSE)) {
1330 msg(MSG::VERBOSE) << "RNDM BG ADC " << m_tileHWID->to_string(adcId)
1331 << " samples=";
1332 for (int js = 0; js < m_nSamples; ++js)
1333 msg(MSG::VERBOSE) << " " << buffer[js];
1334 if (!good_ch)
1335 msg(MSG::VERBOSE) << " BCH";
1336 // good_dq should always be true here, but leave in place in case
1337 // things change.
1338 //coverity[DEADCODE]
1339 if (!good_dq) {
1340 msg(MSG::VERBOSE) << " BDQ";
1341 } else if (isFilledLG) {
1342 msg(MSG::VERBOSE) << " LG=";
1343 for (int js = 0; js < m_nSamples; ++js)
1344 msg(MSG::VERBOSE) << " " << int(bufferLG[js]*100)/100.;
1345 }
1346 msg(MSG::VERBOSE) << endmsg;
1347 }
1348
1349 } else if (nSamp2 > 0) {
1350 over_gain[channel] = 10+gain; // flag problematic channel
1351
1352 std::vector<double>& buffer = (gain == TileID::HIGHGAIN) ? drawerBufferHi[channel] : drawerBufferLo[channel];
1353
1354 if (digmin != digmax || (dig!=0. && dig!=m_f_ADCmax)) {
1355 dig = m_f_ADCmaskValue; // keep only 0 or m_f_ADCmax as it is
1356 }
1357 std::fill(buffer.begin(), buffer.end(), dig);
1358
1359 if (msgLvl(MSG::VERBOSE)) {
1360 msg(MSG::VERBOSE) << "BAD BG ADC " << m_tileHWID->to_string(adcId)
1361 << " samples=";
1362 for (int js = 0; js < nSamp2; ++js)
1363 msg(MSG::VERBOSE) << " " << digits[js];
1364 msg(MSG::VERBOSE) << ((good_ch)?"":" BCH") << ((good_dq)?"":" BDQ") << endmsg;
1365 }
1366
1367 } else {
1368 ATH_MSG_VERBOSE( "NO BG ADC " << m_tileHWID->to_string(adcId)
1369 << " samples= 0 0 0 0 0 0 0"
1370 << ((good_ch)?"":" BCH") << ((good_dq)?"":" BDQ") );
1371 }
1372 }
1373 return StatusCode::SUCCESS;
1374}
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(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.
static const double MeV
Handle class for reading from StoreGate.
Handle class for recording to StoreGate.
Helper for holding non-const raw data prior to recording in SG.
Wrapper to avoid constant divisions when using units.
#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
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
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.
bool is_valid() const
Check if id is in a valid state.
const_pointer_type retrieve()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type get() const
Dereference the pointer, but don't cache anything.
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.
bool isBad() const
static unsigned int getDrawerIdx(unsigned int ros, unsigned int drawer)
Returns a drawer hash.
Class that holds Data Quality fragment information and provides functions to extract the data quality...
bool isAdcDQgood(int partition, int drawer, int ch, int gain) const
returns status of single ADC returns False if there are any errors
int m_nSamples
Number of time slices for each channel.
int m_binTime0Lo
Index of time=0 bin for low gain pulse shape.
Gaudi::Property< std::string > m_randomStreamName
Random Stream Name.
SG::WriteHandleKey< TileDigitsContainer > m_digitsContainerKey
float m_ADCmaxMinusEps
ADC saturation value - 0.01 or something small.
Gaudi::Property< int > m_allChannels
SG::ReadHandleKey< TileHitContainer > m_hitContainer_DigiHSTruthKey
SG::ReadCondHandleKey< TileBadChannels > m_badChannelsKey
Name of TileBadChannels in condition store.
int m_nShapeLo
Number of bins in low gain pulse shape.
Gaudi::Property< bool > m_onlyUseContainerName
int m_i_ADCmax
ADC saturation value.
SG::ReadHandleKey< TileHitContainer > m_hitContainerKey
float m_f_ADCmax
ADC saturation value.
int m_nBinsPerXHi
Number of bins per bunch crossing in high gain pulse shape.
float m_ADCmaxPlusEps
ADC saturation value + 0.01 or something small.
bool m_tileNoise
If true => generate noise in TileDigits.
SG::ReadCondHandleKey< TilePulse > m_pulseShapeKey
Name of TilePulseShape in condition store.
ServiceHandle< TileCablingSvc > m_cablingSvc
Name of Tile cabling service.
SG::ReadHandleKey< TileDQstatus > m_DQstatusKey
Gaudi::Property< bool > m_rndmEvtOverlay
virtual StatusCode execute(const EventContext &ctx) const override
execute method
const TileHWID * m_tileHWID
int m_nBinsPerXLo
Number of bins per bunch crossing in low gain pulse shape.
SG::WriteHandleKey< TileDigitsContainer > m_filteredDigitsContainerKey
double m_timeStepHi
Time step in high gain pulse shape: 25.0 / nBinsPerXHi.
Gaudi::Property< bool > m_calibRun
StatusCode fillDigitCollection(const TileHitCollection *hitCollection, std::vector< std::vector< double > > &drawerBufferLo, std::vector< std::vector< double > > &drawerBufferHi, std::vector< int > &igain, std::vector< int > &overgain, std::vector< double > &ech_int, std::vector< bool > &signal_in_channel, const TileEMScale *emScale, const TileSamplingFraction *samplingFraction, const TilePulse *pulse) const
const TileInfo * m_tileInfo
bool m_tileThresh
If true => apply threshold to Digits.
std::vector< double > m_digitShapeHi
High gain pulse shape.
Gaudi::Property< bool > m_useCoolPulseShapes
std::vector< double > m_digitShapeLo
Low gain pulse shape.
bool m_tileCoherNoise
If true => generate coherent noise in TileDigits.
ServiceHandle< PileUpMergeSvc > m_mergeSvc
Gaudi::Property< std::string > m_infoName
const TileCablingService * m_cabling
TileCabling instance.
double m_timeStepLo
Time step in low gain pulse shape: 25.0 / nBinsPerXLo.
int m_iTrig
Index of the triggering time slice.
int m_nShapeHi
Number of bins in high gain pulse shape.
Gaudi::Property< bool > m_integerDigits
double m_tileThreshHi
Actual threshold value for high gain.
std::string m_inputDigitContainerName
Gaudi::Property< double > m_filterThresholdMBTS
SG::ReadCondHandleKey< TileEMScale > m_emScaleKey
Name of TileEMScale in condition store.
SG::ReadCondHandleKey< TileSampleNoise > m_sampleNoiseKey
Name of TileSampleNoise in condition store.
Gaudi::Property< bool > m_doDigiTruth
float m_f_ADCmaskValue
indicates channels which were masked in background dataset
int m_binTime0Hi
Index of time=0 bin for high gain pulse shape.
SG::ReadCondHandleKey< TileSamplingFraction > m_samplingFractionKey
Name of TileSamplingFraction in condition store.
Gaudi::Property< double > m_filterThreshold
Gaudi::Property< bool > m_maskBadChannels
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number service to use.
SG::ReadHandleKey< TileDigitsContainer > m_inputDigitContainerKey
float m_f_ADCmaxHG
ADC saturation value - 0.5.
double m_tileThreshLo
Actual threshold value for low gain.
virtual StatusCode finalize() override
finalize method
StatusCode overlayBackgroundDigits(const TileDigitsCollection *bkgDigitCollection, const TileHitCollection *hitCollection, std::vector< std::vector< double > > &drawerBufferLo, std::vector< std::vector< double > > &drawerBufferHi, std::vector< int > &igain, int ros, int drawer, int drawerIdx, std::vector< int > &over_gain, const TileEMScale *emScale, const TileSampleNoise *sampleNoise, const TileDQstatus *dqStatus, const TileBadChannels *badChannels) const
std::vector< std::unique_ptr< HWIdentifier[]> > m_all_ids
SG::WriteHandleKey< TileDigitsContainer > m_digitsContainer_DigiHSTruthKey
virtual StatusCode initialize() override
initialize method
const TileTBID * m_tileTBID
const TileID * m_tileID
Condition object to keep calibration factors of TileCal channels.
Definition TileEMScale.h:87
float applyOnlineChargeCalibration(unsigned int drawerIdx, unsigned int channel, unsigned int adc, float amplitude) const
Apply online CIS calibration: ADC counts -> pC.
float calibrateChannel(unsigned int drawerIdx, unsigned int channel, unsigned int adc, float amplitude, TileRawChannelUnit::UNIT rawDataUnitIn, TileRawChannelUnit::UNIT rawDataUnitOut) const
Calibrate a Tile channel.
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
Condition object to keep and provide Tile sample noise.
float getPed(unsigned int drawerIdx, unsigned int channel, unsigned int adc) const
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.
@ 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