ATLAS Offline Software
Loading...
Searching...
No Matches
PMGTruthWeightTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
5// EDM include(s):
6#ifndef XAOD_STANDALONE
8#endif
9
10// Local include(s):
12#include <regex>
16
18
19
20namespace PMGTools
21{
23 : asg::AsgMetadataTool(name)
24 {
25 declareProperty("MetaObjectName", m_metaName = "TruthMetaData");
26 }
27
28
30 {
31 ATH_MSG_DEBUG("Initialising...");
32
33 ATH_MSG_INFO("Attempting to retrieve truth meta data from the first file...");
34
35 // Clear cached weights
37
39 m_calibCache.initialize (std::move (affSysts),
40 [this] (const CP::SystematicSet& sys,
41 std::size_t& idx) {
42 if (!sys.name().empty()) ATH_MSG_WARNING("Mapping for " << sys.name() << " missing, setting to index 0.");
43 idx = 0;
44 return StatusCode::SUCCESS;
45 });
46
47 // Try to load MC channel number from file metadata
49
50 if (m_mcChannelNumber == uint32_t(-1)) {
51 ATH_MSG_WARNING("... MC channel number could not be loaded");
52 } else {
53 ATH_MSG_INFO("... MC channel number identified as " << m_mcChannelNumber);
54 }
55
56 // Start by trying to load metadata from the store
57 m_metaDataContainer = nullptr;
60 ATH_MSG_INFO("Loaded xAOD::TruthMetaDataContainer");
61
62 // Check for incorrectly stored McChannelNumber
64 for (auto truthMetaData : *m_metaDataContainer) {
65 if (truthMetaData->mcChannelNumber() != 0) { m_useChannelZeroInMetaData = false; }
66 }
67 // If we only have one metadata item take MC channel from there if needed
68 if (m_mcChannelNumber == uint32_t(-1) && m_metaDataContainer->size() == 1) {
69 m_mcChannelNumber = m_metaDataContainer->at(0)->mcChannelNumber();
70 ATH_MSG_WARNING("... MC channel number taken from the metadata as " << m_mcChannelNumber);
71 }
72 if (m_useChannelZeroInMetaData) { ATH_MSG_WARNING("MC channel number in TruthMetaData is invalid - assuming that channel 0 has the correct information."); }
73
74 // Load metadata from TruthMetaDataContainer if we have a valid channel number or if we're going to use 0 anyway
75 // ... otherwise wait until we can load a channel number from EventInfo
76 if (m_mcChannelNumber != uint32_t(-1) || m_useChannelZeroInMetaData) {
77 if (loadMetaData().isFailure()) {
78 ATH_MSG_ERROR("Could not load metadata for MC channel number " << m_mcChannelNumber);
79 return StatusCode::FAILURE;
80 }
81 }
82 } else {
83 // ... now try to load the weight container using the POOL metadata (not possible in AnalysisBase)
84 // see https://twiki.cern.ch/twiki/bin/viewauth/AtlasProtected/AthAnalysisBase#How_to_read_the_truth_weight_nam
85 if (loadPOOLMetaData().isFailure()) {
86 ATH_MSG_ERROR("Could not load POOL HepMCWeightNames");
87 return StatusCode::FAILURE;
88 }
89 }
90
91 // Add the affecting systematics to the global registry
93 if (!registry.registerSystematics(*this)) {
94 ATH_MSG_ERROR("unable to register the systematics");
95 return StatusCode::FAILURE;
96 }
97
98 ATH_MSG_DEBUG("Successfully initialized!");
99
100 return StatusCode::SUCCESS;
101 }
102
103
104 const std::vector<std::string>& PMGTruthWeightTool::getWeightNames() const {
105 return m_weightNames;
106 }
107
108
109 float PMGTruthWeightTool::getWeight(const xAOD::EventInfo* evtInfo, const std::string& weightName) const {
110 // Return appropriate weight from EventInfo: this should be identical to the TruthEvent
111 try {
112 return evtInfo->mcEventWeight(m_weightIndices.at(weightName));
113 } catch (const std::out_of_range& e) {
114 // Before throwing an exception, try to recover with bad naming conventions
115 std::string strippedName = std::regex_replace(weightName, std::regex(" "), "_");
116 std::transform(strippedName.begin(), strippedName.end(), strippedName.begin(),
117 [](unsigned char c){ return std::tolower(c); });
118 for (const std::string &weight : m_weightNames) {
119 std::string modifiedName = std::regex_replace(weight, std::regex(" "), "_");
120 std::transform(modifiedName.begin(), modifiedName.end(), modifiedName.begin(),
121 [](unsigned char c){ return std::tolower(c); });
122 if (strippedName == modifiedName){
123 ATH_MSG_WARNING("Using weight name \"" << weight << "\" instead of requested \"" << weightName << "\"");
124 return getWeight(evtInfo, weight);
125 }
126 }
127 ATH_MSG_FATAL("Weight \"" + weightName + "\" could not be found");
128 throw std::runtime_error(name() + ": Weight \"" + weightName + "\" could not be found");
129 }
130 }
131
132
133 bool PMGTruthWeightTool::hasWeight(const std::string& weightName) const {
134 return (m_weightIndices.count(weightName) > 0);
135 }
136
137
139 {
140 const std::size_t *res;
142 return evtInfo->mcEventWeight(*res);
143 }
144
145
147 {
148 const std::size_t *res;
150 return *res;
151 }
152
153
155 {
156 return m_calibCache.affectingSystematics();
157 }
158
159
164
165
166 StatusCode PMGTruthWeightTool::getMCChannelNumber(uint32_t &mcChannelNumber) {
167 mcChannelNumber = static_cast<uint32_t>(-1);
168
169 // Try to load MC channel number from file metadata
170 ATH_MSG_INFO("Attempting to retrieve MC channel number...");
171 const xAOD::FileMetaData *fmd = nullptr;
172 if (inputMetaStore()->contains<xAOD::FileMetaData>("FileMetaData")) {
173 ATH_CHECK(inputMetaStore()->retrieve(fmd, "FileMetaData"));
174 float fltChannelNumber(-1);
175 if (fmd->value(xAOD::FileMetaData::mcProcID, fltChannelNumber)) {
176 mcChannelNumber = static_cast<uint32_t>(fltChannelNumber);
177 return StatusCode::SUCCESS;
178 }
179 }
180 return StatusCode::FAILURE;
181 }
182
184 {
185 // Detect possible MC channel number change
186 uint32_t mcChannelNumber;
187 ATH_CHECK(getMCChannelNumber(mcChannelNumber));
188
189 if (m_mcChannelNumber != uint32_t(-1) && mcChannelNumber != uint32_t(-1) && mcChannelNumber != m_mcChannelNumber) {
190 ATH_MSG_ERROR("MC channel number from a new file does not match the previously processed files.");
191 return StatusCode::FAILURE;
192 }
193
194 return StatusCode::SUCCESS;
195 }
196
197
199 // Find the correct truth meta data object
200 uint32_t targetChannelNumber = (m_useChannelZeroInMetaData ? 0 : m_mcChannelNumber);
201 ATH_MSG_INFO("Attempting to load weight meta data from xAOD TruthMetaData for channel " << targetChannelNumber);
202 auto itTruthMetaDataPtr = std::find_if(m_metaDataContainer->begin(), m_metaDataContainer->end(),
203 [targetChannelNumber] (const auto& it) { return it->mcChannelNumber() == targetChannelNumber; }
204 );
205
206 // If no such object is found then return
207 if (itTruthMetaDataPtr == m_metaDataContainer->end()) {
208 ATH_MSG_ERROR("Could not load weight meta data!");
209 return StatusCode::FAILURE;
210 }
211
212 // Update cached weight data
213 const std::vector<std::string> &truthWeightNames = (*itTruthMetaDataPtr)->weightNames();
214 for(std::size_t idx = 0; idx < truthWeightNames.size(); ++idx ) {
215 m_weightNames.push_back(truthWeightNames.at(idx));
216 m_weightIndices[truthWeightNames.at(idx)] = idx;
217
218 std::string sysName = weightNameWithPrefix(truthWeightNames.at(idx));
219 if (!sysName.empty()) {
221 }
222
223 ANA_MSG_VERBOSE(" " << truthWeightNames.at(idx) << " " << sysName);
224 }
225 return this->validateWeightLocationCaches();
226 }
227
228
230 // AnalysisBase can only use the xAOD::TruthMetaDataContainer, so skip this
231#ifdef XAOD_STANDALONE
232 return StatusCode::SUCCESS;
233#else
234 ATH_MSG_INFO("Looking for POOL HepMC IOVMetaData...");
235 std::map<std::string, int> hepMCWeightNamesMap;
236 if (AAH::retrieveMetadata("/Generation/Parameters", "HepMCWeightNames", hepMCWeightNamesMap, inputMetaStore()).isFailure()) {
237 ATH_MSG_FATAL("Cannot access metadata " << m_metaName << " and failed to get names from IOVMetadata");
238 return StatusCode::FAILURE;
239 }
240
241 // Use input map to fill the index map and the weight names
242 ATH_MSG_INFO("Attempting to load weight meta data from HepMC IOVMetaData container");
243 for (auto& kv : hepMCWeightNamesMap) {
244 m_weightNames.push_back(kv.first);
245 m_weightIndices[kv.first] = kv.second;
246
247 std::string sysName = weightNameWithPrefix(kv.first);
248 if (!sysName.empty()) {
249 ANA_CHECK (m_calibCache.add(CP::SystematicVariation(sysName), kv.second));
250 }
251
252 ANA_MSG_VERBOSE(" " << kv.first << " " << sysName);
253 }
254 return this->validateWeightLocationCaches();
255#endif // XAOD_STANDALONE
256 }
257
258
260 // Validate weight caches against one another
261 if (m_weightNames.size() != m_weightIndices.size()) {
262 ATH_MSG_ERROR("Found " << m_weightNames.size() << " but " << m_weightIndices.size() << " weight indices!");
263 return StatusCode::FAILURE;
264 }
265
266 ATH_MSG_INFO("Successfully loaded information about " << m_weightNames.size() << " weights");
267 return StatusCode::SUCCESS;
268 }
269
270
275
276} // namespace PMGTools
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
#define ANA_MSG_VERBOSE(xmsg)
Macro printing verbose messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
#define ANA_CHECK_THROW(EXP)
check whether the given expression was successful, throwing an exception on failure
std::pair< std::vector< unsigned int >, bool > res
Postprocess generator weight names to be name/ROOT friendly.
static std::string retrieveMetadata(const std::string &folder, const std::string &key, const ServiceHandle< StoreGateSvc > &inputMetaStore)
method that always returns as a string you can use from, e.g, pyROOT with evt = ROOT....
Gaudi::Details::PropertyBase & declareProperty(Gaudi::Property< T, V, H > &t)
This module implements the central registry for handling systematic uncertainties with CP tools.
static SystematicRegistry & getInstance()
Get the singleton instance of the registry for the curren thread.
StatusCode registerSystematics(const IReentrantSystematicsTool &tool)
effects: register all the systematics from the tool
Class to wrap a set of SystematicVariations.
virtual CP::SystematicSet affectingSystematics() const override
Implements interface from ISystematicsTool.
void clearWeightLocationCaches()
Clear caches.
virtual float getWeight(const xAOD::EventInfo *evtInfo, const std::string &weightName) const override
Implements interface from IPMGTruthWeightTool.
StatusCode validateWeightLocationCaches()
Validate weight caches.
virtual size_t getSysWeightIndex(const CP::SystematicSet &sys) const override
Implements interface from IPMGTruthWeightTool.
virtual StatusCode beginInputFile() override
Function called when a new input file is opened.
StatusCode loadPOOLMetaData()
Loads weight information from POOL using HepMCWeightNames.
std::unordered_map< std::string, size_t > m_weightIndices
Weight names to indices of available weights in this file.
bool m_useChannelZeroInMetaData
Flag to indicate whether the xAOD::TruthMetaData objects have incorrect McChannelNumber.
std::vector< std::string > m_weightNames
Available weight names for this file.
StatusCode getMCChannelNumber(uint32_t &mcChannelNumber)
Helper function for retrieving MC channel number from file metadata.
StatusCode loadMetaData()
Loads weight information from xAOD::TruthMetaDataContainer.
uint32_t m_mcChannelNumber
Current MC channel number.
std::string m_metaName
Stores the meta data record name.
PMGTruthWeightTool(const std::string &name)
Create a proper constructor for Athena.
CP::SystematicsCache< std::size_t > m_calibCache
Systematics to indices of available weights.
virtual float getSysWeight(const xAOD::EventInfo *evtInfo, const CP::SystematicSet &sys) const override
Implements interface from IPMGTruthWeightTool.
virtual bool hasWeight(const std::string &weightName) const override
Implements interface from IPMGTruthWeightTool.
virtual const std::vector< std::string > & getWeightNames() const override
Implements interface from IPMGTruthWeightTool.
virtual StatusCode initialize() override
Function initialising the tool.
const xAOD::TruthMetaDataContainer * m_metaDataContainer
Ptr to the meta data container for this file.
virtual CP::SystematicSet recommendedSystematics() const override
Implements interface from ISystematicsTool.
AsgMetadataTool(const std::string &name)
Normal ASG tool constructor with a name.
MetaStorePtr_t inputMetaStore() const
Accessor for the input metadata store.
float mcEventWeight(size_t i=0) const
The weight of one specific MC event used in the simulation.
@ mcProcID
Same as mc_channel_number [float].
bool value(MetaDataType type, std::string &val) const
Get a pre-defined string value out of the object.
bool contains(const std::string &s, const std::string &regx)
does a string contain the substring
Definition hcg.cxx:114
Tool providing sample cross-sections and k-factors etc.
std::string weightNameWithPrefix(const std::string &name)
cleanup the weight name and add prefix
EventInfo_v1 EventInfo
Definition of the latest event info version.
FileMetaData_v1 FileMetaData
Declare the latest version of the class.