ATLAS Offline Software
Loading...
Searching...
No Matches
LArSCL1Maker.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// + +
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 const auto* shapes = this->retrieve(context, m_shapesKey);
269
271 context);
272 auto scContainer = std::make_unique<LArDigitContainer>();
273
274 unsigned int nbSC = (unsigned int)m_scHelper->calo_cell_hash_max();
275 scContainer->reserve(nbSC);
276
277 // .... get SC cabling map
278 //
279 const LArOnOffIdMapping* cabling = this->retrieve(context, m_cablingKeySC);
280 if (!cabling) {
281 ATH_MSG_ERROR("Do not have SC cabling map !!!");
282 return StatusCode::FAILURE;
283 }
284
285 /* Disable HIT recording for the moment
286 CaloCellContainer *scHitContainer = 0;
287 if(m_saveHitsContainer.size()>0) {
288 scHitContainer = new CaloCellContainer;
289 ATH_CHECK( evtStore()->record(scHitContainer, m_saveHitsContainer) );
290 }
291 */
292
293 //
294 // ... initialise vectors for sums of energy in each TT
295 //
296 ATH_MSG_DEBUG("Max number of LAr Super-Cell= " << nbSC);
297
298 std::vector<std::vector<float> >
299 sumEnergy; // inner index = time slot (from 0 to visEvecSize-1)
300 std::vector<std::vector<float> >
301 sumTime; // inner index = time slot (from 0 to visEvecSize-1)
302 sumEnergy.resize(nbSC);
303 sumTime.resize(nbSC);
304 std::vector<float> scSumE;
305 int scSumEvecSize = 5;
306
307 scSumE.reserve(scSumEvecSize);
308 std::vector<std::vector<float> > scFloatContainerTmp;
309
310 int it = 0;
311 int it_end = hitmapPtr->GetNbCells();
312 scContainer->reserve(nbSC); // container ordered by hash
313 const std::vector<float> base_vec(0);
314 scFloatContainerTmp.assign(nbSC, base_vec); // container ordered by hash
315 std::vector<bool> alreadyThere;
316 alreadyThere.resize(nbSC);
317 alreadyThere.assign(nbSC, false);
318
319 std::vector<float> truthE;
320 truthE.resize(nbSC);
321 truthE.assign(nbSC, 0);
322
323 std::vector<HWIdentifier> hwid;
324 hwid.resize(nbSC);
325 hwid.assign(nbSC, HWIdentifier(0));
326
327 for (unsigned int i = 0; i < m_OnlSCHelper->channelHashMax(); ++i)
328 hwid[i] = m_OnlSCHelper->channel_Id(IdentifierHash(i));
329
330 // m_nSamples=5;
331 std::vector<float> samples;
332 samples.resize(m_nSamples);
333 std::vector<short> samplesInt;
334 samplesInt.reserve(m_nSamples);
336
337 for (; it != it_end; ++it) {
338 const LArHitList& hitlist = hitmapPtr->GetCell(it);
339 const std::vector<std::pair<float, float> >& timeE = hitlist.getData();
340 if (!timeE.empty()) {
341 Identifier cellId = m_OflHelper->cell_id(IdentifierHash(it));
342 Identifier scId = m_scidtool->offlineToSuperCellID(cellId);
343 IdentifierHash scHash = m_scHelper->calo_cell_hash(scId);
344 if (scHash.value() == 999999)
345 continue;
346 HWIdentifier hwSC = cabling->createSignalChannelID(scId);
347 IdentifierHash scHWHash = m_OnlSCHelper->channel_Hash(hwSC);
348
349 hwid[scHWHash] = hwSC;
350
351 float factor = 1.0;
352 if ((adc2mev->ADC2MEV(hwSC, scGain)).size() < 2) {
353 continue;
354 }
355 factor = (adc2mev->ADC2MEV(hwSC, scGain))[1];
356 factor = 1.0 / fracS->FSAMPL(hwSC) / factor;
357
358 ConvertHits2Samples(shapes, hwSC, scGain, timeE, samples);
359
360 std::vector<float>& vec = scFloatContainerTmp.at(scHWHash);
361 if (!alreadyThere[scHWHash]) {
362 alreadyThere[scHWHash] = true;
363 for (unsigned int i = 0; i < samples.size(); i++) {
364 vec.push_back(factor * samples[i]);
365 }
366 } else {
367 for (unsigned int i = 0; i < samples.size(); i++) {
368 vec[i] += (factor * samples[i]);
369 }
370 }
371 }
372 } // it end
373
374 it = 0;
375 it_end = nbSC;
376 short MAXADC = 4096; // 12 bits ADC?
377 std::vector<float> noise(m_nSamples);
378 double Rndm[32];
379 std::vector<float> zeroSamp;
380 zeroSamp.assign(m_nSamples, 0); // for empty channels
381 ATHRNG::RNGWrapper* rngWrapper =
382 m_atRndmGenSvc->getEngine(this, m_randomStreamName);
387 seedingmode);
388 CLHEP::HepRandomEngine* rndmEngine = rngWrapper->getEngine(context);
389 for (; it != it_end; ++it) {
390 std::vector<float>* vecPtr = &zeroSamp;
391 if (alreadyThere[it])
392 vecPtr = &(scFloatContainerTmp.at(it));
393 std::vector<float>& vec = *vecPtr;
394
395 const HWIdentifier id = hwid[it];
396 if (id == 0) {
397 continue;
398 }
399
400 // Do I have Overlay
401 size_t backGroundIdx = 999999;
402 if (addBkg && (IDtoIndexMap.find(id) != IDtoIndexMap.end()))
403 backGroundIdx = IDtoIndexMap.find(id)->second;
404
405 // reset noise
406 noise.assign(m_nSamples, 0);
407
408 // noise definition
409 if (m_NoiseOnOff && (backGroundIdx == 999999)) {
410 float SigmaNoise = (larnoise->noise(id, 0));
411 int index;
412 const std::vector<float>& CorrGen = (autoCorrNoise->autoCorrSqrt(id, 0));
413
414 RandGaussZiggurat::shootArray(rndmEngine, static_cast<int>(m_nSamples),
415 Rndm, 0., 1.);
416
417 for (int i = 0; i < (int)m_nSamples; i++) {
418 noise[i] = 0.;
419 for (int j = 0; j <= i; j++) {
420 index = i * m_nSamples + j;
421 noise[i] += Rndm[j] * (CorrGen)[index];
422 }
423 noise[i] = noise[i] * SigmaNoise;
424 }
425 }
426
427 if (backGroundIdx < 999999) { // bkgDigits exist and have compatible sizes
428 // assuming compatible sizes, see above
429 const std::vector<short>& bkgSamples =
430 bkgDigitsPtr->at(backGroundIdx)->samples();
431 samplesInt.assign(bkgSamples.begin(), bkgSamples.end());
432 } else {
433 int ped = pedestal->pedestal(id, 0); // DB pedestal
434 samplesInt.assign(m_nSamples, ped);
435 }
436 for (unsigned int i = 0; i < vec.size(); i++) {
437 samplesInt[i] += rint(vec[i] + noise[i]);
438 if (samplesInt[i] >= MAXADC)
439 samplesInt[i] = MAXADC - 1;
440 if (samplesInt[i] < 0)
441 samplesInt[i] = 0;
442 }
443 LArDigit* dig = new LArDigit(id, scGain, samplesInt);
444 scContainer->push_back(dig);
445 }
446 // record final output container
447 ATH_CHECK(scContainerHandle.record(std::move(scContainer)));
448
449 if (addBkg)
450 IDtoIndexMap.clear(); // clear event
451
452 if (m_chronoTest) {
453 m_chronSvc->chronoStop("LArSCL1Mk hit loop ");
454 m_chronSvc->chronoPrint("LArSCL1Mk hit loop ");
455 m_chronSvc->chronoStart("LArSCL1Mk SC loop ");
456 }
457
458 return StatusCode::SUCCESS;
459}
460
462
463 ATH_MSG_INFO(" LArSCL1Maker finalize completed successfully");
464 m_chronSvc->chronoPrint("LArSCL1Mk hit loop ");
465 m_chronSvc->chronoPrint("LArSCL1Mk TT loop ");
466
467 return StatusCode::SUCCESS;
468}
469
471 // will keep it for future implementation
472}
473
475 const ILArShape* shapes, const HWIdentifier& hwSC,
476 CaloGain::CaloGain igain,
477 const std::vector<std::pair<float, float> >& TimeE,
478 std::vector<float>& samples) const {
479 // Converts hits of a particular LAr cell into energy samples
480 // declarations
481
482 int nsamples;
483 int nsamples_der;
484 int i;
485 int j;
486 float energy;
487 float time;
488
489 // ........ retrieve data (1/2) ................................
490 //
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.
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
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
This is a "hash" representation of an Identifier.
constexpr 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
size_t GetNbCells(void) const
Definition LArHitEMap.h:42
const LArHitList & GetCell(const unsigned int index) const
Definition LArHitEMap.h:43
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 ILArShape *shapes, 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