ATLAS Offline Software
Loading...
Searching...
No Matches
BookkeeperTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
4
5// Implementation file for class BookkeeperTool
6// Authors: Tadej Novak <tadej@cern.ch>
7// Jack Cranshaw <Jack.Cranshaw@cern.ch>
8
10
11#ifndef GENERATIONBASE
14#endif
15
16#ifndef XAOD_STANDALONE
19#endif
20
23
24
25BookkeeperTool::BookkeeperTool(const std::string& name)
26 : asg::AsgMetadataTool(name)
27{
28#ifndef XAOD_STANDALONE
29 declareInterface< ::IMetaDataTool >( this );
30#endif // XAOD_STANDALONE
31}
32
33
35{
36 ATH_MSG_DEBUG("Initializing " << name());
37
38 ATH_MSG_DEBUG("InputCollName = " << m_inputCollName);
39 ATH_MSG_DEBUG("OutputCollName = " << m_outputCollName);
40
41#ifndef XAOD_STANDALONE
42 ATH_CHECK(m_cutFlowSvc.retrieve());
43 // Access "private" CutFlowSvc methods
44 m_cutFlowSvcPrivate = dynamic_cast<CutFlowSvc *>(&*(m_cutFlowSvc));
45#endif
46
47 return StatusCode::SUCCESS;
48}
49
50
51#ifdef XAOD_STANDALONE
53#else
55#endif
56{
57 // OPENING NEW INPUT FILE
58 // Things to do:
59 // 1) Load CutBookkeepers from input file
60 // a) if incomplete from input, directly propagate to output
61 // b) if complete from input, wait for EndInputFile to decide what to do in output
62
63 // Get number of event weight variations if needed
65 ATH_MSG_DEBUG("Determining number of weight variations");
66#ifndef GENERATIONBASE
68 StatusCode status = loadXAODMetaData();
69 if (!status.isSuccess()) {
70 if (status.isRecoverable()) {
72 } else {
73 return StatusCode::FAILURE;
74 }
75 }
76 } else {
78 }
79#else
81#endif
82
84 ATH_MSG_ERROR("Could not determine the number of weight variations");
85 return StatusCode::FAILURE;
86 }
87
88 ATH_MSG_INFO("Using number of event weight variations " << m_numberOfWeightVariations);
89
90#ifndef XAOD_STANDALONE
91 ATH_CHECK(m_cutFlowSvcPrivate->setNumberOfWeightVariations(m_numberOfWeightVariations));
92#endif
93 }
94
95#ifdef XAOD_STANDALONE
96 SG::SourceID source{"file"};
97#endif
98
99 // Prepare local cache
100 ATH_MSG_INFO("Preparing local cache for source '" << source << "' with " << m_numberOfWeightVariations << " variations");
103
104 // Check if a local container is there. IT SHOULD NOT BE
105 auto sit = m_inputContainers.find(source);
106 if (sit != m_inputContainers.end()) {
107 ATH_MSG_ERROR("Undefined behaviour: this file has already been processed");
108 return StatusCode::FAILURE;
109 }
110
111 const xAOD::CutBookkeeperContainer *inputCollection{};
112 // Get the incomplete bookkeeper collections of the input metadata store
113 std::string incompleteCollName = "Incomplete" + m_inputCollName;
114 if (inputMetaStore()->contains<xAOD::CutBookkeeperContainer>(incompleteCollName)) {
115 for (size_t i{}; i < m_numberOfWeightVariations; ++i) {
116 std::string name = incompleteCollName;
117 if (i != 0) {
118 name.append("_weight_");
119 name.append(std::to_string(i));
120 }
122 && inputMetaStore()->retrieve(inputCollection, name).isSuccess()) {
124 }
125 }
126 ATH_MSG_DEBUG("Successfully merged input incomplete bookkeepers with output");
127 } else {
128 ATH_MSG_INFO("No incomplete bookkeepers with name '" << incompleteCollName << "' in this file");
129 }
130
131 // Get the complete bookkeeper collections of the input metadata store
133 // Create the temporary container
134 auto [it, status] = m_inputContainers.emplace(source, CutBookkeepersLocalCache());
136
137 for (size_t i{}; i < m_numberOfWeightVariations; ++i) {
138 std::string name = m_inputCollName;
139 if (i != 0) {
140 name.append("_weight_");
141 name.append(std::to_string(i));
142 }
144 && inputMetaStore()->retrieve(inputCollection, name).isSuccess()) {
145 xAOD::CutFlowHelpers::updateContainer(it->second.at(i), inputCollection);
146 }
147 }
148 ATH_MSG_DEBUG("Successfully copied complete bookkeepers to temp container");
149 } else {
150 ATH_MSG_INFO("No complete bookkeepers with name '" << m_inputCollName.value() << "' in this file");
151 }
152
153 return StatusCode::SUCCESS;
154}
155
156#ifdef XAOD_STANDALONE
158#else
160#endif
161{
162#ifdef XAOD_STANDALONE
163 SG::SourceID source{"file"};
164#endif
165 ATH_MSG_INFO("Copying input containers for source '" << source << "'");
167
168 return StatusCode::SUCCESS;
169}
170
172{
173 // TERMINATING THE JOB (EndRun)
174 // Things to do:
175 // 1) Create new incomplete CutBookkeepers if relevant
176 // 2) Copy cutflow from the service
177 // 3) Copy containers to output
178
179 // All files that have not been fully processed are incomplete
181
182 // Copy cutflow from the service
184
185 // Write out the containers
186 for (std::size_t i = 0; i < m_completeContainers.size(); ++i) {
187 std::string name = m_outputCollName;
188 if (i != 0) {
189 name.append("_weight_");
190 name.append(std::to_string(i));
191 }
192 std::string incompleteName = "Incomplete" + name;
193
194 // In MP we might already have them written out
197 if (!outputMetaStore()->retrieve(complete, name).isSuccess()) {
198 ATH_MSG_ERROR("Could not get " << name << " CutBookkeepers from output MetaDataStore");
199 return StatusCode::FAILURE;
200 }
202 } else {
203 ATH_CHECK(outputMetaStore()->record(std::move(m_completeContainers.cont[i]), name));
204 ATH_CHECK(outputMetaStore()->record(std::move(m_completeContainers.aux[i]), name + "Aux."));
205 }
206
208 xAOD::CutBookkeeperContainer *incomplete{};
209 if (!outputMetaStore()->retrieve(incomplete, incompleteName).isSuccess()) {
210 ATH_MSG_ERROR("Could not get " << incompleteName << " CutBookkeepers from output MetaDataStore");
211 return StatusCode::FAILURE;
212 }
214 } else {
215 // Only write non-empty incomplete containers for variations
216 if (i == 0 || !m_incompleteContainers.at(i)->empty()) {
217 ATH_CHECK(outputMetaStore()->record(std::move(m_incompleteContainers.cont[i]), incompleteName));
218 ATH_CHECK(outputMetaStore()->record(std::move(m_incompleteContainers.aux[i]), incompleteName + "Aux."));
219 }
220 }
221 }
222
224 m_completeContainers.clear();
225
226 ATH_MSG_INFO("Successfully copied CutBookkeepers to the output MetaDataStore");
227
228 return StatusCode::SUCCESS;
229}
230
231
233 const SG::SourceID &source)
234{
236
237 if (msgLvl(MSG::DEBUG)) {
238 ATH_MSG_DEBUG("Available sources:");
239 for (const auto &[sourceID, list] : m_inputContainers) {
240 ATH_MSG_DEBUG(" " << sourceID);
241 }
242 }
243
244 if (!source.empty()) {
245 auto it = m_inputContainers.find(source);
246 if (it == m_inputContainers.end()) {
247 ATH_MSG_DEBUG("No input containers for this file");
248 return StatusCode::SUCCESS;
249 }
250
251 for (std::size_t i = 0; i < it->second.size(); ++i) {
252 xAOD::CutFlowHelpers::updateContainer(target.at(i), it->second.at(i));
253 }
254 m_inputContainers.erase(it);
255
256 return StatusCode::SUCCESS;
257 }
258
259 for (auto &[s, list] : m_inputContainers) {
260 for (std::size_t i = 0; i < list.size(); ++i) {
261 xAOD::CutFlowHelpers::updateContainer(target.at(i), list.at(i));
262 }
263 }
264 m_inputContainers.clear();
265
266 return StatusCode::SUCCESS;
267}
268
270{
271#ifndef XAOD_STANDALONE
272 ATH_MSG_DEBUG("Copying cutflow from CutFlowSvc");
273
274 // Get the bookkeeper from the current processing
275 const CutBookkeepersLocalCache &cache = m_cutFlowSvcPrivate->getCutBookkeepers();
276 if (!cache.empty()) {
277 ATH_MSG_DEBUG("Cache size: " << cache.size());
278
279 // sync the size
282
283 for (std::size_t i = 0; i < cache.size(); ++i) {
285 }
286 } else {
287 ATH_MSG_ERROR("No cutflow container in the CutFlowSvc");
288 return StatusCode::FAILURE;
289 }
290#endif
291
292 return StatusCode::SUCCESS;
293}
294
295
297{
298#ifdef GENERATIONBASE
299 return StatusCode::RECOVERABLE;
300#else
301
302 // Try to load MC channel number from file metadata
303 ATH_MSG_DEBUG("Attempting to retrieve MC channel number...");
304 const xAOD::FileMetaData *fileMetaData{};
305 uint32_t mcChannelNumber{uint32_t(-1)};
306 if (inputMetaStore()->contains<xAOD::FileMetaData>("FileMetaData")) {
307 ATH_CHECK(inputMetaStore()->retrieve(fileMetaData, "FileMetaData"));
308 float fltChannelNumber{-1};
309 if (fileMetaData->value(xAOD::FileMetaData::mcProcID, fltChannelNumber)) {
310 mcChannelNumber = static_cast<uint32_t>(fltChannelNumber);
311 }
312 }
313 if (mcChannelNumber == uint32_t(-1)) {
314 ATH_MSG_WARNING("... MC channel number could not be loaded from FileMetaData");
315#ifdef XAOD_STANDALONE
316 mcChannelNumber = 0;
317#else
318 return StatusCode::RECOVERABLE;
319#endif
320 }
321
322 // Find the correct truth meta data object
323 ATH_MSG_DEBUG("Attempting to load weight meta data from xAOD TruthMetaData for channel " << mcChannelNumber);
324 const xAOD::TruthMetaDataContainer *metaDataContainer{};
325 ATH_CHECK(inputMetaStore()->retrieve(metaDataContainer, "TruthMetaData"));
326
327 // If we only have one metadata item take MC channel from there if needed
328 if (mcChannelNumber == 0 && metaDataContainer->size() == 1) {
329 mcChannelNumber = metaDataContainer->at(0)->mcChannelNumber();
330 ATH_MSG_WARNING("... MC channel number taken from the metadata as " << mcChannelNumber);
331 }
332
333 auto itTruthMetaDataPtr = std::find_if(metaDataContainer->begin(), metaDataContainer->end(),
334 [mcChannelNumber] (const auto& it) { return it->mcChannelNumber() == mcChannelNumber; }
335 );
336
337 // If no such object is found then return
338 if (itTruthMetaDataPtr == metaDataContainer->end()) {
339#ifdef XAOD_STANDALONE
341 ATH_MSG_DEBUG("Could not load weight meta data! Assuming 1 variation.");
342 return StatusCode::SUCCESS;
343#else
344 ATH_MSG_DEBUG("Could not load weight meta data from TruthMetaData!");
345 return StatusCode::RECOVERABLE;
346#endif
347 }
348
349 // Update cached weight data
350 const std::vector<std::string> &truthWeightNames = (*itTruthMetaDataPtr)->weightNames();
351
352 m_numberOfWeightVariations = truthWeightNames.size();
354 ATH_MSG_DEBUG("No variations present, setting to 1.");
356 }
357
358 return StatusCode::SUCCESS;
359#endif
360}
361
362
364{
365 // AnalysisBase can only use the xAOD::TruthMetaDataContainer, so skip this
366#ifdef XAOD_STANDALONE
367 return StatusCode::SUCCESS;
368#else
369
371 = inputMetaStore()->tryConstRetrieve<IOVMetaDataContainer>("/Generation/Parameters");
372 if (container == nullptr) {
373 // set variations to 1 and exit quietly...
375 return StatusCode::SUCCESS;
376 }
377 // payload is a collection of CondAttrListCollections
378 // only look a the first one, assuming it exists, and within that only look at the first channel;
379 if (!(container->payloadContainer()->size() > 0
380 && container->payloadContainer()->at(0)->size() > 0)) {
381 return StatusCode::FAILURE;
382 }
383
384 // we take the first collection of weights
385 // TODO: improve this
386 CondAttrListCollection::ChanNum chanNum{container->payloadContainer()->at(0)->chanNum(0)};
387 const coral::Attribute& attr
388 = container->payloadContainer()->at(0)->attributeList(chanNum)["HepMCWeightNames"];
389
390 ATH_MSG_DEBUG("Attempting to load weight meta data from /Generation/Parameters");
391 std::map<std::string, int> truthWeightMap;
392 ATH_CHECK(Gaudi::Parsers::parse(truthWeightMap, attr.data<std::string>()));
393
394 m_numberOfWeightVariations = truthWeightMap.size();
395
396 return StatusCode::SUCCESS;
397#endif // XAOD_STANDALONE
398}
#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)
This class is an implementation of the AsgMetadataTool for the xAOD::CutBookkeeperContainer.
This file defines the class for a collection of AttributeLists where each one is associated with a ch...
This class is a container for conditions data.
bool msgLvl(const MSG::Level lvl) const
CutBookkeepersLocalCache m_incompleteContainers
virtual StatusCode metaDataStop() override
Function called when the tool should write out its metadata.
StatusCode copyCutflowFromService()
Fill Cutflow information from the service.
BookkeeperTool(const std::string &name="BookkeeperTool")
Declare the correct constructor for Athena.
Gaudi::Property< std::string > m_inputCollName
The name of the input CutBookkeeperContainer.
CutFlowSvc * m_cutFlowSvcPrivate
Direct pointer to the CutFlowSvc for "private" methods access.
virtual StatusCode endInputFile() override
Function called when the currently open input file got completely processed.
StatusCode loadPOOLMetaData()
virtual StatusCode initialize() override
Standard reimplemented functions.
virtual StatusCode beginInputFile() override
Function called when a new input file is opened.
std::unordered_map< SG::SourceID, CutBookkeepersLocalCache > m_inputContainers
Input CutBookkeeperContainers.
ServiceHandle< ICutFlowSvc > m_cutFlowSvc
Pointer to the public CutFlowSvc interface.
size_t m_numberOfWeightVariations
Number of event weight variations.
CutBookkeepersLocalCache m_completeContainers
Local CutBookkeeperContainers.
StatusCode copyInputContainersToOutput(CutBookkeepersLocalCache &target, const SG::SourceID &source="")
Copy input containers to the output.
StatusCode loadXAODMetaData()
Initialisation helpers.
Gaudi::Property< std::string > m_outputCollName
The name of the output CutBookkeeperContainer.
This implements the methods for ICutFlowSvc.
Definition CutFlowSvc.h:47
const T * at(size_type n) const
Access an element, as an rvalue.
const_iterator end() const noexcept
Return a const_iterator pointing past the end of the collection.
const_iterator begin() const noexcept
Return a const_iterator pointing at the beginning of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
This class is a container for conditions data.
MetaStorePtr_t outputMetaStore() const
Accessor for the output metadata store.
AsgMetadataTool(const std::string &name)
Normal ASG tool constructor with a name.
MetaStorePtr_t inputMetaStore() const
Accessor for the input metadata store.
@ 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
StatusCode parse(std::tuple< Tup... > &tup, const Gaudi::Parsers::InputData &input)
void updateContainer(xAOD::CutBookkeeperContainer *contToUpdate, const xAOD::CutBookkeeperContainer *otherCont)
Helper function to update a container with information from another one.
TruthMetaDataContainer_v1 TruthMetaDataContainer
Declare the latest version of the truth vertex container.
FileMetaData_v1 FileMetaData
Declare the latest version of the class.
CutBookkeeperContainer_v1 CutBookkeeperContainer
Define the latest version of the CutBookkeeperContainer class.
Helper in-memory structure.
xAOD::CutBookkeeperContainer * at(std::size_t n) const
static void prepareContainers(CutBookkeepersLocalCache &target, size_t size, bool extend=false)