ATLAS Offline Software
Loading...
Searching...
No Matches
LArHitEMapToDigitAlg.cxx
Go to the documentation of this file.
1/*
2 * Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
6#include "CLHEP/Random/RandGaussZiggurat.h"
14
16#include "CLHEP/Random/RandomEngine.h"
17#include <CLHEP/Random/Randomize.h>
18
19
20using CLHEP::RandFlat;
21using CLHEP::RandGaussZiggurat;
22
24{
25
27 ATH_MSG_ERROR("Requested Nsamples " << m_NSamples << " larger than max "
28 << s_MaxNSamples);
29 return StatusCode::FAILURE;
30 }
33
34 ATH_CHECK(m_shapeKey.initialize());
35 ATH_CHECK(m_fSamplKey.initialize());
36 ATH_CHECK(m_OFCKey.initialize());
37 ATH_CHECK(m_pedestalKey.initialize());
39 ATH_CHECK(m_bcContKey.initialize());
40 ATH_CHECK(m_badFebKey.initialize());
41 ATH_CHECK(m_adc2mevKey.initialize());
42 ATH_CHECK(m_caloMgrKey.initialize());
43
44 ATH_CHECK(m_cablingKey.initialize());
45
46 // helpers
47 //retrieve ID helpers
48 ATH_CHECK(detStore()->retrieve(m_calocell_id,"CaloCell_ID"));
49
50
51 const CaloIdManager* caloIdMgr = nullptr;
52 StatusCode sc = detStore()->retrieve(caloIdMgr);
53 if (sc.isFailure()) {
54 ATH_MSG_ERROR(" Unable to retrieve CaloIdManager from DetectoreStore");
55 return StatusCode::FAILURE;
56 }
57 m_larem_id = caloIdMgr->getEM_ID();
58 m_larhec_id = caloIdMgr->getHEC_ID();
59 m_larfcal_id = caloIdMgr->getFCAL_ID();
60
61 sc = detStore()->retrieve(m_laronline_id);
62 if (sc.isFailure()) {
63 ATH_MSG_ERROR(" Unable to retrieve LArOnlineId from DetectoreStore");
64 return StatusCode::FAILURE;
65 }
66 ATH_CHECK(m_bcMask.buildBitMask(m_problemsToMask,msg()));
67
68 // Services
69 ATH_CHECK(m_rndmGenSvc.retrieve());
70 ATH_CHECK(m_hitMapKey.initialize());
72
73 ATH_CHECK(m_DigitContainerName.initialize());
75 return StatusCode::SUCCESS;
76
77}
78
79StatusCode LArHitEMapToDigitAlg::execute(const EventContext& context) const {
80
81 // load many conditions
84 const LArOnOffIdMapping* cabling=*cablingHdl;
85 if(!cabling) {
86 ATH_MSG_ERROR("Failed to retrieve LAr Cabling map with key " << m_cablingKey.key() );
87 return StatusCode::FAILURE;
88 }
89
90 // Inputs
92 const LArHitEMap* hitmapPtr = hitmap.cptr();
93 const LArHitEMap* hitmapPtr_DigiHSTruth = nullptr;
94 if ( m_doDigiTruth ) {
95 SG::ReadHandle<LArHitEMap> hitmap_DigitHSTruth(m_hitMapKey_DigiHSTruth,context);
96 hitmapPtr_DigiHSTruth = hitmap_DigitHSTruth.cptr();
97 }
98
99 int it,it_end;
100 it = 0;
101 it_end = hitmapPtr->GetNbCells();
102
103 // Prepare Output
104 //
105 // For the standard one lets use a DataPool
106 auto DigitContainer = std::make_unique<LArDigitContainer>(SG::VIEW_ELEMENTS);
107 DigitContainer->reserve(it_end);
108 DataPool<LArDigit> dataItemsPool(context);
109 dataItemsPool.reserve(it_end);
110 //
111 // HSTruth outputt might not be needed so avoid doing anything
112 // in that case
113 std::unique_ptr<LArDigitContainer> DigitContainer_DigiHSTruth = nullptr;
114 if (m_doDigiTruth){
115 DigitContainer_DigiHSTruth = std::make_unique<LArDigitContainer>();
116 DigitContainer_DigiHSTruth->reserve(it_end);
117 }
118 //
119 const std::vector<std::pair<float,float> >* TimeE;
120 const std::vector<std::pair<float,float> >* TimeE_DigiHSTruth = nullptr;
121
122 ATHRNG::RNGWrapper* rngWrapper = m_rndmGenSvc->getEngine(this, m_randomStreamName);
123 CLHEP::HepRandomEngine * engine = rngWrapper->getEngine(context);
125 rngWrapper->setSeedLegacy( m_randomStreamName, context, m_randomSeedOffset, seedingmode );
126
127 for( ; it!=it_end;++it) // now loop on cells
128 {
129 const LArHitList& hitlist = hitmapPtr->GetCell(it);
130
131 if (!m_Windows || hitlist.inWindows()) {
132 TimeE = &(hitlist.getData());
133 if(m_doDigiTruth) {
134 const auto& hitlist_DigiHSTruth=hitmapPtr_DigiHSTruth->GetCell(it);
135 TimeE_DigiHSTruth = &(hitlist_DigiHSTruth.getData());
136 }
137
138 if (!TimeE->empty() || m_NoiseOnOff || m_RndmEvtOverlay) {
139 const Identifier cellID=m_calocell_id->cell_id(IdentifierHash(it));
140 HWIdentifier ch_id = cabling->createSignalChannelIDFromHash(IdentifierHash(it));
141 HWIdentifier febId = m_laronline_id->feb_Id(ch_id);
142 bool missing=!(badFebs->status(febId).good());
143 if (!missing) {
144 const LArDigit * digit = nullptr ;
145 if(m_RndmEvtOverlay) digit = hitmapPtr->GetDigit(it);
146 // MakeDigit called if in no overlay mode or
147 // if in overlay mode and random digit exists
148 if ((!m_RndmEvtOverlay) || (m_RndmEvtOverlay && digit)) {
149 LArDigit* Digit = nullptr;
150 LArDigit* Digit_DigiHSTruth = nullptr;
151 ATH_CHECK(MakeDigit(context, cellID, ch_id, Digit,
152 dataItemsPool,
153 Digit_DigiHSTruth, TimeE, digit, engine,
154 TimeE_DigiHSTruth));
155 DigitContainer->push_back(Digit);
156 if (DigitContainer_DigiHSTruth){
157 DigitContainer_DigiHSTruth->push_back(Digit_DigiHSTruth);
158 }
159 }
160 }
161 }
162 } // check window
163 } // end of loop over the cells
164
165
166 ATH_MSG_DEBUG(" number of created digits = " << DigitContainer->size());
167
168 SG::WriteHandle<LArDigitContainer> DigitContainerHandle( m_DigitContainerName, context);
169 ATH_CHECK(DigitContainerHandle.record( std::move(DigitContainer) ) );
170 if ( DigitContainer_DigiHSTruth ){
171 SG::WriteHandle<LArDigitContainer> DigitContainer_DigiHSTruthHandle( m_DigitContainerName_DigiHSTruth, context);
172 ATH_CHECK(DigitContainer_DigiHSTruthHandle.record( std::move(DigitContainer_DigiHSTruth) ) );
173 }
174
175
176 return StatusCode::SUCCESS;
177}
178
180 const EventContext& ctx,
181 const Identifier& cellId,
182 const HWIdentifier& ch_id,
183 LArDigit*& Digit,
184 DataPool<LArDigit>& dataItemsPool,
185 LArDigit*& Digit_DigiHSTruth,
186 const std::vector<std::pair<float, float>>* TimeE,
187 const LArDigit* rndmEvtDigit,
188 CLHEP::HepRandomEngine* engine,
189 const std::vector<std::pair<float, float>>* TimeE_DigiHSTruth) const {
190 bool createDigit_DigiHSTruth = true;
191
192 int sampleGainChoice{2};
193 if (m_firstSample<0) sampleGainChoice-=m_firstSample;
194
195 int i;
196 short Adc;
197 short Adc_DigiHSTruth;
198
199 CaloGain::CaloGain igain;
200 std::vector<short> AdcSample(m_NSamples);
201 std::vector<short> AdcSample_DigiHSTruth(m_NSamples);
202
203 float MeV2GeV=0.001; // to convert hit from MeV to GeV before apply GeV->ADC
204
205 float SF=1.;
206 float SigmaNoise;
207 staticVecFloat_t rndm_energy_samples(m_NSamples) ;
208
209
211 const LArADC2MeV* adc2MeVs=*adc2mevHdl;
212
214 const ILArfSampl* fSampl=*fSamplHdl;
215
217 const ILArPedestal* pedestal=*pedHdl;
218
219 const ILArNoise* noise=nullptr;
222 noise=*noiseHdl;
223 }
224
225 const LArAutoCorrNoise* autoCorrNoise=nullptr;
228 autoCorrNoise=*autoCorrNoiseHdl;
229 }
230
233 const LArBadChannelCont* bcCont{*bch};
234
235 int iCalo=0;
236 if(m_larem_id->is_lar_em(cellId)) {
237 if (m_larem_id->is_em_endcap_inner(cellId)) iCalo=EMIW;
238 else iCalo=EM;
239 }
240 if(m_larem_id->is_lar_hec(cellId)) iCalo=HEC;
241 if(m_larem_id->is_lar_fcal(cellId)) iCalo=FCAL;
242
244 if (iCalo==HEC) initialGain = CaloGain::LARMEDIUMGAIN;
245
247
248// ........ retrieve data (1/2) ................................
249//
250 SF=fSampl->FSAMPL(ch_id);
251
252//
253// ....... dump info ................................
254//
255#ifndef NDEBUG
256 ATH_MSG_DEBUG(" Cellid " << m_larem_id->show_to_string(cellId));
257 ATH_MSG_DEBUG(" SF: " << SF);
258#endif
259
260 staticVecDouble_t Samples;
261 staticVecDouble_t Samples_DigiHSTruth;
262 staticVecDouble_t Noise;
263 Samples.resize(m_NSamples,0);
264 if(m_doDigiTruth) Samples_DigiHSTruth.resize(m_NSamples,0);
265 Noise.resize(m_NSamples,0);
266
267//
268// ....... make the five samples
269//
270
271#ifndef NDEBUG
272 ATH_MSG_DEBUG(" number of hit for this cell " << TimeE->size());
273#endif
274
275//
276// convert Hits into energy samples and add result to Samples assuming LARHIGHGAIN for pulse shape
277//
278 bool isDead = m_bcMask.cellShouldBeMasked(bcCont,ch_id);
279
280
281 if (!isDead) {
282 if( this->ConvertHits2Samples(ctx, cellId,ch_id,initialGain,TimeE, Samples).isFailure() ) {
283 return StatusCode::SUCCESS;
284 }
285 if(m_doDigiTruth && TimeE_DigiHSTruth){
286 if( this->ConvertHits2Samples(ctx, cellId,ch_id,initialGain,TimeE_DigiHSTruth, Samples_DigiHSTruth).isFailure() ) {
287 return StatusCode::SUCCESS;
288 }
289 }
290 }
291
292//
293// .... add random event digit if needed
294//
295 float energy2adc ;
296 float rAdc ;
297 if(m_RndmEvtOverlay && rndmEvtDigit ) // no overlay if missing random digit
298 {
299 rndmGain= rndmEvtDigit->gain();
300 auto polynom_adc2mev =adc2MeVs->ADC2MEV(cellId,rndmEvtDigit->gain());
301 if (polynom_adc2mev.size() > 1) {
302 float adc2energy = SF * polynom_adc2mev[1];
303 const std::vector<short> & rndm_digit_samples = rndmEvtDigit->samples() ;
304 float Pedestal = pedestal->pedestal(ch_id,rndmEvtDigit->gain());
305 if (Pedestal <= (1.0+LArElecCalib::ERRORCODE)) {
306 ATH_MSG_WARNING(" Pedestal not found in database for this channel offID " << cellId << " Use sample 0 for random");
307 Pedestal = rndm_digit_samples[0];
308 }
309 ATH_MSG_DEBUG(" Params for inverting LAr Digitization: pedestal " << Pedestal << " adc2energy " << adc2energy);
310
311// in case Medium or low gain, take into account ramp intercept in ADC->"energy" computation
312// this requires to take into account the sum of the optimal filter coefficients, as they don't compute with ADC shift
313 float adc0=0.;
314 if (!m_isMcOverlay && rndmEvtDigit->gain()>0) {
316 if (larOFC.cptr() != nullptr) {
317 ILArOFC::OFCRef_t ofc_a = larOFC->OFC_a(ch_id,rndmEvtDigit->gain(),0);
318 float sumOfc=0.;
319 if (ofc_a.size()>0) {
320 for (unsigned int j=0;j<ofc_a.size();j++) sumOfc += ofc_a.at(j);
321 }
322 if (sumOfc>0) adc0 = polynom_adc2mev[0] * SF /sumOfc;
323 }
324 }
325
326 int nmax=m_NSamples;
327 if ((int)(rndm_digit_samples.size()) < m_NSamples) {
329 "Less digit Samples than requested in digitization for cell "
330 << ch_id.get_compact() << " Digit has " << rndm_digit_samples.size()
331 << " samples. Digitization request " << m_NSamples);
332 nmax = rndm_digit_samples.size();
333 }
334 for(i=0 ; i<nmax ; i++)
335 {
336 rAdc = (rndm_digit_samples[i] - Pedestal ) * adc2energy + adc0;
337 rndm_energy_samples[i] = rAdc ;
338 Samples[i] += rAdc ;
339 }
340 }
341 else {
342 ATH_MSG_WARNING(" No ramp found for this random cell " << m_larem_id->show_to_string(cellId) << " for gain " << rndmEvtDigit->gain());
343 }
344 }
345//...................................................................
346
347//
348//........ choice of the gain
349//
350//
351// fix the shift +1 if HEC and nSamples 4 and firstSample 0
352 int ihecshift=0;
353 if(iCalo == HEC && m_NSamples.value() == 4 && m_firstSample.value() == 0) ihecshift=1;
354 float samp2=Samples[sampleGainChoice-ihecshift]*MeV2GeV;
355 if ( samp2 <= m_EnergyThresh ) return(StatusCode::SUCCESS);
356
357 if(m_doDigiTruth){
358 float Samp2_DigiHSTruth=Samples_DigiHSTruth[sampleGainChoice-ihecshift]*MeV2GeV;
359 if ( Samp2_DigiHSTruth <= m_EnergyThresh ) createDigit_DigiHSTruth = false;
360 }
361 //We choose the gain in applying thresholds on the 3rd Sample (index "2")
362 //converted in ADC counts in MediumGain (index "1" of (ADC2MEV)).
363 //Indeed, thresholds in ADC counts are defined with respect to the MediumGain.
364 //
365 // 1300 3900
366 // ---------------|----------------|--------------> ADC counts in MediumGain
367 // HighGain <--- MediumGain ---> LowGain
368
369 float pseudoADC3;
370 float Pedestal = pedestal->pedestal(ch_id,CaloGain::LARMEDIUMGAIN);
371 if (Pedestal <= (1.0+LArElecCalib::ERRORCODE)) {
372 ATH_MSG_DEBUG(" Pedestal not found for medium gain ,cellID " << cellId << " assume 1000 ");
373 Pedestal=1000.;
374 }
375 auto polynom_adc2mev = adc2MeVs->ADC2MEV(cellId,CaloGain::LARMEDIUMGAIN);
376 if ( polynom_adc2mev.size() < 2) {
377 ATH_MSG_WARNING(" No medium gain ramp found for cell " << m_larem_id->show_to_string(cellId) << " no digit produced...");
378 return StatusCode::SUCCESS;
379 }
380 pseudoADC3 = Samples[sampleGainChoice-ihecshift]/(polynom_adc2mev[1])/SF + Pedestal ;
381 //
382 // ......... try a gain
383 //
384 if (pseudoADC3 <= m_HighGainThresh[iCalo]) {
385 igain = CaloGain::LARHIGHGAIN;
386 } else if (pseudoADC3 <= m_LowGainThresh[iCalo]) {
388 } else {
389 igain = CaloGain::LARLOWGAIN;
390 }
391
392 // check that select gain is never lower than random gain in case of overlay
394 if (rndmGain==CaloGain::LARLOWGAIN ) igain=CaloGain::LARLOWGAIN;
395
396//
397// recompute Samples if igain != HIGHGAIN
398//
399 if (igain != initialGain ){
400 for (i=0;i<m_NSamples;i++) {
401 if(m_doDigiTruth) Samples_DigiHSTruth[i] = 0.;
402 if (m_RndmEvtOverlay) Samples[i]= rndm_energy_samples[i] ;
403 else Samples[i] = 0.;
404 }
405
406 if (!isDead) {
407 if( this->ConvertHits2Samples(ctx, cellId,ch_id,igain,TimeE, Samples) == StatusCode::FAILURE ) {
408 return StatusCode::SUCCESS;
409 }
410 if(m_doDigiTruth){
411 if( this->ConvertHits2Samples(ctx, cellId,ch_id,igain,TimeE_DigiHSTruth, Samples_DigiHSTruth) == StatusCode::FAILURE ) {
412 return StatusCode::SUCCESS;
413 }
414 }
415 }
416 }
417
418//
419// ........ add the noise ................................
420//
421
422 double Rndm[32]{};
423 int BvsEC=0;
424 if(iCalo==EM || iCalo==EMIW) BvsEC=std::abs(m_larem_id->barrel_ec(cellId));
425
426 bool addedNoise=false;
427 if (m_NoiseOnOff &&
428 ((BvsEC == 1 && m_NoiseInEMB) || (BvsEC > 1 && m_NoiseInEMEC) ||
429 (iCalo == HEC && m_NoiseInHEC) || (iCalo == FCAL && m_NoiseInFCAL)))
430 // add the noise only in the wanted sub-detectors
431 {
432 if (!m_RndmEvtOverlay) {
433 if (!m_pedestalNoise) {
434 SigmaNoise = noise->noise(ch_id, igain);
435 } else {
436 float noise = pedestal->pedestalRMS(ch_id, igain);
437 if (noise >= (1.0 + LArElecCalib::ERRORCODE))
438 SigmaNoise = noise;
439 else
440 SigmaNoise = 0.;
441 }
442 // Sqrt of noise covariance matrix
443 const std::vector<float>& CorGen =
444 autoCorrNoise->autoCorrSqrt(cellId, igain);
445 if (CorGen.size() < (unsigned)m_NSamples * m_NSamples) {
446 ATH_MSG_ERROR("Noise AutoCorr too small, need "
447 << m_NSamples * m_NSamples << " points for "
448 << m_NSamples << " samples.");
449 return StatusCode::FAILURE;
450 }
451
452 RandGaussZiggurat::shootArray(engine, m_NSamples, Rndm, 0., 1.);
453
454 int index;
455 for (int i = 0; i < m_NSamples; i++) {
456 Noise[i] = 0.;
457 for (int j = 0; j <= i; j++) {
458 index = i * m_NSamples + j;
459 Noise[i] += Rndm[j] * CorGen[index];
460 }
461 Noise[i] = Noise[i] * SigmaNoise;
462 }
463 addedNoise = true;
464 } else {
465 // overlay case a priori don't add any noise
466 for (int i = 0; i < m_NSamples; i++)
467 Noise[i] = 0.;
468 // if gain from zerobias events is < gain from mixed events => add extra
469 // noise to account for gain vs noise dependance
470 // done in a simple way without taking into account the time
471 // correlation of this extra noise properly
472 if (rndmEvtDigit) {
473 // if gain of cell is different from ZB event gain
474 if (igain > rndmEvtDigit->gain()) {
475 double SigmaNoiseZB = 0.; // noise in ZB event for gain of ZB event
476 double SigmaNoise = 0.; // noise expected for new gain value
477 double SigmaExtraNoise = 0.; // quadratic difference of noise values
478 if (!m_pedestalNoise) {
479 SigmaNoiseZB = noise->noise(ch_id, rndmEvtDigit->gain());
480 SigmaNoise = noise->noise(ch_id, igain);
481 } else {
482 float noise = pedestal->pedestalRMS(ch_id, rndmEvtDigit->gain());
483 if (noise >= (1.0 + LArElecCalib::ERRORCODE))
484 SigmaNoiseZB = noise;
485 else
486 SigmaNoiseZB = 0.;
487 noise = pedestal->pedestalRMS(ch_id, igain);
488 if (noise >= (1.0 + LArElecCalib::ERRORCODE))
489 SigmaNoise = noise;
490 else
491 SigmaNoise = 0.;
492 }
493 // Convert SigmaNoiseZB in noise in ADC counts for igain conversion
494 auto polynom_adc2mevZB =
495 adc2MeVs->ADC2MEV(cellId, rndmEvtDigit->gain());
496 auto polynom_adc2mev = adc2MeVs->ADC2MEV(cellId, igain);
497 if (polynom_adc2mevZB.size() > 1 && polynom_adc2mev.size() > 1) {
498 if (polynom_adc2mev[1] > 0.) {
499 SigmaNoiseZB = SigmaNoiseZB * (polynom_adc2mevZB[1]) /
500 (polynom_adc2mev[1]);
501 if (SigmaNoise > SigmaNoiseZB)
502 SigmaExtraNoise = sqrt(SigmaNoise * SigmaNoise -
503 SigmaNoiseZB * SigmaNoiseZB);
504 }
505 } // check that AC2MeV factors are there
506 RandGaussZiggurat::shootArray(engine, m_NSamples, Rndm, 0.,
507 1.); // generate noise
508 for (int i = 0; i < m_NSamples; i++)
509 Noise[i] = SigmaExtraNoise * Rndm[i];
510 addedNoise = true;
511 } // different gains
512 } // rndm Digit is there
513 } // rndm Overlay test
514 } // add noise ?
515 //
516// ......... convert into adc counts ................................
517//
518 Pedestal = pedestal->pedestal(ch_id,igain);
519 if (Pedestal <= (1.0+LArElecCalib::ERRORCODE)) {
520 ATH_MSG_WARNING(" pedestal not found for cellId " << cellId << " assume 1000" );
521 Pedestal=1000.;
522 }
523 polynom_adc2mev = adc2MeVs->ADC2MEV(cellId,igain);
524 if (polynom_adc2mev.size() < 2) {
525 ATH_MSG_WARNING(" No ramp found for requested gain " << igain << " for cell " << m_larem_id->show_to_string(cellId) << " no digit made...");
526 return StatusCode::SUCCESS;
527 }
528
529 energy2adc=1./(polynom_adc2mev[1])/SF;
530
531// in case Medium or low gain, take into account ramp intercept in energy->ADC computation
532// this requires to take into account the sum of the optimal filter coefficients, as they don't compute with ADC shift
533 if(!m_isMcOverlay && m_RndmEvtOverlay && igain>0)
534 {
536 if (larOFC.cptr() != nullptr) {
537 float sumOfc=0.;
538 ILArOFC::OFCRef_t ofc_a = larOFC->OFC_a(ch_id,igain,0);
539 if (ofc_a.size()>0) {
540 for (unsigned int j=0;j<ofc_a.size();j++) sumOfc+= ofc_a.at(j);
541 }
542 if ((polynom_adc2mev[1])>0 && sumOfc>0) Pedestal = Pedestal - (polynom_adc2mev[0])/(polynom_adc2mev[1])/sumOfc;
543 ATH_MSG_DEBUG(" Params for final LAr Digitization gain: " << igain << " pedestal: " << Pedestal << " energy2adc: " << energy2adc);
544 }
545 }
546 for(i=0;i<m_NSamples;i++)
547 {
548 double xAdc;
549 double xAdc_DigiHSTruth = 0;
550
551 if ( addedNoise ){
552 xAdc = Samples[i]*energy2adc + Noise[i] + Pedestal + 0.5;
553 if(m_doDigiTruth) {
554 xAdc_DigiHSTruth = Samples_DigiHSTruth[i]*energy2adc + Noise[i] + Pedestal + 0.5;
555 }
556 }
557
558 else {
559 if (m_roundingNoNoise) {
560 float flatRndm = RandFlat::shoot(engine);
561 xAdc = Samples[i]*energy2adc + Pedestal + flatRndm;
562 if(m_doDigiTruth) {
563 xAdc_DigiHSTruth = Samples_DigiHSTruth[i]*energy2adc + Pedestal + flatRndm;
564 }
565
566 }
567 else{
568 xAdc = Samples[i]*energy2adc + Pedestal + 0.5;
569 if(m_doDigiTruth) {
570 xAdc_DigiHSTruth = Samples_DigiHSTruth[i]*energy2adc + Pedestal + 0.5;
571 }
572 }
573
574 }
575
576//
577// ........ truncate at maximum value + 1
578// add possibility to saturate at 0 for negative signals
579//
580 if (xAdc <0) Adc=0;
581 else if (xAdc >= m_maxADC) Adc=m_maxADC;
582 else Adc = (short) xAdc;
583
584 AdcSample[i]=Adc;
585
586 if(m_doDigiTruth){
587 if (xAdc_DigiHSTruth <0) Adc_DigiHSTruth=0;
588 else if (xAdc_DigiHSTruth >= m_maxADC) Adc_DigiHSTruth=m_maxADC;
589 else Adc_DigiHSTruth = (short) xAdc_DigiHSTruth;
590 AdcSample_DigiHSTruth[i] = Adc_DigiHSTruth;
591 }
592
593#ifndef NDEBUG
594 ATH_MSG_DEBUG(" Sample " << i << " Energy= " << Samples[i] << " Adc=" << Adc);
595#endif
596
597 }
598
599//
600// ...... create the LArDigit .............
601//
602 Digit = dataItemsPool.nextElementPtr();
603 (*Digit)=LArDigit(ch_id,igain,std::move(AdcSample));
604
605 if (m_doDigiTruth && createDigit_DigiHSTruth) {
606 createDigit_DigiHSTruth = false;
607 Digit_DigiHSTruth = nullptr;
608
609 for (int i = 0; i < m_NSamples; i++) {
610 if (Samples_DigiHSTruth[i] != 0)
611 createDigit_DigiHSTruth = true;
612 }
613
614 Digit_DigiHSTruth =
615 new LArDigit(ch_id, igain, std::move(AdcSample_DigiHSTruth));
616 }
617
618 return StatusCode::SUCCESS;
619}
620
621// ---------------------------------------------------------------------------------------
622
623StatusCode LArHitEMapToDigitAlg::ConvertHits2Samples(const EventContext& ctx,
624 const Identifier & cellId, const HWIdentifier ch_id, CaloGain::CaloGain igain,
625 const std::vector<std::pair<float,float> > *TimeE, staticVecDouble_t &sampleList) const
626
627{
628// Converts hits of a particular LAr cell into energy samples
629// declarations
630 int nsamples ;
631 int nsamples_der ;
632 int i ;
633 int j ;
634 float energy ;
635 float time ;
636
638 const ILArShape* shape=*shapeHdl;
639
640
641// ........ retrieve data (1/2) ................................
642//
643 ILArShape::ShapeRef_t Shape = shape->Shape(ch_id,igain);
644 ILArShape::ShapeRef_t ShapeDer = shape->ShapeDer(ch_id,igain);
645
646 nsamples = Shape.size();
647 nsamples_der = ShapeDer.size();
648
649 if (nsamples==0) {
650 ATH_MSG_INFO(" No samples for cell = " << cellId );
651 return StatusCode::FAILURE;
652 }
653
654#ifndef NDEBUG
655 ATH_MSG_DEBUG(" Cellid " << m_larem_id->show_to_string(cellId));
656 for (i=0;i<nsamples;i++)
657 {
658 ATH_MSG_DEBUG(Shape[i] << " ");
659 }
660#endif
661
662 std::vector<std::pair<float,float> >::const_iterator first = TimeE->begin();
663 std::vector<std::pair<float,float> >::const_iterator last = TimeE->end();
664
665 while (first != last)
666 {
667 energy = (*first).first;
668 time = (*first).second;
669
670#ifndef NDEBUG
671 ATH_MSG_DEBUG("m_NSamples, m_usePhase " << m_NSamples << " " << m_usePhase);
672#endif
673
674 // fix the shift +1 if HEC and nSamples 4 and firstSample 0
675 // in case of data overlay this should NOT be done as the pulse shape read from the database is already shifted
676 // but this should still be done in case of MC overlay
677 int ihecshift=0;
678 if((!m_RndmEvtOverlay || m_isMcOverlay) && m_larem_id->is_lar_hec(cellId) && m_NSamples.value() == 4 && m_firstSample.value() == 0) ihecshift=1;
679
680
681 if (!m_usePhase) {
682
683 // Atlas like mode where we use 25ns binned pulse shape and derivative to deal with time offsets
684
685// shift between reference shape and this time
686 int ishift=(int)(rint(time*(1./25.)));
687 double dtime=time-25.*((double)(ishift));
688 for (i=0;i<m_NSamples.value();i++)
689 {
690 j = i - ishift + m_firstSample + ihecshift;
691#ifndef NDEBUG
692 ATH_MSG_DEBUG(" time/i/j " << time << " "<< i << " " << j);
693#endif
694 if (j >=0 && j < nsamples ) {
695 if (j<nsamples_der && std::abs(ShapeDer[j])<10. )
696 sampleList[i] += (Shape[j]- ShapeDer[j]*dtime)*energy ;
697 else sampleList[i] += Shape[j]*energy ;
698 }
699 }
700 }
701// Mode to use phase (tbin) to get pulse shape ( pulse shape with fine time binning should be available)
702
703 else {
704
705 // FIXME hardcode 8phases3ns configuration (cannot access parameters from ILArShape interface now)
706 int nTimeBins = 8;
707 float timeBinWidth = 25./24.*3.;
708
709// -50<t<-25 phase=-t-25, shift by one peak time (for s2 uses shape(3) with tbin)
710// for -25<t<0 phase = -t, no shift of peak time
711// for 0<t<25 phase=25-t, shift by one peak time (for s2 uses shape(1) with tbin)
712// 25<t<50 phase=50-t, shift by two
713// etc...
714
715 int ishift = (int)(time*(1./25.));
716 int tbin;
717 if (time>0) {
718 tbin = (int)(fmod(time,25)/timeBinWidth);
719 if (tbin>0) {
720 tbin=nTimeBins-tbin;
721 ishift +=1;
722 }
723 } else {
724 tbin = (int)(fmod(-time,25)/timeBinWidth);
725 }
726
727 double dtime = time - ( 25.*((float)(ishift)) - timeBinWidth*tbin);
728
729 Shape = shape->Shape(ch_id,igain,tbin);
730 ShapeDer = shape->ShapeDer(ch_id,igain,tbin);
731
732 nsamples = Shape.size();
733 nsamples_der = ShapeDer.size();
734
735
736 for (i=0;i<m_NSamples.value();i++)
737 {
738 j = i - ishift+m_firstSample + ihecshift;
739#ifndef NDEBUG
740 ATH_MSG_DEBUG(" time/i/j " << time << " "<< i << " " << j);
741#endif
742 if (j >=0 && j < nsamples ) {
743 if (j<nsamples_der && std::abs(ShapeDer[j])<10. )
744 sampleList[i] += (Shape[j]- ShapeDer[j]*dtime)*energy ;
745 else sampleList[i] += Shape[j]*energy ;
746 }
747 }
748
749 } // else if of m_usePhase
750
751 ++first;
752 } // loop over hits
753
754 return StatusCode::SUCCESS;
755
756}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Definition of CaloDetDescrManager.
interface to a tool that returns the time offset of the current trigger.
LArBadXCont< LArBadFeb > LArBadFebCont
LArBadXCont< LArBadChannel > LArBadChannelCont
static Double_t sc
const int nmax(200)
A wrapper class for event-slot-local random engines.
Definition RNGWrapper.h:56
SeedingOptionType
Options for seeding option=0 is setSeed as in MC20 option=1 is setSeedLegacy as in MC16 option=2 is s...
Definition RNGWrapper.h:97
void setSeedLegacy(const std::string &algName, size_t slot, uint64_t ev, uint64_t run, uint64_t offset, SeedingOptionType seeding, EventContext::ContextEvt_t evt=EventContext::INVALID_CONTEXT_EVT)
Set the random seed using a string (e.g.
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
const_iterator end() const
This class initializes the Calo (LAr and Tile) offline identifiers.
const LArHEC_ID * getHEC_ID(void) const
const LArFCAL_ID * getFCAL_ID(void) const
const LArEM_ID * getEM_ID(void) const
a typed memory pool that saves time spent allocation small object.
Definition DataPool.h:63
void reserve(unsigned int size)
Set the desired capacity.
pointer nextElementPtr()
obtain the next available element in pool by pointer pool is resized if its limit has been reached On...
LArVectorProxy OFCRef_t
This class defines the interface for accessing Optimal Filtering coefficients for each channel provid...
Definition ILArOFC.h:26
virtual float pedestal(const HWIdentifier &id, int gain) const =0
virtual float pedestalRMS(const HWIdentifier &id, int gain) const =0
access to RMS of Pedestal index by Identifier, and gain setting
LArVectorProxy ShapeRef_t
This class defines the interface for accessing Shape (Nsample variable, Dt = 25 ns fixed) @stereotype...
Definition ILArShape.h:26
virtual ShapeRef_t Shape(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
virtual ShapeRef_t ShapeDer(const HWIdentifier &id, int gain, int tbin=0, int mode=0) const =0
virtual const float & FSAMPL(const HWIdentifier &id) const =0
This is a "hash" representation of an Identifier.
value_type get_compact() const
Get the compact id.
const LArVectorProxy ADC2MEV(const HWIdentifier &id, int gain) const
Definition LArADC2MeV.h:32
const std::vector< float > & autoCorrSqrt(const HWIdentifier &id, int gain) const
LArBC_t status(const HWIdentifier channel) const
Query the status of a particular channel or FEB This is the main client access method.
Liquid Argon digit base class.
Definition LArDigit.h:25
CaloGain::CaloGain gain() const
Definition LArDigit.h:72
const std::vector< short > & samples() const
Definition LArDigit.h:78
Gaudi::Property< bool > m_usePhase
Gaudi::Property< double > m_EnergyThresh
Gaudi::Property< bool > m_isMcOverlay
const LArHEC_ID * m_larhec_id
Gaudi::Property< std::vector< std::string > > m_problemsToMask
static constexpr int s_MaxNSamples
Gaudi::Property< bool > m_NoiseInEMEC
Gaudi::Property< bool > m_doDigiTruth
SG::ReadHandleKey< LArHitEMap > m_hitMapKey
SG::ReadCondHandleKey< LArADC2MeV > m_adc2mevKey
const CaloCell_ID * m_calocell_id
Gaudi::Property< bool > m_pedestalNoise
Gaudi::Property< bool > m_roundingNoNoise
SG::ReadHandleKey< LArHitEMap > m_hitMapKey_DigiHSTruth
StatusCode MakeDigit(const EventContext &ctx, const Identifier &cellId, const HWIdentifier &ch_id, LArDigit *&Digit, DataPool< LArDigit > &dataItemsPool, LArDigit *&Digit_DigiHSTruth, const std::vector< std::pair< float, float > > *TimeE, const LArDigit *rndm_digit, CLHEP::HepRandomEngine *engine, const std::vector< std::pair< float, float > > *TimeE_DigiHSTruth=nullptr) const
virtual StatusCode execute(const EventContext &context) const
Gaudi::Property< uint32_t > m_randomSeedOffset
Gaudi::Property< bool > m_NoiseInEMB
SG::ReadCondHandleKey< LArBadChannelCont > m_bcContKey
Gaudi::Property< int > m_firstSample
SG::WriteHandleKey< LArDigitContainer > m_DigitContainerName_DigiHSTruth
const LArOnlineID * m_laronline_id
Gaudi::Property< bool > m_NoiseInHEC
boost::container::static_vector< double, s_MaxNSamples > staticVecDouble_t
Gaudi::Property< bool > m_useLegacyRandomSeeds
const LArFCAL_ID * m_larfcal_id
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKey
std::array< Gaudi::Property< double >, 4 > m_LowGainThresh
virtual StatusCode initialize()
SG::ReadCondHandleKey< ILArPedestal > m_pedestalKey
SG::ReadCondHandleKey< ILArNoise > m_noiseKey
SG::ReadCondHandleKey< CaloDetDescrManager > m_caloMgrKey
Gaudi::Property< bool > m_Windows
StatusCode ConvertHits2Samples(const EventContext &ctx, const Identifier &cellId, HWIdentifier ch_id, CaloGain::CaloGain igain, const std::vector< std::pair< float, float > > *TimeE, staticVecDouble_t &sampleList) const
Gaudi::Property< bool > m_NoiseOnOff
std::array< Gaudi::Property< double >, 4 > m_HighGainThresh
boost::container::static_vector< float, s_MaxNSamples > staticVecFloat_t
Gaudi::Property< bool > m_RndmEvtOverlay
Gaudi::Property< int > m_NSamples
SG::ReadCondHandleKey< ILArOFC > m_OFCKey
ServiceHandle< IAthRNGSvc > m_rndmGenSvc
SG::ReadCondHandleKey< LArAutoCorrNoise > m_autoCorrNoiseKey
const T * pointerFromKey(const EventContext &context, const SG::ReadCondHandleKey< T > &key) const
Gaudi::Property< bool > m_NoiseInFCAL
SG::ReadCondHandleKey< LArBadFebCont > m_badFebKey
SG::ReadCondHandleKey< ILArfSampl > m_fSamplKey
Gaudi::Property< unsigned > m_maxADC
SG::WriteHandleKey< LArDigitContainer > m_DigitContainerName
SG::ReadCondHandleKey< ILArShape > m_shapeKey
Gaudi::Property< std::string > m_randomStreamName
const LArHitList & GetCell(const unsigned int index) const
Definition LArHitEMap.h:43
const LArDigit * GetDigit(unsigned int index) const
Definition LArHitEMap.h:48
int GetNbCells(void) const
bool inWindows() const
Definition LArHitList.h:26
const LARLIST & getData() const
Definition LArHitList.h:25
value_type at(size_t i) const
Vector indexing with bounds check.
const_pointer_type cptr()
const_pointer_type cptr()
Dereference the pointer.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
@ LARMEDIUMGAIN
Definition CaloGain.h:18
@ LARLOWGAIN
Definition CaloGain.h:18
@ LARHIGHGAIN
Definition CaloGain.h:18
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
Definition index.py:1