ATLAS Offline Software
Loading...
Searching...
No Matches
ZdcLEDAnalysisTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include <sstream>
6#include <memory>
7
18#include <TFile.h>
19
20namespace ZDC
21{
22 ZdcLEDAnalysisTool::ZdcLEDAnalysisTool(const std::string& name) :
23 asg::AsgTool(name),
24 m_name(name)
25{
26
27
28#ifndef XAOD_STANDALONE
29 declareInterface<IZdcAnalysisTool>(this);
30#endif
31 declareProperty("ForceCalibRun", m_forceCalibRun = -1);
32 declareProperty("DoFADCCorr", m_doFADCCorr = false);
33}
34
36{
37 ATH_MSG_DEBUG("Deleting ZdcLEDAnalysisTool named " << m_name);
38}
39
41{
42 // Use configuration to direct initialization.
43 //
44 if (m_configuration == "ppPbPb2023") {
46 }
47 else if (m_configuration == "ppALFA2023") {
49 }
50 else if (m_configuration == "zdcStandalone") {
52 }
53 else {
54 ATH_MSG_ERROR("Unknown configuration: " << m_configuration);
55 return StatusCode::FAILURE;
56 }
57
58 // Check for valid configuration
59 //
61 ATH_MSG_ERROR("Invalid initialization of tool for configuration " << m_configuration);
62 return StatusCode::FAILURE;
63 }
64
65 ATH_MSG_INFO("doZDC: " << (m_doZDC ? "true" : "false"));
66 ATH_MSG_INFO("doRPD: " << (m_doRPD ? "true" : "false"));
67 ATH_MSG_INFO("Configuration: " << m_configuration);
68 ATH_MSG_DEBUG("AuxSuffix: " << m_auxSuffix);
69 ATH_MSG_DEBUG("NumSamples: " << m_numSamples);
70 ATH_MSG_DEBUG("Presample: " << m_preSample);
71 ATH_MSG_DEBUG("DeltaTSample: " << m_deltaTSample);
72
73 if (m_writeAux && m_auxSuffix != "") {
74 ATH_MSG_DEBUG("suffix string = " << m_auxSuffix);
75 }
76
77 std::ostringstream BCIDList;
78 BCIDList << "LED BCIDs:";
79
80 for (unsigned int idxLED = 0; idxLED < ZdcEventInfo::NumLEDs; idxLED++) {
81 BCIDList << m_LEDNames[idxLED] << " - BCID " << m_LEDBCID[idxLED];
82 if (idxLED < ZdcEventInfo::NumLEDs - 1) BCIDList << ", ";
83 }
84
85 ATH_MSG_DEBUG(BCIDList.str());
86
87
88 // If an aux suffix is provided, prepend it with "_" so we don't have to do so at each use
89 //
90 if (m_auxSuffix != "") m_auxSuffix = "_" + m_auxSuffix;
91
92 // initialize eventInfo access
93 //
94 ATH_CHECK( m_eventInfoKey.initialize());
95
96 // initialize keys for reading ZDC event-level aux decor information
97 //
99 ATH_CHECK(m_eventTypeKey.initialize());
100
101 m_DAQModeKey = m_zdcSumContainerName + ".DAQMode";
102 ATH_CHECK(m_DAQModeKey.initialize());
103
104 m_robBCIDKey = m_zdcSumContainerName + ".rodBCID";
105 ATH_CHECK(m_robBCIDKey.initialize());
106
107 // Initialize writeDecor handles
108 //
110 ATH_CHECK( m_ZdcLEDPresampleADC.initialize());
111
113 ATH_CHECK( m_ZdcLEDADCSum.initialize());
114
116 ATH_CHECK( m_ZdcLEDMaxADC.initialize());
117
119 ATH_CHECK( m_ZdcLEDMaxSample.initialize());
120
122 ATH_CHECK( m_ZdcLEDAvgTime.initialize());
123
124 // The LED type gets writting to the module 0 sum container
125 //
127 ATH_CHECK( m_ZdcLEDType.initialize());
128
129 // prepare FADC correction per sample
130
131 m_init = true;
132 return StatusCode::SUCCESS;
133}
134
136{
137 // Use the defaults for now except for sampleAnaStart values and the BCIDs
138 //
141
142 m_LEDBCID = {1152, 1154, 1156};
143 m_LEDCalreqIdx = {2, 1, 0};
144}
145
147{
148 // Use the defaults for now except for sampleAnaStart values and the BCIDs
149 //
152
153 m_LEDBCID = {3476, 3479, 3482};
154 m_LEDCalreqIdx = {0, 1, 2};
155}
156
158{
159 // Use the defaults for now except for sampleAnaStart values and the BCIDs
162
163 m_LEDBCID = {3479, 3482, 3485};
164 m_LEDCalreqIdx = {0 ,1 ,2};
165}
166
168 const xAOD::ZdcModuleContainer& moduleSumContainer)
169{
170 if (!m_init) {
171 ATH_MSG_WARNING("Tool not initialized!");
172 return StatusCode::FAILURE;
173 }
174
175 if (moduleContainer.size()==0) return StatusCode::SUCCESS; // if no modules, do nothing
176
178 if (!eventInfo.isValid()) return StatusCode::FAILURE;
179
180 bool zdcErr = eventInfo->isEventFlagBitSet(xAOD::EventInfo::ForwardDet, ZdcEventInfo::ZDCDECODINGERROR );
181 bool rpdErr = eventInfo->isEventFlagBitSet(xAOD::EventInfo::ForwardDet, ZdcEventInfo::RPDDECODINGERROR );
182 if (zdcErr||rpdErr)
183 {
184 ATH_MSG_WARNING("ZDC or RPD decoding error found - abandoning ZdcLEDAnalysisTool!");
185 return StatusCode::SUCCESS;
186 }
187
188 unsigned int thisRunNumber = eventInfo->runNumber();
189 if (thisRunNumber != m_runNumber) {
190 ATH_MSG_INFO("ZDC LED analysis tool will be configured for run " << thisRunNumber << " m_doFADCCorr = " << m_doFADCCorr);
191 if (m_doFADCCorr)
192 {
193 unsigned int calibRunNumber = thisRunNumber;
194 if (m_forceCalibRun > -1) calibRunNumber = m_forceCalibRun;
195 ATH_MSG_INFO("FADC corrections will be configured for run " << calibRunNumber);
196 setFADCCorrections(calibRunNumber);
197 }
198 m_runNumber = thisRunNumber;
199 }
202
203 // Loop over the sum container to find event-level info (side == 0)
204 //
205 bool haveZdcEventInfo = false;
206 unsigned int eventType = ZdcEventInfo::ZdcEventUnknown;
207 unsigned int bcid = eventInfo->bcid();
208 unsigned int DAQMode = ZdcEventInfo::DAQModeUndef;
209
210 const xAOD::ZdcModule* moduleSumEventInfo_ptr = 0;
211
212 for (auto modSum : moduleSumContainer) {
213 //
214 // Module sum object with side == 0 contains event-level information
215 //
216 if (modSum->zdcSide() == 0) {
217 //
218 // Add the event type and bcid as aux decors
219 //
220 ATH_MSG_DEBUG("Found global sum");
221 eventType = eventTypeHandle(*modSum);
222 DAQMode = DAQModeHandle(*modSum);
223 haveZdcEventInfo = true;
224 moduleSumEventInfo_ptr = modSum;
225 }
226 }
227 if (!haveZdcEventInfo) {
228 ATH_MSG_ERROR("Zdc event data not available (moduleSum with side = 0)");
229 return StatusCode::FAILURE;
230 }
231
232 //
233 // only do something on LED calibration events
234 //
235 if (eventType != ZdcEventInfo::ZdcEventLED) return StatusCode::SUCCESS;
236
237 // In standalone mode, we have to read the BCID from the rob header
238 //
239 if (DAQMode == ZdcEventInfo::Standalone) {
241 if (!robBCIDHandle.isValid()) return StatusCode::FAILURE;
242
243 const std::vector<uint16_t>& robBCIDvec = robBCIDHandle(*moduleSumEventInfo_ptr);
244 if (robBCIDHandle->size() == 0) return StatusCode::FAILURE;
245
246 unsigned int checkBCID = robBCIDvec[0];
247 for (unsigned int bcid : robBCIDvec) {
248 if (bcid != checkBCID) {
249 ATH_MSG_ERROR("Inconsistent BCIDs in rob header, cannot continue in standalone mode");
250 return StatusCode::FAILURE;
251 }
252 }
253
254 bcid = checkBCID;
255 }
256
257 // Determine the LED type
258 //
259 unsigned int evtLEDType = ZdcEventInfo::LEDNone;
260
261 for (unsigned int idxLED = 0; idxLED < ZdcEventInfo::NumLEDs; idxLED++) {
262 //
263 // Does the BCID match one of those associated with the LEDs?
264 //
265 if (m_LEDBCID[idxLED] == bcid) {
266 if (DAQMode != ZdcEventInfo::Standalone) {
267 //
268 // Also check the calreq trigger (to be implemented)
269 //
270 if (false) continue;
271 }
272
273 evtLEDType = idxLED;
274 break;
275 }
276 }
277
278 if (evtLEDType == ZdcEventInfo::LEDNone) {
279 //
280 // Thie BCID does not appear to be associated with one of the LEDs, print warning and quit processing
281 //
282 ATH_MSG_WARNING("Unexpected BCID found in data: bcid = " << bcid << m_configuration);
283 return StatusCode::SUCCESS;
284 }
285 else {
286 ATH_MSG_DEBUG("Event with BCID = " << bcid << " has LED type " << evtLEDType);
287 }
288
289 // We are currently calculating the presample as an unsigned it, but there is another "presample"
290 // from ZdcAnalysisTool which for good reasons is float. So we have to match the type.
291 //
297
299
300 ATH_MSG_DEBUG("Starting event processing for LED " << m_LEDNames[evtLEDType]);
301
302 for (const auto zdcModule : moduleContainer)
303 {
304 ZDCLEDModuleResults results;
305 if (zdcModule->zdcType() == 0) {
306 results = processZDCModule(*zdcModule);
307 }
308 else if (zdcModule->zdcType() == 1 && zdcModule->zdcModule() == 4) {
309 results = processRPDModule(*zdcModule);
310 }
311
312 ATH_MSG_DEBUG("Writing aux decors to module with side, module, channel = " << zdcModule->zdcSide() << ", " << zdcModule->zdcModule()
313 << ", " << zdcModule->zdcChannel());
314
315 moduleLEDPresampleADCHandle(*zdcModule) = std::floor(results.getPresampleADC() + 1.0e-6);
316 moduleLEDADCSumHandle(*zdcModule) = results.getADCSum();
317 moduleLEDMaxADCHandle(*zdcModule) = results.getMaxADC();
318 moduleLEDMaxSampleHandle(*zdcModule) = results.getMaxSample();
319 moduleLEDAvgTimeHandle(*zdcModule) = results.getAvgTime();
320 }
321
322 // Write the LED type to the moduleSum container keep event-level data
323 //
324 LEDTypeHandle(*moduleSumEventInfo_ptr) = evtLEDType;
325
326 ATH_MSG_DEBUG("Finishing event processing");
327
328
329 return StatusCode::SUCCESS;
330 }
331
333{
334 if (!m_init) {
335 ATH_MSG_WARNING("Tool not initialized!");
336 return StatusCode::FAILURE;
337 }
338
339 ATH_MSG_DEBUG ("Trying to retrieve " << m_zdcModuleContainerName);
340
341 m_zdcModules = 0;
343
344
346
347 return StatusCode::SUCCESS;
348}
349
351{
352 ATH_MSG_DEBUG("Processing ZDC side, channel = " << module.zdcSide() << ", " << module.zdcModule());
353 bool doLG = false;
354
355 static const SG::ConstAccessor<std::vector<uint16_t> > g1dataAcc ("g1data");
356 static const SG::ConstAccessor<std::vector<uint16_t> > g0dataAcc ("g0data");
357 std::vector<uint16_t> HGSamples = g1dataAcc (module);
358 std::vector<uint16_t> LGSamples = g0dataAcc (module);
359
360 std::vector<uint16_t>::const_iterator maxIter = std::max_element(HGSamples.begin(), HGSamples.end());
361 if (maxIter != HGSamples.end()) {
362 if (*maxIter > m_HGADCOverflow) doLG = true;
363 }
364
365 if (doLG) {
366 return processModuleData(module.zdcSide(),module.zdcModule(),LGSamples, m_sampleAnaStartZDC, m_sampleAnaEndZDC, m_ZdcLowGainScale);
367 }
368 else {
369 return processModuleData(module.zdcSide(),module.zdcModule(),HGSamples, m_sampleAnaStartZDC, m_sampleAnaEndZDC, 1);
370 }
371}
372
374{
375 ATH_MSG_DEBUG("Processing RPD side, channel = " << module.zdcSide() << ", " << module.zdcChannel());
376 static const SG::ConstAccessor<std::vector<uint16_t> > g0dataAcc ("g0data");
377 return processModuleData(-1,-1,g0dataAcc (module), m_sampleAnaStartRPD, m_sampleAnaEndRPD, 1);
378}
379
380ZDCLEDModuleResults ZdcLEDAnalysisTool::processModuleData(int iside, int imod, const std::vector<unsigned short>& data,
381 unsigned int startSample, unsigned int endSample, float gainScale)
382{
383
384 int ADCSum = 0;
385 int maxADCsub = -999;
386 unsigned int maxSample = 0;
387 float avgTime = 0.f;
388 bool highgain = (gainScale<1.1); // HG is 1 and LG is 10
389
390 if (startSample > m_numSamples || endSample > m_numSamples) {
391 ATH_MSG_ERROR("Start or end sample number greater than number of samples");
392 return ZDCLEDModuleResults();
393 }
394
395 int preFADC = data[m_preSample];
396
397 for (unsigned int sample = startSample; sample <= endSample; sample++) {
398
399 int FADCsub = data[sample] - preFADC;
400 if (m_doFADCCorr && (iside!=-1) ) // iside==-1 dummy to indicate RPD and ensure no FADC correction
401 {
402 float corr = getAmplitudeCorrection(iside,imod,highgain,FADCsub);
403 FADCsub *= corr;
404 }
405
406 float time = (sample + 0.5f)*m_deltaTSample;
407 ADCSum += FADCsub;
408 if (FADCsub > maxADCsub) {
409 maxADCsub = FADCsub;
410 maxSample = sample;
411 }
412
413 avgTime += time*FADCsub;
414 }
415 if (ADCSum!=0){
416 avgTime /= ADCSum;
417 } else {
418 avgTime = 0.f; //used as default in the ZDCLEDModuleResults c'tor
419 }
420
421 return ZDCLEDModuleResults(preFADC, ADCSum*gainScale, maxADCsub*gainScale, maxSample, avgTime);
422}
423
424// FADC corrections
425
426double ZdcLEDAnalysisTool::getAmplitudeCorrection(int iside, int imod, bool highGain, float fitAmp)
427{
428 double amplCorrFactor = 1;
429
430 double fadcCorr = highGain ? m_FADCCorrHG[iside][imod]->Interpolate(fitAmp) : m_FADCCorrLG[iside][imod]->Interpolate(fitAmp);
431 amplCorrFactor *= fadcCorr;
432
433 return amplCorrFactor;
434}
435
436void ZdcLEDAnalysisTool::setFADCCorrections(unsigned int runNumber)
437{
438 std::string filename;
439 std::string runString;
440
441 if (runNumber == 0) runString = "ZdcFADCCorr_" + m_configuration + "_default.root";
442 else runString = ("ZdcFADCCorr_Run"+TString::Itoa(runNumber,10)+".root").Data();
443
444 filename = PathResolverFindCalibFile("ZdcAnalysis/" + runString );
445
446 if (filename.empty())
447 {
448 ATH_MSG_INFO("No FADC corrections file - disabling correction");
449 m_doFADCCorr = false; // disable correction
450 return;
451 }
452
453 ATH_MSG_INFO("Opening FADC corrections file " << filename);
454 std::unique_ptr<TFile> fFADCCorr(TFile::Open(filename.c_str(), "READ"));
455
456 if (!fFADCCorr->IsOpen()) {
457 ATH_MSG_INFO ("setFADCCorrections: failed to open file: " << filename << ". Disabling correction.");
458 m_doFADCCorr = false; // disable correctio
459 return;
460 //throw std::runtime_error ("ZdcAnalysisTool failed to open FADCCorrections file " + filename);
461 }
462
463 // Attempt to read histograms with corrections from file
464 //
465 bool readSuccess = true;
466 std::array<std::array<std::unique_ptr<const TH1>, 4>, 2> histogramsHG;
467 std::array<std::array<std::unique_ptr<const TH1>, 4>, 2> histogramsLG;
468
469 for (size_t side : {0, 1}) {
470 for (int module : {0, 1, 2, 3}) {
471 std::string histNameHG = "ZDC_FADCCorr_s" + std::to_string(side) + "_m" + std::to_string(module)+"_HG";
472 std::string histNameLG = "ZDC_FADCCorr_s" + std::to_string(side) + "_m" + std::to_string(module)+"_LG";
473
474 ATH_MSG_DEBUG("setFADCCorrections: Searching for histograms HG and LG: " << histNameHG << ", " << histNameLG);
475
476 TH1* histHG_ptr = static_cast<TH1*>(fFADCCorr->GetObjectChecked(histNameHG.c_str(), "TH1"));
477 TH1* histLG_ptr = static_cast<TH1*>(fFADCCorr->GetObjectChecked(histNameLG.c_str(), "TH1"));
478
479 if (!histHG_ptr || !histLG_ptr) {
480 std::string errMsg = "setFADCCorrections: unable to read FADC correction histogram(s) ";
481 if (!histHG_ptr) errMsg += histNameHG + " ";
482 if (!histLG_ptr) errMsg += histNameLG;
483
484 ATH_MSG_ERROR(errMsg);
485 readSuccess = false;
486 break;
487 }
488 else {
489 //
490 // Check for valid range (Lion uses -0.5 to 4095.5)
491 //
492
493 if ( std::abs(histHG_ptr->GetXaxis()->GetXmin()+0.5) > 1e-3 || std::abs(histHG_ptr->GetXaxis()->GetXmax() - 4095.5) > 1e-3) {
494 ATH_MSG_ERROR("setFADCCorrections: invalid axis range for HG FADC corrections in histogram with name " << histNameHG);
495 readSuccess = false;
496 break;
497 }
498 if (std::abs(histLG_ptr->GetXaxis()->GetXmin()+0.5) > 1e-3 || std::abs(histLG_ptr->GetXaxis()->GetXmax() - 4095.5) > 1e-3) {
499 ATH_MSG_ERROR("setFADCCorrections: invalid axis range for HG FADC corrections in histogram with name " << histNameLG);
500 readSuccess = false;
501 break;
502 }
503 ATH_MSG_INFO("Configuring FADC histos for side " << side << " mod " << module);
504 m_FADCCorrHG[side][module].reset(histHG_ptr);
505 m_FADCCorrLG[side][module].reset(histLG_ptr);
506
507 }
508 }
509 }
510
511 fFADCCorr->Close();
512
513 if (readSuccess) {
514 ATH_MSG_INFO("Successfully configured FADC correction");
515 m_doFADCCorr = true;
516 }
517 else {
518 ATH_MSG_ERROR("setFADCCorrections: due to at least one error, FADC corrections are not implemented");
519 m_doFADCCorr = false;
520 }
521
522 return;
523}
524
525
526} // namespace ZDC
527
#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)
Handle class for reading a decoration on an object.
Handle class for reading from StoreGate.
Handle class for adding a decoration to an object.
Handle class for recording to StoreGate.
@ Data
Definition BaseObject.h:11
Helper class to provide constant type-safe access to aux data.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
std::string PathResolverFindCalibFile(const std::string &logical_file_name)
Define enumerations for event-level ZDC data.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
size_type size() const noexcept
Returns the number of elements in the collection.
Helper class to provide constant type-safe access to aux data.
Handle class for reading a decoration on an object.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Handle class for adding a decoration to an object.
Gaudi::Property< std::string > m_auxSuffix
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_ZdcLEDADCSum
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_ZdcLEDMaxADC
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_ZdcLEDAvgTime
double getAmplitudeCorrection(int iside, int imod, bool highGain, float fitAmp)
ZDCLEDModuleResults processRPDModule(const xAOD::ZdcModule &module)
const xAOD::ZdcModuleContainer * m_zdcModules
Gaudi::Property< bool > m_doZDC
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
Gaudi::Property< bool > m_doRPD
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_ZdcLEDMaxSample
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_ZdcLEDType
std::array< std::array< std::unique_ptr< const TH1 >, 4 >, 2 > m_FADCCorrLG
std::array< std::array< std::unique_ptr< const TH1 >, 4 >, 2 > m_FADCCorrHG
void setFADCCorrections(unsigned int runNumber)
StatusCode reprocessZdc() override
StatusCode initialize() override
Dummy implementation of the initialisation function.
ZdcLEDAnalysisTool(const std::string &name)
StatusCode recoZdcModules(const xAOD::ZdcModuleContainer &moduleContainer, const xAOD::ZdcModuleContainer &moduleSumContainer) override
const std::vector< std::string > m_LEDNames
SG::ReadDecorHandleKey< xAOD::ZdcModuleContainer > m_eventTypeKey
Gaudi::Property< std::string > m_zdcSumContainerName
const xAOD::ZdcModuleContainer * m_zdcSums
SG::ReadDecorHandleKey< xAOD::ZdcModuleContainer > m_DAQModeKey
std::vector< unsigned int > m_LEDCalreqIdx
SG::ReadDecorHandleKey< xAOD::ZdcModuleContainer > m_robBCIDKey
Gaudi::Property< std::string > m_zdcModuleContainerName
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_ZdcLEDPresampleADC
ZDCLEDModuleResults processModuleData(int iside, int imod, const std::vector< unsigned short > &data, unsigned int startSample, unsigned int endSample, float gainScale)
ZDCLEDModuleResults processZDCModule(const xAOD::ZdcModule &module)
Gaudi::Property< std::string > m_configuration
std::vector< unsigned int > m_LEDBCID
virtual ~ZdcLEDAnalysisTool() override
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
@ ForwardDet
The forward detectors.
ZdcModuleContainer_v1 ZdcModuleContainer
ZdcModule_v1 ZdcModule
Definition ZdcModule.h:15