ATLAS Offline Software
Loading...
Searching...
No Matches
LArSCL1Maker.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5// +======================================================================+
6// + +
7// + Author ........: Denis O. Damazio , Will Buttinger (Cambridge) +
8// + Institut ......: BNL +
9// + Creation date .: 18/11/2013 +
10// + +
11// +======================================================================+
12//
13// ........ includes
14//
15#include "LArSCL1Maker.h"
16// .......... utilities
17//
18#include <math.h>
19
20#include <fstream>
21
23//
24#include "CLHEP/Random/RandGaussZiggurat.h"
25#include "CLHEP/Random/RandomEngine.h"
26#include "GaudiKernel/ServiceHandle.h"
27//
30//
39//
40// ........ Gaudi needed includes
41//
42#include "Gaudi/Property.h"
43#include "GaudiKernel/IChronoStatSvc.h"
44#include "GaudiKernel/IIncidentSvc.h"
45#include "GaudiKernel/IService.h"
46#include "GaudiKernel/IToolSvc.h"
47#include "GaudiKernel/TypeNameString.h"
48#include "GaudiKernel/MsgStream.h"
51
52// trigger time
54
55//
56
57using CLHEP::RandGaussZiggurat;
58
59LArSCL1Maker::LArSCL1Maker(const std::string& name, ISvcLocator* pSvcLocator)
60 : AthReentrantAlgorithm(name, pSvcLocator)
61 //, p_triggerTimeTool()
62 ,
63 m_scidtool("CaloSuperCellIDTool"),
64 m_scHelper(nullptr),
65 m_OnlSCHelper(nullptr),
66 m_incSvc("IncidentSvc", name) {
67 //
68 // ........ default values of private data
69 //
70
71 m_chronSvc = nullptr;
72 m_useTriggerTime = false;
73 // m_triggerTimeToolName = "CosmicTriggerTimeTool";
74
76
77 // m_ttSvc = 0;
78 m_scHelper = nullptr;
79
80 m_NoiseOnOff = true;
81 m_PileUp = false;
82 m_noEmCalibMode = false;
83 m_noHadCalibMode = false;
84 m_chronoTest = false;
85
86 //
87 // ........ declare the private data as properties
88 //
89
90 declareProperty("SubDetectors", m_SubDetectors = "LAr_All");
91
92 declareProperty("NoiseOnOff", m_NoiseOnOff);
93
94 declareProperty("PileUp", m_PileUp);
95 declareProperty("UseTriggerTime", m_useTriggerTime);
96 // declareProperty("TriggerTimeTool",p_triggerTimeTool);
97
98 declareProperty("FirstSample", m_firstSample = -1);
99 declareProperty("NSamples", m_nSamples = 7);
100
101 declareProperty("ChronoTest", m_chronoTest);
102
103 declareProperty("TruthHitsContainer", m_saveHitsContainer = "",
104 "Specify to save hits");
105 //
106 return;
107}
108
111
112 return;
113}
114
116 // +======================================================================+
117 // + +
118 // + Author ........: Denis O. Damazio +
119 // + Creation date .: 18/11/2013 +
120 // + +
121 // +======================================================================+
122 //
123 // ......... declaration
124 //
125 m_chronSvc = chronoSvc();
126
127 ATH_MSG_INFO("***********************************************");
128 ATH_MSG_INFO("* Steering options for LArSCL1Maker algorithm *");
129 ATH_MSG_INFO("***********************************************");
130
131 //
132 // ......... print the noise flag
133 //
134 if (m_NoiseOnOff) {
136 "Electronic noise will be added in each SC for selected "
137 "sub-detectors.");
138 } else {
139 ATH_MSG_INFO("No electronic noise added.");
140 }
141
142 //
143 // ......... print the pile-up flag
144 //
145 if (m_PileUp) {
146 ATH_MSG_INFO("take events from PileUp service");
147 } else {
148 ATH_MSG_INFO("no pile up");
149 }
150
151 //
152 // ......... print the trigger time flag
153 //
154 // if (m_useTriggerTime) { ATH_MSG_INFO("use Trigger Time service " <<
155 // p_triggerTimeTool.name()); } else { ATH_MSG_INFO("no Trigger Time used");
156 // }
157
158 //
159 // .........retrieve tool computing trigger time if requested
160 //
161 if (m_useTriggerTime && m_PileUp) {
163 " In case of pileup, the trigger time subtraction is done in "
164 "PileUpSvc ");
165 ATH_MSG_INFO(" => LArSCL1Maker will not apply Trigger Time ");
166 m_useTriggerTime = false;
167 }
168
169 /*
170 if (m_useTriggerTime) {
171 if( p_triggerTimeTool.retrieve().isFailure() ) {
172 ATH_MSG_ERROR("Unable to retrieve trigger time tool. Disabling Trigger
173 time"); m_useTriggerTime=false;
174 }
175 }
176 */
177
178 //
179 // ..... need LAr and CaloIdManager to retrieve all needed helpers
180 //
181
182 const CaloIdManager* caloMgr;
183
184 CHECK(detStore()->retrieve(caloMgr));
186 CHECK(detStore()->retrieve(m_OflHelper, "CaloCell_ID"));
187
188 //
189 //..... need of course the LVL1 helper
190 //
192 if (!m_scHelper) {
193 ATH_MSG_ERROR("Could not access CaloCell_SuperCell_ID helper");
194 return StatusCode::FAILURE;
195 } else {
196 ATH_MSG_DEBUG("Successfully accessed CaloCell_SuperCell_ID helper");
197 }
198
199 // ..... need cabling services, to get channels associated to each SC
200 //
201
202 CHECK(m_cablingKeySC.initialize());
203 CHECK(m_shapesKey.initialize());
204 CHECK(m_fracSKey.initialize());
205 CHECK(m_pedestalSCKey.initialize());
206 CHECK(m_noiseSCKey.initialize());
207 CHECK(m_autoCorrNoiseSCKey.initialize());
208 CHECK(m_adc2mevSCKey.initialize());
209 CHECK(m_scidtool.retrieve());
210 CHECK(m_sLArDigitsContainerKey.initialize());
211 CHECK(m_hitMapKey.initialize());
212 CHECK(m_bkgDigitsKey.initialize(!m_bkgDigitsKey.empty()));
213
214 // Incident Service:
215 ATH_MSG_DEBUG("Initialization completed successfully");
216
217 CHECK(m_atRndmGenSvc.retrieve());
218
219 return StatusCode::SUCCESS;
220}
221
222StatusCode LArSCL1Maker::execute(const EventContext& context) const {
223
224 ATH_MSG_DEBUG("Begining of execution");
225
226 //
227 // ....... fill the LArHitEMap
228 //
230 const LArHitEMap* hitmapPtr = hitmap.cptr();
231
232 bool addBkg(false);
233 const LArDigitContainer* bkgDigitsPtr = nullptr;
234 std::map<HWIdentifier, size_t> IDtoIndexMap;
235 if (!m_bkgDigitsKey.empty()) {
236 addBkg = true;
238 bkgDigitsPtr = bkgDigits.cptr();
239 unsigned int digitCount(0);
240 for (const auto* const bkgDigit : *bkgDigitsPtr) {
241 IDtoIndexMap.insert({bkgDigit->channelID(), digitCount});
242 digitCount++;
243 }
244 // check size compatibility with first LArDigit
245 if ((unsigned int)bkgDigitsPtr->at(0)->nsamples() != m_nSamples) {
246 addBkg = false; // don't add background
248 "Uncompatible background and signal LArDigit size : Overlay "
249 "requested but will not be performed");
250 }
251 } // end of check if the Key is empty
252 //
253 // .....get the trigger time if requested
254 //
255 // double trigtime=0;
256 /*
257 if (m_useTriggerTime && !p_triggerTimeTool.empty()) {
258 trigtime = p_triggerTimeTool->time();
259 }
260 ATH_MSG_DEBUG("Trigger time used : " << trigtime);
261 */
262
263 const auto* fracS = this->retrieve(context, m_fracSKey);
264 const auto* pedestal = this->retrieve(context, m_pedestalSCKey);
265 const auto* larnoise = this->retrieve(context, m_noiseSCKey);
266 const auto* autoCorrNoise = this->retrieve(context, m_autoCorrNoiseSCKey);
267 const auto* adc2mev = this->retrieve(context, m_adc2mevSCKey);
268
270 context);
271 auto scContainer = std::make_unique<LArDigitContainer>();
272
273 unsigned int nbSC = (unsigned int)m_scHelper->calo_cell_hash_max();
274 scContainer->reserve(nbSC);
275
276 // .... get SC cabling map
277 //
278 const LArOnOffIdMapping* cabling = this->retrieve(context, m_cablingKeySC);
279 if (!cabling) {
280 ATH_MSG_ERROR("Do not have SC cabling map !!!");
281 return StatusCode::FAILURE;
282 }
283
284 /* Disable HIT recording for the moment
285 CaloCellContainer *scHitContainer = 0;
286 if(m_saveHitsContainer.size()>0) {
287 scHitContainer = new CaloCellContainer;
288 ATH_CHECK( evtStore()->record(scHitContainer, m_saveHitsContainer) );
289 }
290 */
291
292 //
293 // ... initialise vectors for sums of energy in each TT
294 //
295 ATH_MSG_DEBUG("Max number of LAr Super-Cell= " << nbSC);
296
297 std::vector<std::vector<float> >
298 sumEnergy; // inner index = time slot (from 0 to visEvecSize-1)
299 std::vector<std::vector<float> >
300 sumTime; // inner index = time slot (from 0 to visEvecSize-1)
301 sumEnergy.resize(nbSC);
302 sumTime.resize(nbSC);
303 std::vector<float> scSumE;
304 int scSumEvecSize = 5;
305
306 scSumE.reserve(scSumEvecSize);
307 std::vector<std::vector<float> > scFloatContainerTmp;
308
309 int it = 0;
310 int it_end = hitmapPtr->GetNbCells();
311 scContainer->reserve(nbSC); // container ordered by hash
312 const std::vector<float> base_vec(0);
313 scFloatContainerTmp.assign(nbSC, base_vec); // container ordered by hash
314 std::vector<bool> alreadyThere;
315 alreadyThere.resize(nbSC);
316 alreadyThere.assign(nbSC, false);
317
318 std::vector<float> truthE;
319 truthE.resize(nbSC);
320 truthE.assign(nbSC, 0);
321
322 std::vector<HWIdentifier> hwid;
323 hwid.resize(nbSC);
324 hwid.assign(nbSC, HWIdentifier(0));
325
326 for (unsigned int i = 0; i < m_OnlSCHelper->channelHashMax(); ++i)
327 hwid[i] = m_OnlSCHelper->channel_Id(IdentifierHash(i));
328
329 // m_nSamples=5;
330 std::vector<float> samples;
331 samples.resize(m_nSamples);
332 std::vector<short> samplesInt;
333 samplesInt.reserve(m_nSamples);
335
336 for (; it != it_end; ++it) {
337 const LArHitList& hitlist = hitmapPtr->GetCell(it);
338 const std::vector<std::pair<float, float> >& timeE = hitlist.getData();
339 if (!timeE.empty()) {
340 Identifier cellId = m_OflHelper->cell_id(IdentifierHash(it));
341 Identifier scId = m_scidtool->offlineToSuperCellID(cellId);
342 IdentifierHash scHash = m_scHelper->calo_cell_hash(scId);
343 if (scHash.value() == 999999)
344 continue;
345 HWIdentifier hwSC = cabling->createSignalChannelID(scId);
346 IdentifierHash scHWHash = m_OnlSCHelper->channel_Hash(hwSC);
347
348 hwid[scHWHash] = hwSC;
349
350 float factor = 1.0;
351 if ((adc2mev->ADC2MEV(hwSC, scGain)).size() < 2) {
352 continue;
353 }
354 factor = (adc2mev->ADC2MEV(hwSC, scGain))[1];
355 factor = 1.0 / fracS->FSAMPL(hwSC) / factor;
356
357 ConvertHits2Samples(context, hwSC, scGain, timeE, samples);
358
359 std::vector<float>& vec = scFloatContainerTmp.at(scHWHash);
360 if (!alreadyThere[scHWHash]) {
361 alreadyThere[scHWHash] = true;
362 for (unsigned int i = 0; i < samples.size(); i++) {
363 vec.push_back(factor * samples[i]);
364 }
365 } else {
366 for (unsigned int i = 0; i < samples.size(); i++) {
367 vec[i] += (factor * samples[i]);
368 }
369 }
370 }
371 } // it end
372
373 it = 0;
374 it_end = nbSC;
375 short MAXADC = 4096; // 12 bits ADC?
376 std::vector<float> noise(m_nSamples);
377 double Rndm[32];
378 std::vector<float> zeroSamp;
379 zeroSamp.assign(m_nSamples, 0); // for empty channels
380 ATHRNG::RNGWrapper* rngWrapper =
381 m_atRndmGenSvc->getEngine(this, m_randomStreamName);
386 seedingmode);
387 CLHEP::HepRandomEngine* rndmEngine = rngWrapper->getEngine(context);
388 for (; it != it_end; ++it) {
389 std::vector<float>* vecPtr = &zeroSamp;
390 if (alreadyThere[it])
391 vecPtr = &(scFloatContainerTmp.at(it));
392 std::vector<float>& vec = *vecPtr;
393
394 const HWIdentifier id = hwid[it];
395 if (id == 0) {
396 continue;
397 }
398
399 // Do I have Overlay
400 size_t backGroundIdx = 999999;
401 if (addBkg && (IDtoIndexMap.find(id) != IDtoIndexMap.end()))
402 backGroundIdx = IDtoIndexMap.find(id)->second;
403
404 // reset noise
405 noise.assign(m_nSamples, 0);
406
407 // noise definition
408 if (m_NoiseOnOff && (backGroundIdx == 999999)) {
409 float SigmaNoise = (larnoise->noise(id, 0));
410 int index;
411 const std::vector<float>& CorrGen = (autoCorrNoise->autoCorrSqrt(id, 0));
412
413 RandGaussZiggurat::shootArray(rndmEngine, static_cast<int>(m_nSamples),
414 Rndm, 0., 1.);
415
416 for (int i = 0; i < (int)m_nSamples; i++) {
417 noise[i] = 0.;
418 for (int j = 0; j <= i; j++) {
419 index = i * m_nSamples + j;
420 noise[i] += Rndm[j] * (CorrGen)[index];
421 }
422 noise[i] = noise[i] * SigmaNoise;
423 }
424 }
425
426 if (backGroundIdx < 999999) { // bkgDigits exist and have compatible sizes
427 // assuming compatible sizes, see above
428 const std::vector<short>& bkgSamples =
429 bkgDigitsPtr->at(backGroundIdx)->samples();
430 samplesInt.assign(bkgSamples.begin(), bkgSamples.end());
431 } else {
432 int ped = pedestal->pedestal(id, 0); // DB pedestal
433 samplesInt.assign(m_nSamples, ped);
434 }
435 for (unsigned int i = 0; i < vec.size(); i++) {
436 samplesInt[i] += rint(vec[i] + noise[i]);
437 if (samplesInt[i] >= MAXADC)
438 samplesInt[i] = MAXADC - 1;
439 if (samplesInt[i] < 0)
440 samplesInt[i] = 0;
441 }
442 LArDigit* dig = new LArDigit(id, scGain, samplesInt);
443 scContainer->push_back(dig);
444 }
445 // record final output container
446 ATH_CHECK(scContainerHandle.record(std::move(scContainer)));
447
448 if (addBkg)
449 IDtoIndexMap.clear(); // clear event
450
451 if (m_chronoTest) {
452 m_chronSvc->chronoStop("LArSCL1Mk hit loop ");
453 m_chronSvc->chronoPrint("LArSCL1Mk hit loop ");
454 m_chronSvc->chronoStart("LArSCL1Mk SC loop ");
455 }
456
457 return StatusCode::SUCCESS;
458}
459
461
462 ATH_MSG_INFO(" LArSCL1Maker finalize completed successfully");
463 m_chronSvc->chronoPrint("LArSCL1Mk hit loop ");
464 m_chronSvc->chronoPrint("LArSCL1Mk TT loop ");
465
466 return StatusCode::SUCCESS;
467}
468
470 // will keep it for future implementation
471}
472
474 const EventContext& context, const HWIdentifier& hwSC,
475 CaloGain::CaloGain igain,
476 const std::vector<std::pair<float, float> >& TimeE,
477 std::vector<float>& samples) const {
478 // Converts hits of a particular LAr cell into energy samples
479 // declarations
480
481 int nsamples;
482 int nsamples_der;
483 int i;
484 int j;
485 float energy;
486 float time;
487
488 // ........ retrieve data (1/2) ................................
489 //
490 const auto* shapes = this->retrieve(context, m_shapesKey);
491 ILArShape::ShapeRef_t Shape = shapes->Shape(hwSC, igain);
492 ILArShape::ShapeRef_t ShapeDer = shapes->ShapeDer(hwSC, igain);
493
494 nsamples = Shape.size();
495 nsamples_der = ShapeDer.size();
496
497 if (nsamples == 0) {
498 std::cout << " No samples for cell = " << hwSC << std::endl;
499 return;
500 }
501
502 std::vector<std::pair<float, float> >::const_iterator first = TimeE.begin();
503 std::vector<std::pair<float, float> >::const_iterator last = TimeE.end();
504 samples.clear();
505 samples.assign(m_nSamples, 0);
506 // m_firstSample=0;
507
508 while (first != last) {
509 energy = (*first).first;
510 time = (*first).second;
511
512 // Atlas like mode where we use 25ns binned pulse shape and derivative to
513 // deal with time offsets
514 // shift between reference shape and this time
515 int ishift = (int)(rint(time * (1. / 25)));
516 double dtime = time - 25. * ((double)(ishift));
517
518 for (i = 0; i < (int)m_nSamples; i++) {
519 j = i - ishift + m_firstSample;
520 if (j >= 0 && j < nsamples) {
521 if (j < nsamples_der && std::fabs(ShapeDer[j]) < 10.)
522 samples[i] += (Shape[j] - ShapeDer[j] * dtime) * energy;
523 else
524 samples[i] += Shape[j] * energy;
525 }
526 }
527
528 ++first;
529 } // loop over hits
530
531 return;
532}
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_DEBUG(x)
Helper class for offline supercell identifiers.
std::vector< size_t > vec
#define CHECK(...)
Evaluate an expression and check for errors.
interface to a tool that returns the time offset of the current trigger.
#define MAXADC
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
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
const ServiceHandle< StoreGateSvc > & detStore() const
An algorithm that can be simultaneously executed in multiple threads.
const_iterator end() const
This class initializes the Calo (LAr and Tile) offline identifiers.
const CaloCell_SuperCell_ID * getCaloCell_SuperCell_ID(void) const
const T * at(size_type n) const
Access an element, as an rvalue.
LArVectorProxy ShapeRef_t
This class defines the interface for accessing Shape (Nsample variable, Dt = 25 ns fixed) @stereotype...
Definition ILArShape.h:26
This is a "hash" representation of an Identifier.
value_type value() const
Container class for LArDigit.
Liquid Argon digit base class.
Definition LArDigit.h:25
const std::vector< short > & samples() const
Definition LArDigit.h:78
const LArHitList & GetCell(const unsigned int index) const
Definition LArHitEMap.h:43
int GetNbCells(void) const
const LARLIST & getData() const
Definition LArHitList.h:25
unsigned int m_firstSample
output first samples
SG::ReadCondHandleKey< ILArPedestal > m_pedestalSCKey
Property: Pedestal offset (conditions input).
bool m_noEmCalibMode
algorithm property: no calibration mode for EM towers
SG::ReadCondHandleKey< ILArNoise > m_noiseSCKey
Property: Electronics Noise (conditions input).
bool m_NoiseOnOff
algorithm property: noise (in all sub-detectors) is on if true
SG::WriteHandleKey< LArDigitContainer > m_sLArDigitsContainerKey
output Lar Digits SC container
SG::ReadCondHandleKey< ILArShape > m_shapesKey
Property: Pulse shape (conditions input).
SG::ReadCondHandleKey< LArADC2MeV > m_adc2mevSCKey
Property: ADC2MeV conversion (conditions input).
int m_BeginRunPriority
pointer to the TriggerTimeTool
StatusCode initialize()
Read ascii files for auxiliary data (puslse shapes, noise, etc...)
const T * retrieve(const EventContext &context, const SG::ReadCondHandleKey< T > &handleKey) const
const CaloCell_SuperCell_ID * m_scHelper
pointer to the offline TT helper
bool m_useTriggerTime
Alorithm property: use trigger time or not.
Gaudi::Property< uint32_t > m_randomSeedOffset
Gaudi::Property< std::string > m_randomStreamName
IChronoStatSvc * m_chronSvc
ServiceHandle< IAthRNGSvc > m_atRndmGenSvc
bool m_chronoTest
algorithm property: switch chrono on
SG::ReadHandleKey< LArDigitContainer > m_bkgDigitsKey
Background Digit Overlay, default key is Bkg_LArDigitSCL2.
void ConvertHits2Samples(const EventContext &context, const HWIdentifier &hwSC, CaloGain::CaloGain igain, const std::vector< std::pair< float, float > > &TimeE, std::vector< float > &samples) const
Method for converting Hits from samples (simplified version of the same method in LarPileUpTool)
bool m_PileUp
algorithm property: pile up or not
std::string m_saveHitsContainer
std::string m_SubDetectors
algorithm property: sub-detectors to be simulated
ToolHandle< ICaloSuperCellIDTool > m_scidtool
ServiceHandle< IIncidentSvc > m_incSvc
SG::ReadCondHandleKey< LArAutoCorrNoise > m_autoCorrNoiseSCKey
Property: AutoCorr Noise (conditions input).
Gaudi::Property< bool > m_useLegacyRandomSeeds
SG::ReadCondHandleKey< LArOnOffIdMapping > m_cablingKeySC
LArSCL1Maker(const std::string &name, ISvcLocator *pSvcLocator)
constructor
StatusCode execute(const EventContext &context) const
Create LArSCL1 object save in TES (2 containers: 1 EM, 1 hadronic)
SG::ReadCondHandleKey< ILArfSampl > m_fracSKey
Property: Fraction of Energy Sampled (conditions input).
const LArOnline_SuperCellID * m_OnlSCHelper
pointer to the online LAr helper
StatusCode finalize()
~LArSCL1Maker()
destructor
SG::ReadHandleKey< LArHitEMap > m_hitMapKey
hit map
unsigned int m_nSamples
output number of samples
const CaloCell_ID * m_OflHelper
pointer to the offline id helper
void printConditions(const HWIdentifier &hwSC)
Method to print SuperCell Conditions.
bool m_noHadCalibMode
algorithm property: no calibration mode for had towers
const_pointer_type cptr()
Dereference the pointer.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
@ LARHIGHGAIN
Definition CaloGain.h:18
Definition index.py:1