ATLAS Offline Software
Loading...
Searching...
No Matches
RPDAnalysisTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
6
8#include "ZdcUtils/RPDUtils.h"
11
12namespace ZDC {
13
14RPDAnalysisTool::RPDAnalysisTool(std::string const& name) : asg::AsgTool(name) {
15 declareProperty("ZdcModuleContainerName", m_ZDCModuleContainerName = "ZdcModules", "Location of ZDC processed data");
16 declareProperty("ZdcSumContainerName", m_ZDCSumContainerName = "ZdcSums", "Location of ZDC processed sums");
17 declareProperty("Configuration", m_configuration = "default");
18 declareProperty("WriteAux", m_writeAux = true);
19 declareProperty("AuxSuffix", m_auxSuffix = "");
20
21 declareProperty("NSamples", m_forceNSamples, "Total number of FADC samples in readout window");
22 declareProperty("NBaselineSamples", m_forceNBaselineSamples, "Number of baseline samples; the sample equal to this number is the start of signal region");
23 declareProperty("EndSignalSample", m_forceEndSignalSample, "Samples before (not including) this sample are the signal region; 0 or Nsamples goes to end of window");
24 declareProperty("Pulse2ndDerivThresh", m_forcePulse2ndDerivThresh, "Second differences less than or equal to this number indicate a pulse");
25 declareProperty("PostPulseFracThresh", m_forcePostPulseFracThresh, "If there is a good pulse and post-pulse and size of post-pulse as a fraction of good pulse is less than or equal to this number, ignore post-pulse");
26 declareProperty("GoodPulseSampleStart", m_forceGoodPulseSampleStart, "Pulses before this sample are considered pre-pulses");
27 declareProperty("GoodPulseSampleStop", m_forceGoodPulseSampleStop, "Pulses after this sample are considered post-pulses");
28 declareProperty("NominalBaseline", m_forceNominalBaseline, "The global nominal baseline; used when pileup is detected");
29 declareProperty("PileupBaselineSumThresh", m_forcePileupBaselineSumThresh, "Baseline sum (after subtracting nominal baseline) less than this number indicates there is NO pileup");
30 declareProperty("PileupBaselineStdDevThresh", m_forcePileupBaselineStdDevThresh, "Baseline standard deviations less than this number indicate there is NO pileup");
31 declareProperty("NNegativesAllowed", m_forceNNegativesAllowed, "Maximum number of negative ADC values after baseline and pileup subtraction allowed in signal range");
32 declareProperty("ADCOverflow", m_forceADCOverflow, "ADC values greater than or equal to this number are considered overflow");
33 declareProperty("SideCCalibFactors", m_forceOutputCalibFactors.at(RPDUtils::sideC), "Multiplicative calibration factors to apply to RPD output, e.g., sum/max ADC, per channel on side C");
34 declareProperty("SideACalibFactors", m_forceOutputCalibFactors.at(RPDUtils::sideA), "Multiplicative calibration factors to apply to RPD output, e.g., sum/max ADC, per channel on side A");
35}
36
37StatusCode RPDAnalysisTool::initializeWriteKey(std::string const& containerName, SG::WriteDecorHandleKey<xAOD::ZdcModuleContainer> & writeHandleKey, std::string const& key) {
38 writeHandleKey = containerName + key + m_auxSuffix;
39 return writeHandleKey.initialize();
40}
41
43 RPDConfig finalConfig {};
44 std::array<std::vector<float>, 2> finalOutputCalibFactors;
45 // first initialize reconstruction parameters
46 finalConfig.nSamples = 24;
47 finalConfig.nBaselineSamples = 7;
48 finalConfig.endSignalSample = 23;
49 finalConfig.pulse2ndDerivThresh = -18;
50 finalConfig.postPulseFracThresh = 0.15;
51 finalConfig.goodPulseSampleStart = 8;
52 finalConfig.goodPulseSampleStop = 10;
53 finalConfig.nominalBaseline = 100;
54 finalConfig.pileupBaselineSumThresh = 53;
55 finalConfig.pileupBaselineStdDevThresh = 2;
56 finalConfig.nNegativesAllowed = 2;
57 finalConfig.ADCOverflow = 4095;
58 finalOutputCalibFactors.at(RPDUtils::sideC) = std::vector<float>(16, 1.0);
59 finalOutputCalibFactors.at(RPDUtils::sideA) = std::vector<float>(16, 1.0);
60
61 // then overwrite individual parameters from configuration if any were provided
62 if (m_forceNSamples.has_value()) {
63 finalConfig.nSamples = m_forceNSamples.value();
64 }
65 if (m_forceNBaselineSamples.has_value()) {
66 finalConfig.nBaselineSamples = m_forceNBaselineSamples.value();
67 }
68 if (m_forceEndSignalSample.has_value()) {
69 finalConfig.endSignalSample = m_forceEndSignalSample.value();
70 }
71 if (m_forcePulse2ndDerivThresh.has_value()) {
73 }
74 if (m_forcePostPulseFracThresh.has_value()) {
76 }
77 if (m_forceGoodPulseSampleStart.has_value()) {
79 }
80 if (m_forceGoodPulseSampleStop.has_value()) {
82 }
83 if (m_forceNominalBaseline.has_value()) {
84 finalConfig.nominalBaseline = m_forceNominalBaseline.value();
85 }
86 if (m_forcePileupBaselineSumThresh.has_value()) {
88 }
89 if (m_forcePileupBaselineStdDevThresh.has_value()) {
91 }
92 if (m_forceNNegativesAllowed.has_value()) {
93 finalConfig.nNegativesAllowed = m_forceNNegativesAllowed.value();
94 }
95 if (m_forceADCOverflow.has_value()) {
96 finalConfig.ADCOverflow = m_forceADCOverflow.value();
97 }
98 for (auto const side : RPDUtils::sides) {
99 if (m_forceOutputCalibFactors.at(side).has_value()) {
100 finalOutputCalibFactors.at(side) = m_forceOutputCalibFactors.at(side).value();
101 }
102 }
103
104 ATH_MSG_DEBUG("RPDAnalysisTool reconstruction parameters:");
105 ATH_MSG_DEBUG("config = " << m_configuration);
106 ATH_MSG_DEBUG("nSamples = " << finalConfig.nSamples);
107 ATH_MSG_DEBUG("nBaselineSamples = " << finalConfig.nBaselineSamples);
108 ATH_MSG_DEBUG("endSignalSample = " << finalConfig.endSignalSample);
109 ATH_MSG_DEBUG("pulse2ndDerivThresh = " << finalConfig.pulse2ndDerivThresh);
110 ATH_MSG_DEBUG("postPulseFracThresh = " << finalConfig.postPulseFracThresh);
111 ATH_MSG_DEBUG("goodPulseSampleStart = " << finalConfig.goodPulseSampleStart);
112 ATH_MSG_DEBUG("goodPulseSampleStop = " << finalConfig.goodPulseSampleStop);
113 ATH_MSG_DEBUG("nominalBaseline = " << finalConfig.nominalBaseline);
114 ATH_MSG_DEBUG("pileupBaselineSumThresh = " << finalConfig.pileupBaselineSumThresh);
115 ATH_MSG_DEBUG("pileupBaselineStdDevThresh = " << finalConfig.pileupBaselineStdDevThresh);
116 ATH_MSG_DEBUG("nNegativesAllowed = " << finalConfig.nNegativesAllowed);
117 ATH_MSG_DEBUG("ADCOverflow = " << finalConfig.ADCOverflow);
118 ATH_MSG_DEBUG("sideCCalibFactors = " << RPDUtils::vecToString(finalOutputCalibFactors.at(RPDUtils::sideC)));
119 ATH_MSG_DEBUG("sideACalibFactors = " << RPDUtils::vecToString(finalOutputCalibFactors.at(RPDUtils::sideA)));
120
121 m_dataAnalyzers.at(RPDUtils::sideC) = std::make_unique<RPDDataAnalyzer>(MakeMessageFunction(), "rpdC", finalConfig, finalOutputCalibFactors.at(RPDUtils::sideC));
122 m_dataAnalyzers.at(RPDUtils::sideA) = std::make_unique<RPDDataAnalyzer>(MakeMessageFunction(), "rpdA", finalConfig, finalOutputCalibFactors.at(RPDUtils::sideA));
123
124 // initialize per-channel decorations (in ZdcModules)
139
140 // initialize per-side decorations (in ZdcSums)
142
143 ATH_CHECK( m_eventInfoKey.initialize());
144
145 if (m_writeAux && !m_auxSuffix.empty()) {
146 ATH_MSG_DEBUG("Suffix string = " << m_auxSuffix);
147 }
148
149 m_initialized = true;
150 return StatusCode::SUCCESS;
151}
152
154 return std::make_shared<ZDCMsg::MessageFunction>(
155 [this] (int const messageZdcLevel, const std::string& message) -> bool {
156 auto const messageAthenaLevel = static_cast<MSG::Level>(messageZdcLevel);
157 bool const passesStreamOutputLevel = messageAthenaLevel >= this->msg().level();
158 if (passesStreamOutputLevel) {
159 this->msg(messageAthenaLevel) << message << endmsg;
160 }
161 return passesStreamOutputLevel;
162 }
163 );
164}
165
167 for (auto & analyzer : m_dataAnalyzers) {
168 analyzer->reset();
169 }
170}
171
173 // loop through ZDC modules to find those which are RPD channels
174 for (auto const module : moduleContainer) {
175 if (module->zdcType() != RPDUtils::ZDCModuleRPDType) {
176 // this is not an RPD channel, so skip it
177 continue;
178 }
179 unsigned int const side = RPDUtils::ZDCSideToSideIndex(module->zdcSide());
180 if (module->zdcChannel() < 0 || static_cast<unsigned int>(module->zdcChannel()) > RPDUtils::nChannels - 1) {
181 ATH_MSG_ERROR("Invalid RPD channel found on side " << side << ": channel number = " << module->zdcChannel());
182 }
183 // channel numbers are fixed in mapping in ZdcConditions, numbered 0-15
184 unsigned int const channel = module->zdcChannel();
185 ATH_MSG_DEBUG("RPD side " << side << " channel " << module->zdcChannel());
186 SG::ConstAccessor<std::vector<uint16_t>> accessor("g0data");
187 auto const& waveform = accessor(*module);
188 m_dataAnalyzers.at(side)->loadChannelData(channel, waveform);
189 }
190}
191
193 for (auto & analyzer : m_dataAnalyzers) {
194 analyzer->analyzeData();
195 }
196}
197
198void RPDAnalysisTool::writeAOD(xAOD::ZdcModuleContainer const& moduleContainer, xAOD::ZdcModuleContainer const& moduleSumContainer) const {
199 if (!m_writeAux) {
200 return;
201 }
202
203 ATH_MSG_DEBUG("Adding variables with suffix = " + m_auxSuffix);
204
205 // write per-channel decorations (in ZdcModules)
220 for (auto const module : moduleContainer) {
221 if (module->zdcType() != RPDUtils::ZDCModuleRPDType) {
222 // this is not an RPD channel, so skip it
223 continue;
224 }
225 unsigned int const side = RPDUtils::ZDCSideToSideIndex(module->zdcSide());
226 unsigned int const channel = module->zdcChannel();
227 chBaseline(*module) = m_dataAnalyzers.at(side)->getChBaseline(channel);
228 chPileupExpFitParams(*module) = m_dataAnalyzers.at(side)->getChPileupExpFitParams(channel);
229 chPileupStretchedExpFitParams(*module) = m_dataAnalyzers.at(side)->getChPileupStretchedExpFitParams(channel);
230 chPileupExpFitParamErrs(*module) = m_dataAnalyzers.at(side)->getChPileupExpFitParamErrs(channel);
231 chPileupStretchedExpFitParamErrs(*module) = m_dataAnalyzers.at(side)->getChPileupStretchedExpFitParamErrs(channel);
232 chPileupExpFitMSE(*module) = m_dataAnalyzers.at(side)->getChPileupExpFitMSE(channel);
233 chPileupStretchedExpFitMSE(*module) = m_dataAnalyzers.at(side)->getChPileupStretchedExpFitMSE(channel);
234 chAmplitude(*module) = m_dataAnalyzers.at(side)->getChSumAdc(channel);
235 chAmplitudeCalib(*module) = m_dataAnalyzers.at(side)->getChSumAdcCalib(channel);
236 chMaxADC(*module) = m_dataAnalyzers.at(side)->getChMaxAdc(channel);
237 chMaxADCCalib(*module) = m_dataAnalyzers.at(side)->getChMaxAdcCalib(channel);
238 chMaxSample(*module) = m_dataAnalyzers.at(side)->getChMaxSample(channel);
239 chStatus(*module) = m_dataAnalyzers.at(side)->getChStatus(channel);
240 chPileupFrac(*module) = m_dataAnalyzers.at(side)->getChPileupFrac(channel);
241 }
242
243 // write per-side decorations (in ZdcSums)
245 for (auto const sum: moduleSumContainer) {
246 if (sum->zdcSide() == RPDUtils::ZDCSumsGlobalZDCSide) {
247 // skip global sum (it's like the side between sides)
248 continue;
249 }
250 unsigned int const side = RPDUtils::ZDCSideToSideIndex(sum->zdcSide());
251 sideStatus(*sum) = m_dataAnalyzers.at(side)->getSideStatus();
252 }
253}
254
255StatusCode RPDAnalysisTool::recoZdcModules(xAOD::ZdcModuleContainer const& moduleContainer, xAOD::ZdcModuleContainer const& moduleSumContainer) {
256 if (moduleContainer.empty()) {
257 return StatusCode::SUCCESS; // if no modules, do nothing
258 }
259
261 if (!eventInfo.isValid()) {
262 return StatusCode::FAILURE;
263 }
264
265 if (eventInfo->isEventFlagBitSet(xAOD::EventInfo::ForwardDet, ZdcEventInfo::RPDDECODINGERROR)) {
266 ATH_MSG_WARNING("RPD decoding error found - abandoning RPD reco!");
267 return StatusCode::SUCCESS;
268 }
269
270 reset();
271 readAOD(moduleContainer);
272 analyze();
273 writeAOD(moduleContainer, moduleSumContainer);
274
275 return StatusCode::SUCCESS;
276}
277
279 if (!m_initialized) {
280 ATH_MSG_WARNING("Tool not initialized!");
281 return StatusCode::FAILURE;
282 }
283 xAOD::ZdcModuleContainer const* ZDCModules = nullptr;
284 ATH_CHECK(evtStore()->retrieve(ZDCModules, m_ZDCModuleContainerName));
285 xAOD::ZdcModuleContainer const* ZDCSums = nullptr;
286 ATH_CHECK(evtStore()->retrieve(ZDCSums, m_ZDCSumContainerName));
287 return recoZdcModules(*ZDCModules, *ZDCSums);
288}
289
290} // namespace ZDC
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Handle class for adding a decoration to an object.
Define enumerations for event-level ZDC data.
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
ServiceHandle< StoreGateSvc > & evtStore()
bool empty() const noexcept
Returns true if the collection is empty.
Helper class to provide constant type-safe access to aux data.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
Property holding a SG store/key/clid/attr name from which a WriteDecorHandle is made.
StatusCode initialize(bool used=true)
If this object is used as a property, then this should be called during the initialize phase.
Handle class for adding a decoration to an object.
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chPileupStretchedExpFitParamErrsKey
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_sideStatusKey
RPDUtils::OptionalToolProperty< float > m_forcePostPulseFracThresh
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chAmplitudeCalibKey
RPDUtils::OptionalToolProperty< unsigned int > m_forceNBaselineSamples
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chPileupExpFitParamErrsKey
std::string m_ZDCSumContainerName
RPDAnalysisTool(std::string const &name)
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chPileupExpFitParamsKey
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chBaselineKey
RPDUtils::OptionalToolProperty< unsigned int > m_forceADCOverflow
RPDUtils::OptionalToolProperty< unsigned int > m_forceGoodPulseSampleStop
RPDUtils::OptionalToolProperty< unsigned int > m_forceEndSignalSample
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chMaxSampleKey
void readAOD(xAOD::ZdcModuleContainer const &moduleContainer)
RPDUtils::OptionalToolProperty< float > m_forcePileupBaselineStdDevThresh
RPDUtils::OptionalToolProperty< unsigned int > m_forceGoodPulseSampleStart
StatusCode reprocessZdc() override
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chAmplitudeKey
std::string m_ZDCModuleContainerName
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chStatusKey
ZDCMsg::MessageFunctionPtr MakeMessageFunction()
RPDUtils::OptionalToolProperty< unsigned int > m_forceNNegativesAllowed
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chMaxADCCalibKey
RPDUtils::OptionalToolProperty< unsigned int > m_forceNSamples
SG::ReadHandleKey< xAOD::EventInfo > m_eventInfoKey
StatusCode recoZdcModules(xAOD::ZdcModuleContainer const &moduleContainer, xAOD::ZdcModuleContainer const &moduleSumContainer) override
StatusCode initialize() override
Dummy implementation of the initialisation function.
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chPileupStretchedExpFitMSEKey
std::string m_configuration
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chMaxADCKey
StatusCode initializeWriteKey(std::string const &containerName, SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > &writeHandleKey, std::string const &key)
std::array< std::unique_ptr< RPDDataAnalyzer >, 2 > m_dataAnalyzers
RPDUtils::OptionalToolProperty< float > m_forceNominalBaseline
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chPileupStretchedExpFitParamsKey
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chPileupExpFitMSEKey
void writeAOD(xAOD::ZdcModuleContainer const &moduleContainer, xAOD::ZdcModuleContainer const &moduleSumContainer) const
SG::WriteDecorHandleKey< xAOD::ZdcModuleContainer > m_chPileupFracKey
RPDUtils::OptionalToolProperty< float > m_forcePulse2ndDerivThresh
RPDUtils::OptionalToolProperty< float > m_forcePileupBaselineSumThresh
std::array< RPDUtils::OptionalToolProperty< std::vector< float > >, 2 > m_forceOutputCalibFactors
AsgTool(const std::string &name)
Constructor specifying the tool instance's name.
Definition AsgTool.cxx:58
@ ForwardDet
The forward detectors.
unsigned int ZDCSideToSideIndex(int const ZDCSide)
Definition RPDUtils.cxx:7
int constexpr ZDCSumsGlobalZDCSide
Definition RPDUtils.h:19
unsigned int constexpr nChannels
Definition RPDUtils.h:23
unsigned int constexpr ZDCModuleRPDType
Definition RPDUtils.h:21
unsigned int constexpr sideC
Definition RPDUtils.h:15
unsigned int constexpr sideA
Definition RPDUtils.h:16
std::initializer_list< unsigned int > constexpr sides
Definition RPDUtils.h:17
std::string vecToString(std::vector< T > const &v)
Definition RPDUtils.cxx:57
std::shared_ptr< MessageFunction > MessageFunctionPtr
Definition ZDCMsg.h:14
ZdcModuleContainer_v1 ZdcModuleContainer
unsigned int goodPulseSampleStop
unsigned int nBaselineSamples
unsigned int endSignalSample
float pileupBaselineStdDevThresh
unsigned int nSamples
unsigned int nNegativesAllowed
unsigned int ADCOverflow
unsigned int goodPulseSampleStart
float pileupBaselineSumThresh
MsgStream & msg
Definition testRead.cxx:32