ATLAS Offline Software
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 
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
64  if (m_numberOfWeightVariations == 0) {
65  ATH_MSG_DEBUG("Determining number of weight variations");
66 #ifndef GENERATIONBASE
67  if (inputMetaStore()->contains<xAOD::TruthMetaDataContainer>("TruthMetaData")) {
68  StatusCode status = loadXAODMetaData();
69  if (!status.isSuccess()) {
70  if (status.isRecoverable()) {
71  ATH_CHECK(loadPOOLMetaData());
72  } else {
73  return StatusCode::FAILURE;
74  }
75  }
76  } else {
77  ATH_CHECK(loadPOOLMetaData());
78  }
79 #else
80  ATH_CHECK(loadPOOLMetaData());
81 #endif
82 
83  if (m_numberOfWeightVariations == 0) {
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");
101  CutBookkeepersLocalCache::prepareContainers(m_completeContainers, m_numberOfWeightVariations);
102  CutBookkeepersLocalCache::prepareContainers(m_incompleteContainers, m_numberOfWeightVariations);
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 
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  }
121  if (inputMetaStore()->contains<xAOD::CutBookkeeperContainer>(name)
122  && inputMetaStore()->retrieve(inputCollection, name).isSuccess()) {
123  xAOD::CutFlowHelpers::updateContainer(m_incompleteContainers.at(i), inputCollection);
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
132  if (inputMetaStore()->contains<xAOD::CutBookkeeperContainer>(m_inputCollName)) {
133  // Create the temporary container
134  auto [it, status] = m_inputContainers.emplace(source, CutBookkeepersLocalCache());
135  CutBookkeepersLocalCache::prepareContainers(it->second, m_numberOfWeightVariations);
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  }
143  if (inputMetaStore()->contains<xAOD::CutBookkeeperContainer>(name)
144  && inputMetaStore()->retrieve(inputCollection, name).isSuccess()) {
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 << "'");
166  ATH_CHECK(copyInputContainersToOutput(m_completeContainers, 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
195  if (outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(name)) {
196  xAOD::CutBookkeeperContainer *complete{};
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 
207  if (outputMetaStore()->contains<xAOD::CutBookkeeperContainer>(incompleteName)) {
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 
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) {
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) {
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
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{};
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();
353  if (m_numberOfWeightVariations == 0) {
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 
370  const IOVMetaDataContainer *container
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
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 }
python.PyKernel.retrieve
def retrieve(aClass, aKey=None)
Definition: PyKernel.py:110
CutFlowSvc.h
IOVMetaDataContainer::payloadContainer
const IOVPayloadContainer * payloadContainer() const
Access to payload container.
Definition: IOVMetaDataContainer.h:141
IOVPayloadContainer::at
CondAttrListCollection * at(unsigned int i) const
Element access.
Definition: IOVPayloadContainer.h:128
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
IOVMetaDataContainer
This class is a container for conditions data. It is intended to be used to store conditions data fro...
Definition: IOVMetaDataContainer.h:37
max
#define max(a, b)
Definition: cfImp.cxx:41
BookkeeperTool.h
This class is an implementation of the AsgMetadataTool for the xAOD::CutBookkeeperContainer.
Gaudi::Parsers::parse
StatusCode parse(std::tuple< Tup... > &tup, const Gaudi::Parsers::InputData &input)
Definition: CaloGPUClusterAndCellDataMonitorOptions.h:284
CondAttrListCollection.h
This file defines the class for a collection of AttributeLists where each one is associated with a ch...
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
CutFlowSvc::getCutBookkeepers
const CutBookkeepersLocalCache & getCutBookkeepers() const
Get CutBookkeepers cache.
Definition: CutFlowSvc.cxx:385
xAOD::uint32_t
setEventNumber uint32_t
Definition: EventInfo_v1.cxx:127
BookkeeperTool::m_incompleteContainers
CutBookkeepersLocalCache m_incompleteContainers
Definition: BookkeeperTool.h:105
CutBookkeepersLocalCache::size
std::size_t size() const
Definition: CutBookkeepersLocalCache.h:20
skel.it
it
Definition: skel.GENtoEVGEN.py:423
asg
Definition: DataHandleTestTool.h:28
asg::AsgMetadataTool::inputMetaStore
MetaStorePtr_t inputMetaStore() const
Accessor for the input metadata store.
Definition: AsgMetadataTool.cxx:88
AthCommonMsg< AlgTool >::msgLvl
bool msgLvl(const MSG::Level lvl) const
Definition: AthCommonMsg.h:30
CutBookkeepersLocalCache::cont
std::vector< std::unique_ptr< xAOD::CutBookkeeperContainer > > cont
Definition: CutBookkeepersLocalCache.h:16
BookkeeperTool::beginInputFile
virtual StatusCode beginInputFile() override
Function called when a new input file is opened.
Definition: BookkeeperTool.h:64
BookkeeperTool::loadXAODMetaData
StatusCode loadXAODMetaData()
Initialisation helpers.
Definition: BookkeeperTool.cxx:296
xAOD::mcChannelNumber
mcChannelNumber
Definition: EventInfo_v1.cxx:197
BookkeeperTool::copyCutflowFromService
StatusCode copyCutflowFromService()
Fill Cutflow information from the service.
Definition: BookkeeperTool.cxx:269
CutBookkeepersLocalCache::clear
void clear()
Definition: CutBookkeepersLocalCache.h:22
BookkeeperTool::copyInputContainersToOutput
StatusCode copyInputContainersToOutput(CutBookkeepersLocalCache &target, const SG::SourceID &source="")
Copy input containers to the output.
Definition: BookkeeperTool.cxx:232
IOVPayloadContainer::size
size_type size() const
size of payload vector
Definition: IOVPayloadContainer.h:121
BookkeeperTool::loadPOOLMetaData
StatusCode loadPOOLMetaData()
Definition: BookkeeperTool.cxx:363
CutBookkeepersLocalCache::prepareContainers
static void prepareContainers(CutBookkeepersLocalCache &target, size_t size, bool extend=false)
Definition: CutBookkeepersLocalCache.h:25
PhysDESDM_SmpCaloId.inputCollection
inputCollection
Definition: PhysDESDM_SmpCaloId.py:95
BookkeeperTool::m_cutFlowSvc
ServiceHandle< ICutFlowSvc > m_cutFlowSvc
Pointer to the public CutFlowSvc interface.
Definition: BookkeeperTool.h:84
CutBookkeepersLocalCache
Helper in-memory structure.
Definition: CutBookkeepersLocalCache.h:15
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
checkCoolLatestUpdate.chanNum
chanNum
Definition: checkCoolLatestUpdate.py:27
lumiFormat.i
int i
Definition: lumiFormat.py:92
CutFlowSvc
This implements the methods for ICutFlowSvc.
Definition: CutFlowSvc.h:47
CutBookkeepersLocalCache::aux
std::vector< std::unique_ptr< xAOD::CutBookkeeperAuxContainer > > aux
Definition: CutBookkeepersLocalCache.h:17
BookkeeperTool::BookkeeperTool
BookkeeperTool(const std::string &name="BookkeeperTool")
Declare the correct constructor for Athena.
Definition: BookkeeperTool.cxx:25
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
ATH_MSG_DEBUG
#define ATH_MSG_DEBUG(x)
Definition: AthMsgStreamMacros.h:29
BookkeeperTool::m_cutFlowSvcPrivate
CutFlowSvc * m_cutFlowSvcPrivate
Direct pointer to the CutFlowSvc for "private" methods access.
Definition: BookkeeperTool.h:86
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
BookkeeperTool::metaDataStop
virtual StatusCode metaDataStop() override
Function called when the tool should prepare to write its metadata.
Definition: BookkeeperTool.cxx:171
CondAttrListCollection::chanNum
ChanNum chanNum(unsigned int index) const
channel number for index: (index = 0 to size-1)
Definition: CondAttrListCollection.h:384
xAOD::CutBookkeeperContainer_v1
Container that holds the Container of all CutBookkeepers.
Definition: CutBookkeeperContainer_v1.h:27
histSizes.list
def list(name, path='/')
Definition: histSizes.py:38
xAOD::FileMetaData_v1::mcProcID
@ mcProcID
Same as mc_channel_number [float].
Definition: FileMetaData_v1.h:74
xAOD::CutFlowHelpers::updateContainer
void updateContainer(xAOD::CutBookkeeperContainer *contToUpdate, const xAOD::CutBookkeeperContainer *otherCont)
Helper function to update a container with information from another one.
Definition: xAODCutFlowHelpers.cxx:105
CondAttrListCollection::attributeList
const AttributeList & attributeList(ChanNum chanNum) const
attribute list for a given channel number
Definition: CondAttrListCollection.h:401
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
BookkeeperTool::m_inputContainers
std::unordered_map< SG::SourceID, CutBookkeepersLocalCache > m_inputContainers
Input CutBookkeeperContainers.
Definition: BookkeeperTool.h:101
CondAttrListCollection::ChanNum
unsigned int ChanNum
Definition: CondAttrListCollection.h:55
xAOD::FileMetaData_v1
Class holding file-level metadata about an xAOD file.
Definition: FileMetaData_v1.h:34
CutBookkeepersLocalCache::at
xAOD::CutBookkeeperContainer * at(std::size_t n) const
Definition: CutBookkeepersLocalCache.h:21
IOVMetaDataContainer.h
This class is a container for conditions data. It is intended to be used to store conditions data fro...
Muon::nsw::incomplete
@ incomplete
Definition: NSWTriggerElink.h:37
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:195
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
BookkeeperTool::endInputFile
virtual StatusCode endInputFile() override
Function called when the currently open input file got completely processed.
Definition: BookkeeperTool.h:65
CutBookkeepersLocalCache::empty
bool empty() const
Definition: CutBookkeepersLocalCache.h:19
CondAttrListCollection::size
size_type size() const
number of Chan/AttributeList pairs
Definition: CondAttrListCollection.h:322
BookkeeperTool::m_inputCollName
Gaudi::Property< std::string > m_inputCollName
The name of the input CutBookkeeperContainer.
Definition: BookkeeperTool.h:90
xAODCutFlowHelpers.h
FileMetaData.h
BookkeeperTool::initialize
virtual StatusCode initialize() override
Standard reimplemented functions.
Definition: BookkeeperTool.cxx:34
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
asg::AsgMetadataTool::outputMetaStore
MetaStorePtr_t outputMetaStore() const
Accessor for the output metadata store.
Definition: AsgMetadataTool.cxx:97
SG::SourceID
std::string SourceID
Definition: AthenaKernel/AthenaKernel/SourceID.h:23
DEBUG
#define DEBUG
Definition: page_access.h:11
BookkeeperTool::m_outputCollName
Gaudi::Property< std::string > m_outputCollName
The name of the output CutBookkeeperContainer.
Definition: BookkeeperTool.h:94
merge.status
status
Definition: merge.py:17
COOLRates.target
target
Definition: COOLRates.py:1106
BookkeeperTool::m_completeContainers
CutBookkeepersLocalCache m_completeContainers
Local CutBookkeeperContainers.
Definition: BookkeeperTool.h:104
TruthMetaDataContainer.h
DataVector::empty
bool empty() const noexcept
Returns true if the collection is empty.
BookkeeperTool::m_numberOfWeightVariations
size_t m_numberOfWeightVariations
Number of event weight variations.
Definition: BookkeeperTool.h:98