ATLAS Offline Software
Control/xAODRootAccess/Root/TEvent.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 // Local include(s).
5 
6 #include "IOUtils.h"
7 
8 // System include(s):
9 #include <cassert>
10 #include <cstring>
11 #include <iomanip>
12 #include <sstream>
13 
14 // ROOT include(s):
15 #include <TBranch.h>
16 #include <TChain.h>
17 #include <TChainElement.h>
18 #include <TError.h>
19 #include <TFile.h>
20 #include <TFriendElement.h>
21 #include <TKey.h>
22 #include <TMethodCall.h>
23 #include <TSystem.h>
24 #include <TTree.h>
25 
26 // Gaudi/Athena include(s):
33 #ifndef XAOD_STANDALONE
35 #include "SGTools/DataProxy.h"
36 #endif // not XAOD_STANDALONE
37 #include "CxxUtils/ClassName.h"
39 
40 // Interface include(s):
42 
43 // xAOD include(s):
44 #include "xAODCore/AuxSelection.h"
45 #include "xAODCore/tools/IOStats.h"
48 
49 // Local include(s):
52 #include "xAODRootAccess/TStore.h"
67 
68 namespace xAOD {
69 
71 static const ::Int_t CACHE_SIZE = -1;
73 const char* const TEvent::EVENT_TREE_NAME = "CollectionTree";
75 static const char* const METADATA_TREE_NAME = "MetaData";
76 
77 TEvent::TEvent(EAuxMode mode) : Event("xAOD::TEvent"), m_auxMode(mode) {}
78 
80 
81  // Let the initialisation function deal with setting up the object.
82  readFrom(file).ignore();
83 }
84 
86 
87  // Let the initialisation function deal with setting up the object.
88  readFrom(tree).ignore();
89 }
90 
92 
93  // Check that the user didn't forget to call finishWritingTo().
94  if (m_outTree) {
96  "Did not call finishWritingTo() before destroying the TEvent object!");
97  }
98 
99  // Clear the input and output objects before the input/output files would be
100  // closed. Otherwise we can be left with "TTree related" objects pointing
101  // nowhere.
102  m_inputObjects.clear();
103  m_outputObjects.clear();
104 }
105 
109 
110  return m_auxMode;
111 }
112 
122 StatusCode TEvent::readFrom(::TFile* file, bool useTreeCache,
123  std::string_view treeName) {
124 
125  // If no file was specified, return gracefully.
126  if (file == nullptr) {
127  ATH_MSG_DEBUG("No input file specified for readFrom(...)");
128  return StatusCode::SUCCESS;
129  }
130 
131  // Clear the cached input objects.
132  m_inputObjects.clear();
133  m_inputMissingObjects.clear();
134  m_inputMetaObjects.clear();
135  {
137  lock.upgrade();
138  m_branches.clear();
139  }
140 
141  // Reset the internal flags.
142  m_inTreeMissing = kFALSE;
143  m_entry = -1;
144 
145  // Make sure we return to the current directory:
147 
148  // Set up the file access tracer.
149  static TFileAccessTracer tracer ATLAS_THREAD_SAFE;
150  tracer.add(*file);
151 
152  // Look for the metadata tree:
153  m_inMetaTree = file->Get<TTree>(METADATA_TREE_NAME);
154  if (m_inMetaTree == nullptr) {
155  ATH_MSG_ERROR("Couldn't find metadata tree on input. Object is unusable!");
156  return StatusCode::FAILURE;
157  }
158 
159  // Set metadata entry to be read
160  // NB: no reading is done calling LoadTree
161  if (m_inMetaTree->LoadTree(0) < 0) {
162  ATH_MSG_ERROR("Failed to load entry 0 for metadata tree");
163  return StatusCode::FAILURE;
164  }
165 
166  // A sanity check.
167  if (m_inMetaTree->GetEntries() != 1) {
168  ATH_MSG_WARNING("Was expecting a metadata tree with size 1, instead of "
169  << m_inMetaTree->GetEntries() << ".");
170  ATH_MSG_WARNING("The input file was most probably produced by hadd...");
171  }
172 
173  // Make sure that the xAOD::EventFormat dictonary is loaded.
174  // This may not be the case if streamer information reading is turned
175  // off.
176  static const std::string eventFormatTypeName =
178  ::TClass* cl = ::TClass::GetClass(eventFormatTypeName.c_str());
179  if (cl == nullptr) {
180  ATH_MSG_WARNING("Couldn't load the xAOD::EventFormat dictionary");
181  }
182 
183  // Helper lambda for collecting the event format metadata from an RNTuple
184  // with a given name.
185  auto readEventFormatMetadata = [&](std::string_view treeName) -> StatusCode {
186  // Look for the metadata tree:
187  TTree* metaTree = file->Get<TTree>(treeName.data());
188  if (metaTree == nullptr) {
189  ATH_MSG_ERROR("Couldn't find metadata tree \"" << treeName
190  << "\"on input.");
191  return StatusCode::FAILURE;
192  }
193  // Set metadata entry to be read.
194  if (metaTree->LoadTree(0) < 0) {
195  ATH_MSG_ERROR("Failed to load entry 0 for metadata tree \"" << treeName
196  << "\"");
197  return StatusCode::FAILURE;
198  }
199 
200  // Check if the EventFormat branch is available:
201  const std::string eventFormatBranchName =
203  if (!metaTree->GetBranch(eventFormatBranchName.c_str())) {
204  // This can happen when the file was produced by an Athena job that
205  // didn't have any input events itself. This means that the file
206  // doesn't actually have any useful metadata.
207  ATH_MSG_INFO("Input file provides no event or metadata");
208  return StatusCode::RECOVERABLE;
209  }
210 
211  // Read in the event format object:
212  EventFormat* format = 0;
213  ::TBranch* br = 0;
214  const Int_t status =
215  metaTree->SetBranchAddress(eventFormatBranchName.c_str(), &format, &br);
216  if (status < 0) {
217  ATH_MSG_ERROR("Failed to connect to xAOD::EventFormat object");
218  return StatusCode::FAILURE;
219  }
220 
221  // Merge the object into our private member.
222  br->GetEntry(0);
223  for (const auto& [key, element] : *format) {
224  m_inputEventFormat.add(element);
225  }
226 
227  // This is a strange place. The object has to be deleted, as it is the
228  // responsibility of the user code to do so. But if I also explicitly
229  // tell the branch to forget about the address of the pointer, then
230  // all hell breaks loose...
231  delete format;
232 
233  // Return gracefully.
234  return StatusCode::SUCCESS;
235  };
236 
237  // Read in the metadata from the "main" metadata ntuple.
238  m_inputEventFormat = {};
239  const StatusCode sc = readEventFormatMetadata(METADATA_TREE_NAME);
240  if (sc.isRecoverable()) {
241  m_inTree = nullptr;
242  m_inTreeMissing = true;
243  return StatusCode::SUCCESS;
244  }
245  ATH_CHECK(sc);
246 
247  // List all the other Metadata trees in the input file
248  // Having several metatrees can happen for augmented files for instance
249  // as one metadata tree per stream is produced
250  std::set<std::string> lOtherMetaTreeNames = {};
251  TList* lKeys = file->GetListOfKeys();
252 
253  if (lKeys) {
254  for (int iKey = 0; iKey < lKeys->GetEntries(); iKey++) {
255  // iterate over keys and add
256  std::string keyName = lKeys->At(iKey)->GetName();
257  // Make sure the key corresponds to a metadata tree but
258  // do not add the current metadata tree in the list of other trees
259  // and do not add the metadata tree handlers to the list
260  if ((keyName != METADATA_TREE_NAME) &&
261  (keyName.find("MetaData") != std::string::npos) &&
262  !(keyName.find("MetaDataHdr") != std::string::npos)) {
263  // Make sure key corresponds to a tree
264  const char* className = ((::TKey*)lKeys->At(iKey))->GetClassName();
265  static constexpr Bool_t LOAD = kFALSE;
266  static constexpr Bool_t SILENT = kTRUE;
267  ::TClass* cl = ::TClass::GetClass(className, LOAD, SILENT);
268  if ((cl != nullptr) && cl->InheritsFrom(::TTree::Class())) {
269  // key is corresponding to a metadata tree
270  lOtherMetaTreeNames.insert(std::move(keyName));
271  }
272  }
273  }
274  }
275 
276  // Loop over the other metadata trees found (if any).
277  for (const std::string& metaTreeName : lOtherMetaTreeNames) {
278  ATH_CHECK(readEventFormatMetadata(metaTreeName));
279  }
280 
281  // Look for the event tree in the input file.
282  m_inTree = file->Get<TTree>(treeName.data());
283  if (m_inTree == nullptr) {
284  // This is no longer an error condition. As it can happen for DxAODs
285  // that don't have any events in them. But they still have metadata
286  // that needs to be collected.
287  m_inTreeMissing = kTRUE;
288  }
289 
290  // Turn on the cache if requested.
291  if (m_inTree && useTreeCache && (!m_inTree->GetCacheSize())) {
292  m_inTree->SetCacheSize(CACHE_SIZE);
293  m_inTree->SetCacheLearnEntries(10);
294  }
295 
296  // Init the statistics collection.
297  ATH_CHECK(initStats());
298  // Update the event counter in the statistics object.
300  if (m_inTree) {
301  stats.setNEvents(stats.nEvents() + m_inTree->GetEntries());
302  }
303 
304  // Notify the listeners that a new file was opened.
305  const TIncident beginIncident(IncidentType::BeginInputFile);
306  for (TVirtualIncidentListener* listener : m_listeners) {
307  listener->handle(beginIncident);
308  }
309  // For now implement a very simple scheme in which we claim already
310  // at the start that the entire file was processed. Since we have no way
311  // of ensuring that the user indeed does this. And we can't delay calling
312  // this function, as the user may likely close his/her output file before
313  // closing the last opened input file.
314  const TIncident endIncident(IncidentType::EndInputFile);
315  for (TVirtualIncidentListener* listener : m_listeners) {
316  listener->handle(endIncident);
317  }
318 
319  // The initialisation was successful.
320  return StatusCode::SUCCESS;
321 }
322 
331 StatusCode TEvent::readFrom(::TTree* tree, bool useTreeCache) {
332 
333  // Remember the info:
334  m_inTree = nullptr;
335  m_inTreeMissing = false;
336  m_inChain = dynamic_cast<TChain*>(tree);
337  m_inMetaTree = nullptr;
338 
339  if (m_inChain) {
340 
341  // Set up the caching on the chain level. The individual trees of the
342  // input files will get a cache set up automatically after this.
343  if (useTreeCache && (!m_inChain->GetCacheSize())) {
344  m_inChain->SetCacheSize(CACHE_SIZE);
345  m_inChain->SetCacheLearnEntries(10);
346  }
347 
348  // Explicitly open the first file of the chain. To correctly auto-load
349  // the dictionaries necessary. This doesn't happen automatically with
350  // some ROOT versions...
351  const TObjArray* files = m_inChain->GetListOfFiles();
352  if (!files) {
353  ATH_MSG_ERROR("Couldn't get the list of files from the input TChain");
354  return StatusCode::FAILURE;
355  }
356  if (!files->GetEntries()) {
357  ATH_MSG_ERROR("No files are present in the received TChain");
358  return StatusCode::FAILURE;
359  }
360  const ::TChainElement* chEl =
361  dynamic_cast<const ::TChainElement*>(files->At(0));
362  if (!chEl) {
363  ATH_MSG_ERROR("Couldn't cast object to TChainElement");
364  return StatusCode::FAILURE;
365  }
366  {
367  std::unique_ptr<TFile> dummyFile{TFile::Open(chEl->GetTitle())};
368  if (!dummyFile) {
369  ATH_MSG_ERROR("Couldn't open file " << chEl->GetTitle());
370  return StatusCode::FAILURE;
371  }
372  }
373 
374  // Set up a tracker for the chain.
375  if (!m_inChainTracker) {
376  m_inChainTracker = std::make_unique<TChainStateTracker>();
377  }
378  m_inChainTracker->reset();
379  tree->SetNotify(m_inChainTracker.get());
380 
381  // Stop at this point. The first file will be opened when the user
382  // asks for the first event. Otherwise we open the first file of the
383  // chain multiple times.
384  m_inTreeNumber = -1;
385  return StatusCode::SUCCESS;
386 
387  } else {
388 
389  // If it's a simple TTree, then let's fully initialise the object
390  // using its file:
391  m_inTreeNumber = -1;
392  if (m_inChainTracker) {
393  m_inChainTracker.reset();
394  }
395  ::TFile* file = tree->GetCurrentFile();
396  return readFrom(file, useTreeCache, tree->GetName());
397  }
398 }
399 
408 StatusCode TEvent::writeTo(::TFile* file, int autoFlush,
409  std::string_view treeName) {
410 
411  // Just a simple security check.
412  if (!file) {
413  ATH_MSG_ERROR("Null pointer received!");
414  return StatusCode::FAILURE;
415  }
416 
417  // Check that the object is in the "right state":
418  if (m_outTree) {
419  ATH_MSG_ERROR("Object already writing to a file. Close that file first!");
420  return StatusCode::FAILURE;
421  }
422 
423  // Make sure we return to the current directory:
425 
426  // Create the output TTree:
427  file->cd();
428  m_outTree = std::make_unique<TTree>(treeName.data(), "xAOD event tree");
429  m_outTree->SetDirectory(file);
430  m_outTree->SetAutoSave(1000000);
431  m_outTree->SetAutoFlush(autoFlush);
432 
433  // Access the EventFormat object associated with this file:
436 
437  // Return gracefully:
438  return StatusCode::SUCCESS;
439 }
440 
448 
449  // A small sanity check:
450  if (!m_outTree) {
451  ATH_MSG_ERROR("The object doesn't seem to be connected to an output file!");
452  return StatusCode::FAILURE;
453  }
454 
455  // Make sure we return to the current directory:
457 
458  // Notify the listeners that they should write out their metadata, if they
459  // have any.
460  const TIncident incident(IncidentType::MetaDataStop);
461  for (auto& listener : m_listeners) {
462  listener->handle(incident);
463  }
464 
465  // Write out the event tree, and delete it:
466  m_outTree->AutoSave("FlushBaskets");
467  m_outTree->SetDirectory(0);
468  m_outTree.reset();
469 
470  // Now go to the output file:
471  file->cd();
472 
473  // Check if there's already a metadata tree in the output:
474  if (file->Get(METADATA_TREE_NAME)) {
475  // Let's assume that the metadata is complete in the file already.
476  return StatusCode::SUCCESS;
477  }
478 
479  // Create the metadata tree.
480  auto metatree =
481  std::make_unique<TTree>(METADATA_TREE_NAME, "xAOD metadata tree");
482  metatree->SetAutoSave(10000);
483  metatree->SetAutoFlush(-30000000);
484  metatree->SetDirectory(file);
485 
486  // Create the xAOD::EventFormat branch in it.
487  try {
488  metatree->Branch(
489  "EventFormat",
492  } catch (const CxxUtils::ClassName::ExcBadClassName& e) {
493  ::Error("xAOD::TEvent::finishWritingTo",
494  XAOD_MESSAGE("Class name parsing fails for %s ! "), e.what());
495  return StatusCode::FAILURE;
496  }
497 
498  // Create a copy of the m_outputMetaObjects variable. This is necessary
499  // because the putAux(...) function will modify this variable while we
500  // loop over it.
501  std::vector<std::pair<std::string, TObjectManager*>> outputMetaObjects;
502  outputMetaObjects.reserve(m_outputMetaObjects.size());
503  for (const auto& [key, mgr] : m_outputMetaObjects) {
504  TObjectManager* objMgr = dynamic_cast<TObjectManager*>(mgr.get());
505  if (objMgr == nullptr) {
506  ATH_MSG_FATAL("Internal logic error detected");
507  return StatusCode::FAILURE;
508  }
509  outputMetaObjects.emplace_back(key, objMgr);
510  }
511 
512  // Now loop over all the metadata objects that need to be put into the
513  // output file:
514  for (auto& [key, mgr] : outputMetaObjects) {
515 
516  // Select a split level depending on whether this is an interface or an
517  // auxiliary object:
518  const ::Int_t splitLevel = (key.ends_with("Aux.") ? 1 : 0);
519  // Create the new branch:
520  *(mgr->branchPtr()) =
521  metatree->Branch(key.c_str(), mgr->holder()->getClass()->GetName(),
522  mgr->holder()->getPtr(), 32000, splitLevel);
523  if (!mgr->branch()) {
524  ATH_MSG_ERROR("Failed to create metadata branch \""
525  << mgr->holder()->getClass()->GetName() << "/" << key
526  << "\"");
527  return StatusCode::FAILURE;
528  }
529  // Set up the saving of all the dynamic auxiliary properties
530  // of the object if it has any:
531  static constexpr bool METADATA = true;
532  ATH_CHECK(putAux(*metatree, *mgr, METADATA));
533  }
534 
535  // Write the metadata objects:
536  if (metatree->Fill() <= 0) {
537  ATH_MSG_ERROR("Failed to write event format metadata into the output");
538  metatree->SetDirectory(nullptr);
539  return StatusCode::FAILURE;
540  }
541 
542  // Now clean up:
543  metatree->Write();
544  metatree->SetDirectory(nullptr);
545  m_outputEventFormat = nullptr;
546  m_outputObjects.clear();
547  m_outputMetaObjects.clear();
548 
549  // Return gracefully:
550  return StatusCode::SUCCESS;
551 }
552 
562 SG::IAuxStore* TEvent::recordAux(const std::string& key,
564 
565  // A sanity check:
566  if (!m_outTree) {
567  ATH_MSG_ERROR("No output tree given to the object");
568  return nullptr;
569  }
570 
571  // Check for an object with this name in the output list:
573  if (itr == m_outputObjects.end()) {
574  // Create one if if it doesn't exist yet...
575  // Translate the store type:
577  switch (type) {
580  break;
583  break;
584  default:
585  ATH_MSG_ERROR("Unknown store type (" << type << ") requested");
586  return nullptr;
587  }
588  // Create and record the object:
589  static constexpr bool TOP_STORE = true;
590  if (record(std::make_unique<TAuxStore>(key, TOP_STORE, mode), key)
591  .isFailure()) {
592  ATH_MSG_ERROR("Couldn't connect TAuxStore object to the output");
593  return nullptr;
594  }
595  // Update the iterator:
596  itr = m_outputObjects.find(key);
597  }
598 
599  // A security check:
600  if (itr == m_outputObjects.end()) {
601  ATH_MSG_ERROR("Internal logic error detected");
602  return nullptr;
603  }
604 
605  // Check that it is of the right type:
606  TAuxManager* mgr = dynamic_cast<TAuxManager*>(itr->second.get());
607  if (!mgr) {
608  ATH_MSG_ERROR("Internal logic error detected");
609  return nullptr;
610  }
611 
612  // Extract the pointer out of it:
613  TAuxStore* store = mgr->getStore();
614 
615  // Give it to the user:
616  return store;
617 }
618 
621 ::Long64_t TEvent::getEntries() const {
622 
623  if (m_inChain) {
624  return m_inChain->GetEntries();
625  } else if (m_inTree) {
626  return m_inTree->GetEntries();
627  } else if (m_inTreeMissing) {
628  // The input file is empty:
629  return 0;
630  } else {
631  ATH_MSG_ERROR("Function called on an uninitialised object");
632  return 0;
633  }
634 }
635 
650 ::Int_t TEvent::getEntry(::Long64_t entry, ::Int_t getall) {
651 
652  // A little sanity check:
653  if ((!m_inTree) && (!m_inChain)) {
654  ATH_MSG_ERROR("Function called on an uninitialised object");
655  return -1;
656  }
657 
658  // If we have a chain as input:
659  if (m_inChain) {
660  // Make sure that the correct tree is loaded:
661  const ::Long64_t fileEntry = m_inChain->LoadTree(entry);
662  if (fileEntry < 0) {
663  ATH_MSG_ERROR("Failure in loading entry " << entry
664  << " from the input chain");
665  return -1;
666  }
667  // Check if a new file was loaded:
668  if ((m_inTreeNumber != m_inChain->GetTreeNumber()) ||
669  m_inChainTracker->internalStateChanged()) {
670  // Reset the tracker:
671  m_inChainTracker->reset();
672  // Connect to this new file:
673  m_inTreeNumber = m_inChain->GetTreeNumber();
674  ::TFile* file = m_inChain->GetFile();
675  // The useTreeCache parameter is set to false, since the cache
676  // is anyway set up through the TChain. It shouldn't be modified
677  // on the file level.
678  static constexpr bool USE_TREE_CACHE = false;
679  if (readFrom(file, USE_TREE_CACHE, m_inChain->GetName()).isFailure()) {
680  ATH_MSG_ERROR("Couldn't connect to input file #"
681  << m_inTreeNumber << " of the input chain");
682  return -1;
683  }
684  }
685  // Restore the previously received entry number.
686  m_entry = fileEntry;
687  }
688  // If we have a regular file/tree as input:
689  else {
690  m_entry = entry;
691  }
692 
693  // In order to make the reading of branches+tree cache work
694  // NB: TTree::LoadTree() only set the entry that should be read for each
695  // branch but no reading of the branch content is performed when calling that
696  // function. The entry set that can be retrieved with
697  // branch->GetTree()->GetReadEntry()
698  // For friend trees, if an index was built, then the entry which is set for
699  // the related branches is found by the LoadTree function by matching the the
700  // major and minor values of the main tree and friend tree
701  if (m_inTree && m_inTree->LoadTree(m_entry) < 0) {
702  ATH_MSG_ERROR("Failure in loading entry " << m_entry
703  << " from the input file");
704  return -1;
705  }
706 
707  // Stats counter needs to know it's the next event:
709 
710  // The final number of bytes read.
711  ::Int_t result = 0;
712 
713  // Check if objects need to be read in.
714  if (getall) {
715  if (m_auxMode == kAthenaAccess) {
716  // In kAthenaAccess mode we need to use getInputObject(...) to load
717  // all the input objects correctly.
718  for (auto& [key, mgr] : m_inputObjects) {
719  static const std::string dynStorePostfix = "Aux.Dynamic";
720  if (key.ends_with(dynStorePostfix)) {
721  // Ignore the dynamic store objects. They get loaded through
722  // their parents.
723  } else {
724  // Load the objects and their auxiliary stores through the
725  // getInputObject(...) function, which takes care of correctly
726  // setting them up. The type is irrelevant here. We don't
727  // really care about the exact type of the objects.
728  static constexpr bool SILENT = true;
729  static constexpr bool METADATA = false;
730  getInputObject(key, typeid(int), SILENT, METADATA);
731  }
732  }
733  } else {
734  // In a "reasonable" access mode, we do something very simple:
735  for (auto& [key, mgr] : m_inputObjects) {
736  result += mgr->getEntry(getall);
737  }
738  }
739  }
740 
741  // Notify the listeners that a new event was loaded:
742  const TIncident incident(IncidentType::BeginEvent);
743  for (auto& listener : m_listeners) {
744  listener->handle(incident);
745  }
746 
747  // Return the number of bytes read:
748  return result;
749 }
750 
760 ::Long64_t TEvent::getFiles() const {
761 
762  if (m_inChain) {
763  return m_inChain->GetListOfFiles()->GetEntries();
764  } else if (m_inTree || m_inTreeMissing) {
765  return 1;
766  } else {
767  return 0;
768  }
769 }
770 
780 ::Int_t TEvent::getFile(::Long64_t file, ::Int_t getall) {
781 
782  // Check if the file number is valid:
783  if ((file < 0) || (file >= getFiles())) {
784  ATH_MSG_ERROR("Function called with invalid file number (" << file << ")");
785  return -1;
786  }
787 
788  // If we are not reading a TChain, return at this point. As the one and
789  // only file is open already...
790  if (!m_inChain) {
791  return 0;
792  }
793 
794  // Trigger the "scanning" of the input files, so the TChain would know
795  // how many entries are in the various files.
796  getEntries();
797 
798  // Calculate which entry/event we need to load:
799  ::Long64_t entry = 0;
800  for (::Long64_t i = 0; i < file; ++i) {
801  entry += m_inChain->GetTreeOffset()[i];
802  }
803 
804  // Load this entry using the regular event opening function:
805  return getEntry(entry, getall);
806 }
807 
814 ::Int_t TEvent::fill() {
815 
816  // A little sanity check:
817  if (!m_outTree) {
818  ATH_MSG_ERROR("Object not connected to an output file!");
819  return 0;
820  }
821 
822  // Make sure that all objects have been read in. The 99 as the value
823  // has a special meaning for TAuxStore. With this value it doesn't
824  // delete its transient (decoration) variables. Otherwise it does.
825  // (As it's supposed to, when moving to a new event.)
826  Int_t readBytes = 0;
827  if (m_inChain != nullptr) {
828  readBytes = getEntry(m_inChain->GetReadEntry(), 99);
829  } else if (m_inTree != nullptr) {
830  readBytes = getEntry(m_entry, 99);
831  }
832  if (readBytes < 0) {
833  ATH_MSG_ERROR("getEntry failed!");
834  return readBytes;
835  }
836 
837  // Prepare the objects for writing. Note that we need to iterate over a
838  // copy of the m_outputObjects container. Since the putAux(...) function
839  // called inside the loop may itself add elements to the m_outputObject
840  // container.
841  std::string unsetObjects;
842  std::vector<std::pair<std::string, TVirtualManager*>> outputObjectsCopy;
843  outputObjectsCopy.reserve(m_outputObjects.size());
844  for (const auto& [key, mgr] : m_outputObjects) {
845  outputObjectsCopy.emplace_back(key, mgr.get());
846  }
847  for (auto& [key, mgr] : outputObjectsCopy) {
848  // Check that a new object was provided in the event:
849  if (!mgr->create()) {
850  // We are now going to fail. But let's collect the names of
851  // all the unset objects:
852  if (unsetObjects.size()) {
853  unsetObjects += ", ";
854  }
855  unsetObjects.append("\"" + key + "\"");
856  continue;
857  }
858  // Make sure that any dynamic auxiliary variables that
859  // were added to the object after it was put into the event,
860  // get added to the output:
861  static constexpr bool METADATA = false;
862  if (putAux(*m_outTree, *mgr, METADATA).isFailure()) {
864  "Failed to put dynamic auxiliary variables "
865  "in the output for object \""
866  << key << "\"");
867  return 0;
868  }
869  }
870 
871  // Check if there were any unset objects:
872  if (unsetObjects.size()) {
873  ATH_MSG_ERROR("The following objects were not set in the current event: "
874  << unsetObjects);
875  return 0;
876  }
877 
878  // Write the entry, and check the return value:
879  const ::Int_t ret = m_outTree->Fill();
880  if (ret <= 0) {
881  ATH_MSG_ERROR("Output tree filling failed with return value: " << ret);
882  }
883 
884  // Reset the object managers.
885  for (auto& [key, mgr] : m_outputObjects) {
886  mgr->reset();
887  }
888 
889  // Return the value:
890  return ret;
891 }
892 
893 bool TEvent::hasInput() const {
894 
895  return ((m_inTree != nullptr) || (m_inChain != nullptr));
896 }
897 
898 bool TEvent::hasOutput() const {
899 
900  return (m_outTree.get() != nullptr);
901 }
902 
903 StatusCode TEvent::getNames(const std::string& targetClassName,
904  std::vector<std::string>& vkeys,
905  bool metadata) const {
906  // The results go in here
907  std::set<std::string> keys;
908 
909  // Get list of branches from
910  // the input metadata tree or input tree
911  std::vector<TObjArray*> fullListOfBranches = {};
912  if (metadata) {
913  if (m_inMetaTree) {
914  // No friend tree expected for metadata tree
915  // Only add the list of branches of the metadata tree
916  ATH_MSG_DEBUG("Scanning for input metadata objects");
917  fullListOfBranches.push_back(m_inMetaTree->GetListOfBranches());
918  }
919  } else {
920  if (m_inTree) {
921  ATH_MSG_DEBUG("Scanning for input data objects");
922  // Add the list of branches of the main tree
923  fullListOfBranches.push_back(m_inTree->GetListOfBranches());
924  // If the input tree has friend trees
925  // add as well the list of friend tree branches
926  if (m_inTree->GetListOfFriends()) {
927  // Get the list of friends
928  TList* fList = m_inTree->GetListOfFriends();
929  // Loop over friend elements
930  for (TObject* feObj : *fList) {
931  if (feObj) {
932  // Get corresponding friend tree
933  auto* pElement = dynamic_cast<TFriendElement*>(feObj);
934  if (pElement == nullptr) {
935  continue;
936  }
937  TTree* friendTree = pElement->GetTree();
938  // Add list of branches of the friend tree
939  fullListOfBranches.push_back(friendTree->GetListOfBranches());
940  }
941  }
942  }
943  }
944  }
945 
946  // Loop over all list of branches (if any)
947  for (const TObjArray* in : fullListOfBranches) {
948  // Loop over all branches inside the current list of branches
949  for (const TObject* obj : *in) {
950 
951  if (obj == nullptr) {
952  continue;
953  }
954  const TBranch* element = dynamic_cast<const TBranch*>(obj);
955  if (!element) {
956  ATH_MSG_ERROR("Failure inspecting input data objects");
957  return StatusCode::FAILURE;
958  }
959  const std::string objClassName = element->GetClassName();
960  const std::string key = obj->GetName();
961  ATH_MSG_VERBOSE("Inspecting \"" << objClassName << "\" / \"" << key
962  << "\"");
963  if (objClassName == targetClassName) {
964  ATH_MSG_DEBUG("Matched \"" << targetClassName << "\" to key \"" << key
965  << "\"");
966  keys.insert(key);
967  }
968  }
969  }
970 
971  const Object_t& inAux = (metadata ? m_inputMetaObjects : m_inputObjects);
972 
973  ATH_MSG_DEBUG("Scanning input objects for \"" << targetClassName << "\"");
974  for (const auto& [key, vmgr] : inAux) {
975  // All (metadata) objects should be held by TObjectManager objects.
976  const TObjectManager* mgr = dynamic_cast<const TObjectManager*>(vmgr.get());
977  if (mgr == nullptr) {
978  continue;
979  }
980  const std::string& objClassName = mgr->holder()->getClass()->GetName();
981  ATH_MSG_VERBOSE("Inspecting \"" << objClassName << "\" / \"" << key
982  << "\"");
983  if (objClassName == targetClassName) {
984  ATH_MSG_DEBUG("Matched \"" << targetClassName << "\" to key \"" << key
985  << "\"");
986  keys.insert(key);
987  }
988  }
989 
990  // Check for output objects.
991  if ((metadata == false) && m_outTree) {
992  const TObjArray* out = m_outTree->GetListOfBranches();
993  ATH_MSG_DEBUG("Scanning for output data objects");
994 
995  for (const TObject* obj : *out) {
996  if (obj == nullptr) {
997  continue;
998  }
999  const TBranch* element = dynamic_cast<const TBranch*>(obj);
1000  if (element == nullptr) {
1001  ATH_MSG_ERROR("Failure inspecting output objects");
1002  return StatusCode::FAILURE;
1003  }
1004  const std::string objClassName = element->GetClassName();
1005  const std::string key = obj->GetName();
1006  ATH_MSG_VERBOSE("Inspecting \"" << objClassName << "\" / \"" << key
1007  << "\"");
1008  if (objClassName == targetClassName) {
1009  ATH_MSG_DEBUG("Matched \"" << targetClassName << "\" to key \"" << key
1010  << "\"");
1011  keys.insert(key);
1012  }
1013  }
1014  }
1015 
1016  const Object_t& outAux = (metadata ? m_outputMetaObjects : m_outputObjects);
1017 
1018  // Search though the in-memory output objects.
1019  ATH_MSG_DEBUG("Scanning output objects for \"" << targetClassName << "\"");
1020  for (const auto& [key, vmgr] : outAux) {
1021  // All (metadata) objects should be held by TObjectManager objects.
1022  TObjectManager* mgr = dynamic_cast<TObjectManager*>(vmgr.get());
1023  if (mgr == nullptr) {
1024  continue;
1025  }
1026  const std::string& objClassName = mgr->holder()->getClass()->GetName();
1027  ATH_MSG_VERBOSE("Inspecting \"" << objClassName << "\" / \"" << key
1028  << "\"");
1029  if (objClassName == targetClassName) {
1030  ATH_MSG_DEBUG("Matched \"" << targetClassName << "\" to key \"" << key
1031  << "\"");
1032  keys.insert(key);
1033  }
1034  }
1035 
1036  vkeys.insert(vkeys.end(), keys.begin(), keys.end());
1037 
1038  // Return gracefully.
1039  return StatusCode::SUCCESS;
1040 }
1041 
1059 StatusCode TEvent::connectObject(const std::string& key, bool silent) {
1060 
1061  // A little sanity check:
1062  if (hasInput() == false) {
1063  ATH_MSG_ERROR("Function called on un-initialised object");
1064  return StatusCode::FAILURE;
1065  }
1066 
1067  // Increment the access counter on this container:
1069 
1070  // Check if the branch is already connected:
1071  if (m_inputObjects.contains(key)) {
1072  return StatusCode::SUCCESS;
1073  }
1074  // Check if it was already found to be missing.
1075  if (m_inputMissingObjects.contains(key)) {
1076  if (silent == false) {
1077  ATH_MSG_WARNING("Branch \"" << key << "\" not available on input");
1078  }
1079  return StatusCode::RECOVERABLE;
1080  }
1081 
1082  // Check if we have metadata about this branch:
1083  const xAOD::EventFormatElement* ef = nullptr;
1084  if (m_inputEventFormat.exists(key) == false) {
1085  if (silent == false) {
1086  ATH_MSG_WARNING("No metadata available for branch: " << key);
1087  }
1088  } else {
1090  }
1091 
1092  // Check if the branch exists in our input tree:
1093  ::TBranch* br = m_inTree->GetBranch(key.c_str());
1094  if (br == nullptr) {
1095  if (!silent) {
1096  ATH_MSG_WARNING("Branch \"" << key << "\" not available on input");
1097  }
1098  m_inputMissingObjects.insert(key);
1099  return StatusCode::RECOVERABLE;
1100  }
1101 
1102  // Make sure that it's not in "MakeClass mode":
1103  br->SetMakeClass(0);
1104 
1105  // Decide about the type that we need to use for the reading of this
1106  // branch:
1107  std::string className = br->GetClassName();
1108  if (className == "") {
1109  if (ef) {
1110  // This is a fairly weird situation, but let's fall back to taking
1111  // the class name from the metadata object in this case.
1112  className = ef->className();
1113  } else {
1114  ATH_MSG_ERROR(
1115  "Couldn't find an appropriate type with a dictionary for branch \""
1116  << key << "\"");
1117  return StatusCode::FAILURE;
1118  }
1119  }
1120  ::TClass* realClass = ::TClass::GetClass(className.c_str());
1121  if (((!realClass) || (!realClass->IsLoaded())) && ef) {
1122  // We may need to do an actual schema evolution here, in which
1123  // case let's fall back on the class name coming from the metadata
1124  // object.
1125  className = ef->className();
1126  realClass = ::TClass::GetClass(className.c_str());
1127  }
1128  if ((!realClass) || (!realClass->IsLoaded())) {
1129  // Now we're in trouble...
1130  ATH_MSG_ERROR(
1131  "Couldn't find an appropriate type with a dictionary for branch \""
1132  << key << "\"");
1133  return StatusCode::FAILURE;
1134  }
1135 
1136  // Make sure that the current object is the "active event":
1137  setActive();
1138 
1139  // The data type is always "other" for us:
1140  static const ::EDataType dataType = kOther_t;
1141 
1142  // Check if the output already has this object. If it does, let's
1143  // assume that we have been copying the object to the output. Which
1144  // means that we need to resume filling the same memory address that
1145  // the output holder points to.
1146  void* ptr = nullptr;
1147  Object_t::const_iterator out_itr = m_outputObjects.find(key);
1148  if (out_itr != m_outputObjects.end()) {
1149  // It needs to be an object manager...
1150  TObjectManager* mgr = dynamic_cast<TObjectManager*>(out_itr->second.get());
1151  if (mgr == nullptr) {
1152  ATH_MSG_ERROR("Couldn't access output manager for: " << key);
1153  return StatusCode::FAILURE;
1154  }
1155  // Get the pointer out of it:
1156  ptr = mgr->holder()->get();
1157  }
1158 
1159  // If there is no output object, then let's create one ourselves.
1160  // This is the only way in which we can have the memory management of
1161  // THolder do the right thing with this object.
1162  if (ptr == nullptr) {
1163  ptr = realClass->New();
1164  }
1165 
1166  // Create the new manager object that will hold this EDM object:
1167  const bool renewOnRead = (m_auxMode == kAthenaAccess);
1168  auto mgr = std::make_unique<TObjectManager>(
1169  nullptr, std::make_unique<THolder>(ptr, realClass), renewOnRead);
1170 
1171  // One final check. If it's not an auxiliary store, then it must have
1172  // a split level of 0. Otherwise read rules may not work on it. Causing
1173  // *very* serious silent corruption in the data read, if we don't use
1174  // the "Athena read mode".
1175  if ((m_auxMode != kAthenaAccess) && (br->GetSplitLevel() != 0) &&
1176  (Details::isAuxStore(*(mgr->holder()->getClass())) == false)) {
1177  ATH_MSG_ERROR("Split level for branch \""
1178  << key << "\" is " << br->GetSplitLevel()
1179  << ". This can only be read in kAthenaAccess mode.");
1180  // Clean up:
1181  *(mgr->holder()->getPtr()) = nullptr;
1182  m_inputObjects.erase(key);
1183  return StatusCode::FAILURE;
1184  }
1185 
1186  // Now try to connect to the branch:
1187  const ::Int_t status =
1188  m_inTree->SetBranchAddress(key.c_str(), mgr->holder()->getPtr(),
1189  mgr->branchPtr(), realClass, dataType, kTRUE);
1190  if (status < 0) {
1191  ATH_MSG_ERROR("Couldn't connect variable of type \""
1192  << className << "\" to input branch \"" << key
1193  << "\". Return code: " << status);
1194  // Clean up:
1195  *(mgr->holder()->getPtr()) = 0;
1196  m_inputObjects.erase(key);
1197  return StatusCode::FAILURE;
1198  }
1199 
1200  // At this point we have successfully connected the branch.
1201  TObjectManager* mgrPtr = mgr.get();
1202  m_inputObjects[key] = std::move(mgr);
1203 
1204  // If it's an auxiliary store object, set it up correctly:
1205  if (Details::isAuxStore(*(mgrPtr->holder()->getClass()))) {
1207  }
1208 
1209  // If there may be an auxiliary object connected to this one,
1210  // connect that as well:
1211  if (Details::hasAuxStore(*(mgrPtr->holder()->getClass()))) {
1213  key + "Aux.", Details::isStandalone(*(mgrPtr->holder()->getClass()))));
1214  }
1215 
1216  // Return gracefully.
1217  return StatusCode::SUCCESS;
1218 }
1219 
1228 StatusCode TEvent::connectMetaObject(const std::string& key, bool silent) {
1229 
1230  // A little sanity check:
1231  if (!m_inMetaTree) {
1232  ATH_MSG_ERROR("Function called on un-initialised object");
1233  return StatusCode::FAILURE;
1234  }
1235 
1236  // Check if the branch is already connected:
1237  if (m_inputMetaObjects.contains(key)) {
1238  return StatusCode::SUCCESS;
1239  }
1240 
1241  // Check if the branch exists in our metadata tree:
1242  ::TBranch* br = m_inMetaTree->GetBranch(key.c_str());
1243  if (br == nullptr) {
1244  if (silent == false) {
1245  ATH_MSG_WARNING("Metadata branch \"" << key
1246  << "\" not available on input");
1247  }
1248  return StatusCode::RECOVERABLE;
1249  }
1250 
1251  // Check that we have an entry in the branch:
1252  if (br->GetEntries() == 0) {
1253  if (silent == false) {
1254  ATH_MSG_WARNING("Metadata branch \"" << key
1255  << "\" doesn't hold any data");
1256  }
1257  return StatusCode::RECOVERABLE;
1258  }
1259 
1260  // Make sure that it's not in "MakeClass mode":
1261  br->SetMakeClass(0);
1262 
1263  // Extract the type of the branch:
1264  ::TClass* cl = 0;
1265  ::EDataType dt = kOther_t;
1266  if (br->GetExpectedType(cl, dt) || (!cl)) {
1267  ATH_MSG_ERROR("Couldn't get the type for metadata branch \"" << key
1268  << "\"");
1269  return StatusCode::FAILURE;
1270  }
1271 
1272  // Create the object, and all of the managers around it:
1273  void* ptr = cl->New();
1274  const bool renewOnRead = (m_auxMode == kAthenaAccess);
1275  auto mgr = std::make_unique<TObjectManager>(
1276  nullptr, std::make_unique<THolder>(ptr, cl), renewOnRead);
1277 
1278  // Now try to connect to the branch:
1279  const ::Int_t status = m_inMetaTree->SetBranchAddress(
1280  key.c_str(), mgr->holder()->getPtr(), mgr->branchPtr(), cl, dt, kTRUE);
1281  if (status < 0) {
1282  ATH_MSG_ERROR("Couldn't connect variable of type \""
1283  << cl->GetName() << "\" to input branch \"" << key
1284  << "\". Return code: " << status);
1285  // Clean up:
1286  *(mgr->holder()->getPtr()) = 0;
1287  m_inputMetaObjects.erase(key);
1288  return StatusCode::FAILURE;
1289  }
1290 
1291  // Store the manager.
1292  TObjectManager* mgrPtr = mgr.get();
1293  m_inputMetaObjects[key] = std::move(mgr);
1294 
1295  // Read in the object:
1296  if (mgrPtr->getEntry() < 0) {
1297  ATH_MSG_ERROR("Couldn't read in metadata object with key \"" << key
1298  << "\"");
1299  return StatusCode::FAILURE;
1300  }
1301 
1302  // If it's an auxiliary store object, set it up correctly:
1303  if (Details::isAuxStore(*(mgrPtr->holder()->getClass()))) {
1305  }
1306 
1307  // If there may be an auxiliary object connected to this one,
1308  // connect that as well.
1309  if (Details::hasAuxStore(*(mgrPtr->holder()->getClass()))) {
1311  key + "Aux.", Details::isStandalone(*(mgrPtr->holder()->getClass()))));
1312  static constexpr bool METADATA = true;
1313  ATH_CHECK(setAuxStore(key, *mgrPtr, METADATA));
1314  }
1315 
1316  // We succeeded:
1317  return StatusCode::SUCCESS;
1318 }
1319 
1329 StatusCode TEvent::connectAux(const std::string& prefix, bool standalone) {
1330 
1331  // A simple test...
1332  if (hasInput() == false) {
1333  ATH_MSG_ERROR("No input tree is available");
1334  return StatusCode::FAILURE;
1335  }
1336 
1337  // Check if we know anything about this auxiliary object:
1338  if ((!m_inTree->GetBranch(prefix.c_str())) &&
1340  // If not, then let's just return right away. Not having
1341  // an auxiliary object with this name is not an error per se.
1342  return StatusCode::SUCCESS;
1343  }
1344 
1345  // Check if the branch is already connected.
1346  if (m_inputObjects.contains(prefix)) {
1347  return StatusCode::SUCCESS;
1348  }
1349 
1350  // Do different things based on the "auxiliary mode" we are in.
1351  if ((m_auxMode == kClassAccess) || (m_auxMode == kAthenaAccess)) {
1352 
1353  // In "class" and "athena" access modes just connect the concrete auxiliary
1354  // object to the input.
1355  static constexpr bool SILENT = false;
1356  ATH_CHECK(connectObject(prefix, SILENT));
1357 
1358  // Return gracefully.
1359  return StatusCode::SUCCESS;
1360 
1361  } else if (m_auxMode == kBranchAccess) {
1362 
1363  // In "branch access mode" let's create a TAuxStore object, and let
1364  // that take care of the auxiliary store access.
1365  static constexpr bool TOP_STORE = true;
1366  auto store = std::make_unique<TAuxStore>(
1367  prefix, TOP_STORE,
1370 
1371  // Connect it to the input tree.
1372  ATH_CHECK(store->readFrom(*m_inTree));
1373 
1374  // We're using this object to read from the input, it needs to be
1375  // locked:
1376  store->lock();
1377 
1378  // Finally, set up an appropriate manager for it.
1379  static constexpr bool IS_OWNER = true;
1381  std::make_unique<TAuxManager>(store.release(), IS_OWNER);
1382 
1383  // Return gracefully:
1384  return StatusCode::SUCCESS;
1385  }
1386 
1387  // There was some problem:
1388  ATH_MSG_ERROR("Unknown auxiliary access mode set (" << m_auxMode << ")");
1389  return StatusCode::FAILURE;
1390 }
1391 
1402 
1403  // Check if the branch is already connected:
1404  if (m_inputMetaObjects.contains(prefix)) {
1405  return StatusCode::SUCCESS;
1406  }
1407 
1408  // A sanity check:
1409  if (!m_inMetaTree) {
1410  ATH_MSG_FATAL("Internal logic error detected");
1411  return StatusCode::FAILURE;
1412  }
1413 
1414  // Do different things based on the "auxiliary mode" we are in:
1416 
1417  // In "class" and "athena" access modes just connect the concrete auxiliary
1418  // object to the input.
1419  static constexpr bool SILENT = false;
1421 
1422  // Return gracefully:
1423  return StatusCode::SUCCESS;
1424 
1425  } else if (m_auxMode == kBranchAccess) {
1426 
1427  // In "branch access mode" let's create a TAuxStore object, and let
1428  // that take care of the auxiliary store access.
1429  static constexpr bool TOP_STORE = true;
1430  auto store = std::make_unique<TAuxStore>(
1431  prefix, TOP_STORE,
1434 
1435  // Connect it to the input tree.
1436  ATH_CHECK(store->readFrom(*m_inMetaTree));
1437 
1438  // We're using this object to read from the input, it needs to be
1439  // locked:
1440  store->lock();
1441 
1442  // Finally, set up an appropriate manager for it.
1443  static constexpr bool IS_OWNER = true;
1445  std::make_unique<TAuxManager>(store.release(), IS_OWNER);
1446 
1447  // Return gracefully.
1448  return StatusCode::SUCCESS;
1449  }
1450 
1451  // There was some problem:
1452  ATH_MSG_ERROR("Unknown auxiliary access mode set (" << m_auxMode << ")");
1453  return StatusCode::FAILURE;
1454 }
1455 
1467 
1468  // Pre-compute some values.
1469  const bool isAuxStore = Details::isAuxStore(*(mgr.holder()->getClass()));
1470 
1471  // Check if we need to do anything.
1472  if ((Details::hasAuxStore(*(mgr.holder()->getClass())) == false) &&
1473  (isAuxStore == false)) {
1474  return StatusCode::SUCCESS;
1475  }
1476 
1477  // Select which object container to use:
1479 
1480  // Look up the auxiliary object's manager:
1481  TVirtualManager* auxMgr = nullptr;
1482  std::string auxKey;
1483  if (isAuxStore) {
1484  auxMgr = &mgr;
1485  auxKey = key;
1486  } else {
1487  auto itr = objects.find(key + "Aux.");
1488  if (itr == objects.end()) {
1489  // Apparently there's no auxiliary object for this DV, so let's
1490  // give up:
1491  return StatusCode::SUCCESS;
1492  }
1493  auxMgr = itr->second.get();
1494  auxKey = key + "Aux.";
1495  }
1496 
1497  if (metadata == false) {
1498  // Make sure the auxiliary object is up to date:
1499  const ::Int_t readBytes = auxMgr->getEntry();
1500  if (readBytes < 0) {
1501  ATH_MSG_ERROR(
1502  "Couldn't load current entry for auxiliary object with key \""
1503  << auxKey << "\"");
1504  return StatusCode::FAILURE;
1505  }
1506 
1507  // Check if there is a separate auxiliary object for the dynamic
1508  // variables:
1509  const std::string dynAuxKey = auxKey + "Dynamic";
1510  auto dynAuxMgr = objects.find(dynAuxKey);
1511 
1512  if ((dynAuxMgr != objects.end()) &&
1513  (readBytes || (m_auxMode == kAthenaAccess) || (auxMgr == &mgr))) {
1514  // Do different things based on the access mode:
1515  if (m_auxMode != kAthenaAccess) {
1516  // In "normal" access modes just tell the dynamic store object
1517  // to switch to a new event.
1518  dynAuxMgr->second->getEntry();
1519  } else {
1520  // In "Athena mode" this object has already been deleted when
1521  // the main auxiliary store object was switched to the new
1522  // event. So let's re-create it:
1523  xAOD::TObjectManager& auxMgrRef =
1524  dynamic_cast<xAOD::TObjectManager&>(*auxMgr);
1525  ATH_CHECK(
1526  setUpDynamicStore(auxMgrRef, (metadata ? m_inMetaTree : m_inTree)));
1527  // Now tell the newly created dynamic store object which event
1528  // it should be looking at:
1529  auto dynAuxMgr = objects.find(dynAuxKey);
1530  if (dynAuxMgr == objects.end()) {
1531  ATH_MSG_ERROR("Internal logic error detected");
1532  return StatusCode::FAILURE;
1533  }
1534  dynAuxMgr->second->getEntry();
1535  }
1536  }
1537  }
1538 
1539  // Stop here if we've set up an auxiliary store.
1540  if (isAuxStore) {
1541  return StatusCode::SUCCESS;
1542  }
1543 
1544  // Access the auxiliary base class of the object/vector:
1545  SG::AuxVectorBase* vec = 0;
1546  SG::AuxElement* aux = 0;
1547  switch (mgr.holder()->typeKind()) {
1548  case THolder::DATAVECTOR: {
1549  void* vvec = mgr.holder()->getAs(typeid(SG::AuxVectorBase));
1550  vec = reinterpret_cast<SG::AuxVectorBase*>(vvec);
1551  } break;
1552  case THolder::AUXELEMENT: {
1553  void* vaux = mgr.holder()->getAs(typeid(SG::AuxElement));
1554  aux = reinterpret_cast<SG::AuxElement*>(vaux);
1555  } break;
1556  default:
1557  break;
1558  }
1559 
1560  // Check whether index tracking is enabled for the type. If not, then
1561  // we need to fix it...
1562  if (vec && (!vec->trackIndices())) {
1563  Details::forceTrackIndices(*vec);
1564  }
1565 
1566  // Check if we were successful:
1567  if ((!vec) && (!aux)) {
1568  ATH_MSG_FATAL("Couldn't access class \""
1569  << mgr.holder()->getClass()->GetName()
1570  << "\" as SG::AuxVectorBase or SG::AuxElement");
1571  return StatusCode::FAILURE;
1572  }
1573 
1574  // Get the auxiliary store object:
1575  const SG::IConstAuxStore* store = 0;
1576  if (m_auxMode == kBranchAccess) {
1577  // Get the concrete auxiliary manager:
1578  TAuxManager* amgr = dynamic_cast<TAuxManager*>(auxMgr);
1579  if (!amgr) {
1580  ATH_MSG_FATAL("Auxiliary manager for \""
1581  << auxKey << "\" is not of the right type");
1582  return StatusCode::FAILURE;
1583  }
1584  store = amgr->getConstStore();
1585  // If the store still doesn't know its type, help it now:
1586  if (amgr->getStore()->structMode() ==
1591  amgr->getStore()->setStructMode(mode);
1592  }
1593  } else if (m_auxMode == kClassAccess || m_auxMode == kAthenaAccess) {
1594  // Get the concrete auxiliary manager:
1595  TObjectManager* omgr = dynamic_cast<TObjectManager*>(auxMgr);
1596  if (!omgr) {
1597  ATH_MSG_FATAL("Auxiliary manager for \""
1598  << auxKey << "\" is not of the right type");
1599  return StatusCode::FAILURE;
1600  }
1601  void* p = omgr->holder()->getAs(typeid(SG::IConstAuxStore));
1602  store = reinterpret_cast<const SG::IConstAuxStore*>(p);
1603  }
1604  if (!store) {
1605  ATH_MSG_FATAL("Logic error detected in the code");
1606  return StatusCode::FAILURE;
1607  }
1608 
1609  // Connect the two:
1610  if (vec) {
1611  vec->setStore(store);
1612  } else if (aux) {
1613  aux->setStore(store);
1614  } else {
1615  ATH_MSG_FATAL("Logic error detected in the code");
1616  return StatusCode::FAILURE;
1617  }
1618 
1619  // We succeeded:
1620  return StatusCode::SUCCESS;
1621 }
1622 
1638 StatusCode TEvent::record(void* obj, const std::string& typeName,
1639  const std::string& key, bool overwrite, bool metadata,
1640  bool isOwner) {
1641 
1642  // Check if we have an output tree when writing an event:
1643  if (!m_outTree && !metadata) {
1644  ATH_MSG_ERROR(
1645  "No output tree defined. Did you forget to call writeTo(...)?");
1646  return StatusCode::FAILURE;
1647  }
1648  assert(m_outputEventFormat != 0);
1649 
1650  // If this is metadata, just take ownership of it. The object will only
1651  // be recorded into the output file when calling finishWritingTo(...).
1652  if (metadata) {
1653  // Check whether we already have such an object:
1654  if ((!overwrite) &&
1655  (m_outputMetaObjects.find(key) != m_outputMetaObjects.end())) {
1656  ATH_MSG_ERROR("Meta-object \"" << typeName << "\"/\"" << key
1657  << "\" already recorded");
1658  return StatusCode::FAILURE;
1659  }
1660  // Check if we have a dictionary for this object:
1661  TClass* cl = TClass::GetClass(typeName.c_str());
1662  if (!cl) {
1663  ATH_MSG_ERROR("Didn't find dictionary for type: " << typeName);
1664  return StatusCode::FAILURE;
1665  }
1666  // Let's create a holder for the object:
1667  const bool renewOnRead = (m_auxMode == kAthenaAccess);
1668  m_outputMetaObjects[key] = std::make_unique<TObjectManager>(
1669  nullptr, std::make_unique<THolder>(obj, cl, isOwner), renewOnRead);
1670  // We're done. The rest will be done later on.
1671  return StatusCode::SUCCESS;
1672  }
1673 
1674  // Check if we accessed this object on the input. If yes, then this
1675  // key may not be used for recording.
1676  if ((!overwrite) && (m_inputObjects.find(key) != m_inputObjects.end())) {
1677  ATH_MSG_ERROR("Object \"" << typeName << "\"/\"" << key
1678  << "\" already accessed from the input, can't be "
1679  "overwritten in memory");
1680  return StatusCode::FAILURE;
1681  }
1682 
1683  // Choose a split level.
1684  const Int_t splitLevel = (key.ends_with("Aux.") ? 1 : 0);
1685 
1686  // Check if we need to add it to the event record:
1687  Object_t::iterator vitr = m_outputObjects.find(key);
1688  if (vitr == m_outputObjects.end()) {
1689 
1690  // Check if we have a dictionary for this object:
1691  TClass* cl = TClass::GetClass(typeName.c_str());
1692  if (cl == nullptr) {
1693  ATH_MSG_ERROR("Didn't find dictionary for type: " << typeName);
1694  return StatusCode::FAILURE;
1695  }
1696 
1697  // Check if this is a new object "type" or not.
1698  if (!m_outputEventFormat->exists(key)) {
1700  EventFormatElement(key, cl->GetName(), "", getHash(key)));
1701  }
1702 
1703  // Let's create a holder for the object.
1704  const bool renewOnRead = (m_auxMode == kAthenaAccess);
1705  auto mgr = std::make_unique<TObjectManager>(
1706  nullptr, std::make_unique<THolder>(obj, cl, isOwner), renewOnRead);
1707  TObjectManager* mgrPtr = mgr.get();
1708  m_outputObjects[key] = std::move(mgr);
1709 
1710  // ... and let's add it to the output TTree.
1711  static constexpr Int_t basketSize = 32000;
1712  *(mgrPtr->branchPtr()) =
1713  m_outTree->Branch(key.c_str(), cl->GetName(),
1714  mgrPtr->holder()->getPtr(), basketSize, splitLevel);
1715  if (!mgrPtr->branch()) {
1716  ATH_MSG_ERROR("Failed to create branch \"" << key << "\" out of type \""
1717  << cl->GetName() << "\"");
1718  // Clean up:
1719  mgrPtr->holder()->setOwner(kFALSE);
1720  return StatusCode::FAILURE;
1721  }
1722 
1723  // Set up the saving of all the dynamic auxiliary properties
1724  // of the object if it has any:
1725  static constexpr bool METADATA = false;
1726  ATH_CHECK(putAux(*m_outTree, *mgrPtr, METADATA));
1727 
1728  // Return at this point, as we don't want to run the rest of
1729  // the function's code:
1730  return StatusCode::SUCCESS;
1731  }
1732 
1733  // Access the object manager:
1734  TObjectManager* omgr = dynamic_cast<TObjectManager*>(vitr->second.get());
1735  if (!omgr) {
1736  ATH_MSG_ERROR("Manager object of the wrong type encountered");
1737  return StatusCode::FAILURE;
1738  }
1739 
1740  // Check that the type of the object matches that of the previous
1741  // object:
1742  if (typeName != omgr->holder()->getClass()->GetName()) {
1743  // This may still be, when the ROOT dictionary name differs from the
1744  // "simple type name" known to C++. So let's get the ROOT name of the
1745  // new type:
1746  TClass* cl = TClass::GetClass(typeName.c_str());
1747  if ((!cl) ||
1748  ::strcmp(cl->GetName(), omgr->holder()->getClass()->GetName())) {
1749  ATH_MSG_ERROR("For output key \""
1750  << key << "\" the previous type was \""
1751  << omgr->holder()->getClass()->GetName()
1752  << "\", but the newly requested type is \"" << typeName
1753  << "\"");
1754  return StatusCode::FAILURE;
1755  }
1756  }
1757 
1758  // Replace the managed object.
1759  omgr->setObject(obj);
1760 
1761  // Replace the auxiliary objects.
1762  static constexpr bool METADATA = false;
1763  ATH_CHECK(putAux(*m_outTree, *omgr, METADATA));
1764 
1765  // Return gracefully.
1766  return StatusCode::SUCCESS;
1767 }
1768 
1770  bool metadata) {
1771 
1772  // Check if the auxiliary store is a generic object.
1773  Details::IObjectManager* iomgr = dynamic_cast<Details::IObjectManager*>(&mgr);
1774  if (iomgr != nullptr) {
1775  // Record the auxiliary object using the main record function.
1776  static const bool OVERWRITE = true;
1777  static const bool IS_OWNER = true;
1778  ATH_CHECK(record(iomgr->object(), iomgr->holder()->getClass()->GetName(),
1779  key, OVERWRITE, metadata, IS_OWNER));
1780  return StatusCode::SUCCESS;
1781  }
1782 
1783  // Check if it's a TAuxStore object.
1784  TAuxManager* auxmgr = dynamic_cast<TAuxManager*>(&mgr);
1785  if (auxmgr != nullptr) {
1786  // This type has to be an event object.
1787  if (metadata) {
1788  ATH_MSG_ERROR(
1789  "TAuxStore auxiliary objects can only be recorded for event data");
1790  return StatusCode::FAILURE;
1791  }
1792  // Record the auxiliary object with the dedicated record function.
1793  ATH_CHECK(recordAux(auxmgr->getStore(), key));
1794  return StatusCode::SUCCESS;
1795  }
1796 
1797  // Apparently we didn't recorgnize the auxiliary store type.
1798  ATH_MSG_ERROR("Unknown auxiliary store manager type encountered");
1799  return StatusCode::FAILURE;
1800 }
1801 
1809 
1810  // If we're dealing with an empty input file, stop here:
1811  if (m_inTreeMissing) {
1812  return StatusCode::SUCCESS;
1813  }
1814 
1815  // A little sanity check:
1816  if (!m_inTree) {
1817  ATH_MSG_ERROR("Function called on an uninitialised object");
1818  return StatusCode::FAILURE;
1819  }
1820 
1821  // Reset the number of input branches information:
1823 
1824  // Loop over the EventFormat information
1827  for (; itr != end; ++itr) {
1828 
1829  // Get the name of the branch in question:
1830  const std::string& branchName = itr->second.branchName();
1831 
1832  // If it's an auxiliary container, scan it using TAuxStore:
1833  if (branchName.find("Aux.") != std::string::npos) {
1834 
1835  // But first decide whether it describes a container, or just
1836  // a single object. Since the file may have been written in
1837  // kBranchAccess mode, it's not necessarily a good idea to check
1838  // the type of the auxiliary class. So let's check the interface
1839  // class instead.
1840  //
1841  // Get the name of the interface object/container:
1842  const std::string intName = branchName.substr(0, branchName.size() - 4);
1843  if (!m_inputEventFormat.exists(intName)) {
1844  // When this happens, it may still be that both the interface and
1845  // the auxiliary container is missing from the file. As we didn't
1846  // check yet whether the auxiliary container is in place or not.
1847  // So, before printing a warning, let's check for this.
1848  // Unfortunately the check is pretty expensive, but this should
1849  // not be performance critical code after all...
1850  ::Bool_t auxFound = kFALSE;
1851  const std::string dynName = Utils::dynBranchPrefix(branchName);
1852 
1853  std::vector<TObjArray*> fullListOfBranches = {};
1854  // Add the list of branches of the main tree
1855  fullListOfBranches.push_back(m_inTree->GetListOfBranches());
1856  // If input tree has friend trees
1857  // add as well the list of friend tree branches
1858  if (m_inTree->GetListOfFriends()) {
1859  // Get the list of friends
1860  TList* fList = m_inTree->GetListOfFriends();
1861  // Loop over friend elements
1862  for (TObject* feObj : *fList) {
1863  if (feObj) {
1864  // Get corresponding friend tree
1865  auto* pElement = dynamic_cast<TFriendElement*>(feObj);
1866  if (not pElement)
1867  continue;
1868  TTree* friendTree = pElement->GetTree();
1869  // Add list of branches of the friend tree
1870  fullListOfBranches.push_back(friendTree->GetListOfBranches());
1871  }
1872  }
1873  }
1874 
1875  for (TObjArray* branches : fullListOfBranches) {
1876  for (Int_t i = 0; i < branches->GetEntriesFast(); ++i) {
1877  if (!branches->At(i))
1878  continue;
1879 
1880  const TString name(branches->At(i)->GetName());
1881  if (name.BeginsWith(branchName) || name.BeginsWith(dynName)) {
1882  auxFound = kTRUE;
1883  break;
1884  }
1885  }
1886  }
1887  if (auxFound) {
1888  ATH_MSG_WARNING("Couldn't find interface object/container \""
1889  << intName << "\" belonging to branch \""
1890  << branchName << "\"");
1891  }
1892  continue;
1893  }
1894 
1895  // Get the type of the interface:
1896  const EventFormatElement* el = m_inputEventFormat.get(intName);
1897  ::TClass* cl = ::TClass::GetClass(el->className().c_str());
1898  if ((!cl) || (!cl->IsLoaded())) {
1899  ATH_MSG_WARNING("Couldn't find dictionary for type \""
1900  << el->className() << "\"");
1901  continue;
1902  }
1903 
1904  // Get the dictionary for the DataVector base class:
1905  static const std::type_info& baseTi = typeid(SG::AuxVectorBase);
1906  static const std::string baseName = SG::normalizedTypeinfoName(baseTi);
1907  static ::TClass* const baseCl = ::TClass::GetClass(baseName.c_str());
1908  if (!baseCl) {
1909  ATH_MSG_ERROR("Couldn't get dictionary for type \"" << baseName
1910  << "\"");
1911  return StatusCode::FAILURE;
1912  }
1913 
1914  // The type of the auxiliary store is finally deduced from the
1915  // inheritance of the interface container.
1917  (cl->InheritsFrom(baseCl) ? TAuxStore::EStructMode::kContainerStore
1919 
1920  // Scan the branches using a temporary TAuxStore instance:
1921  static constexpr bool TOP_STORE = true;
1922  TAuxStore temp(branchName, TOP_STORE, mode);
1923  static constexpr bool PRINT_WARNINGS = false;
1924  ATH_CHECK(temp.readFrom(*m_inTree, PRINT_WARNINGS));
1925 
1926  // Conveninence variable:
1928 
1929  // Teach the cache about all the branches:
1930  for (SG::auxid_t id : temp.getAuxIDs()) {
1931  stats.branch(branchName, id);
1932  }
1933 
1934  // Increment the number of known branches:
1935  stats.setBranchNum(stats.branchNum() + temp.getAuxIDs().size());
1936  }
1937  // If it's an interface container:
1938  else {
1939  // Try to access the branch:
1940  const ::TBranch* container = m_inTree->GetBranch(branchName.c_str());
1941  // If it exists, let's remember it:
1942  if (container) {
1943  IOStats::instance().stats().container(branchName);
1944  }
1945  }
1946  }
1947 
1948  // Return gracefully:
1949  return StatusCode::SUCCESS;
1950 }
1951 
1964 StatusCode TEvent::record(std::unique_ptr<TAuxStore> store,
1965  const std::string& key) {
1966 
1967  // Check if we have an output tree:
1968  if (!m_outTree) {
1969  ATH_MSG_ERROR(
1970  "No output tree defined. Did you forget to call writeTo(...)?");
1971  return StatusCode::FAILURE;
1972  }
1973 
1974  // Check if we have a filtering rule for this key:
1975  const std::set<std::string>* filter = 0;
1976  auto filter_itr = m_auxItemList.find(key);
1977  if (filter_itr != m_auxItemList.end()) {
1978  filter = &(filter_itr->second);
1979  }
1980 
1981  // Check if we need to add it to the event record:
1982  Object_t::iterator vitr = m_outputObjects.find(key);
1983  if (vitr == m_outputObjects.end()) {
1984 
1985  // Configure the object for variable filtering:
1986  if (filter) {
1987  store->selectAux(*filter);
1988  }
1989  // Tell the object where to write its contents:
1990  ATH_CHECK(store->writeTo(*m_outTree));
1991  // Record it to the output list:
1992  static constexpr bool OWNS_STORE = true;
1993  m_outputObjects[key] =
1994  std::make_unique<TAuxManager>(store.release(), OWNS_STORE);
1995 
1996  // We're done:
1997  return StatusCode::SUCCESS;
1998  }
1999 
2000  // Check if the output has the right store:
2001  if (vitr->second->object() == store.get()) {
2002  // We're done already:
2003  return StatusCode::SUCCESS;
2004  }
2005 
2006  // If not, update the output manager. This can happen when we copy
2007  // objects from the input to the output files, and we process
2008  // multiple input files.
2009 
2010  // Check if the output manager is of the right type:
2011  TAuxManager* mgr = dynamic_cast<TAuxManager*>(vitr->second.get());
2012  if (mgr == nullptr) {
2013  ATH_MSG_ERROR("Output object with key \""
2014  << key << "\" already exists, and is not of type TAuxStore");
2015  return StatusCode::FAILURE;
2016  }
2017 
2018  // Configure the object for variable filtering:
2019  if (filter) {
2020  store->selectAux(*filter);
2021  }
2022 
2023  // Connect the auxiliary store to the output tree:
2024  ATH_CHECK(store->writeTo(*m_outTree));
2025 
2026  // Update the manager:
2027  mgr->setObject(store.release());
2028 
2029  // Return gracefully:
2030  return StatusCode::SUCCESS;
2031 }
2032 
2042 
2043  // Check if we can call setName(...) on the object:
2044  ::TMethodCall setNameCall;
2045  // Don't use this code in Athena access mode. And just accept that access
2046  // monitoring is disabled in this case...
2047  if (m_auxMode != kAthenaAccess) {
2048  setNameCall.InitWithPrototype(mgr.holder()->getClass(), "setName",
2049  "const char*");
2050  if (setNameCall.IsValid()) {
2051  // Yes, there is such a function. Let's call it with the branch
2052  // name:
2053  const ::TString params =
2054  ::TString::Format("\"%s\"", mgr.branch()->GetName());
2055  const char* charParams = params.Data();
2056  setNameCall.Execute(mgr.holder()->get(), charParams);
2057  } else {
2058  // This is weird. What sort of auxiliary container is this? :-/
2059  ATH_MSG_WARNING("Couldn't find setName(...) function for container \""
2060  << mgr.branch()->GetName() << "\" (type: "
2061  << mgr.holder()->getClass()->GetName() << ")");
2062  }
2063  }
2064 
2065  // Check if we can switch out the internal store of this object:
2066  static const TClass* const holderClass =
2067  TClass::GetClass(typeid(SG::IAuxStoreHolder));
2068  if (!mgr.holder()->getClass()->InheritsFrom(holderClass)) {
2069  // Nope... So let's just end the journey here.
2070  return StatusCode::SUCCESS;
2071  }
2072 
2073  // Try to get the object as an IAuxStoreHolder:
2074  SG::IAuxStoreHolder* storeHolder = reinterpret_cast<SG::IAuxStoreHolder*>(
2075  mgr.holder()->getAs(typeid(SG::IAuxStoreHolder)));
2076  if (!storeHolder) {
2077  ATH_MSG_FATAL("There's a logic error in the code");
2078  return StatusCode::FAILURE;
2079  }
2080 
2081  // Create a TAuxStore instance that will read the dynamic variables
2082  // of this container. Notice that the TAuxManager doesn't own the
2083  // TAuxStore object. It will be owned by the SG::IAuxStoreHolder
2084  // object.
2085  static constexpr bool TOP_STORE = false;
2086  auto store = std::make_unique<TAuxStore>(
2087  mgr.branch()->GetName(), TOP_STORE,
2091  // This object is used to read data from the input, it needs to be
2092  // locked:
2093  store->lock();
2094 
2095  // Set it up to read from the input RNTuple.
2096  ATH_CHECK(store->readFrom(*tree));
2097 
2098  // Set it up to read from the input TTree.
2099  ATH_CHECK(store->readFrom(*tree));
2100  // Tell the auxiliary store which entry to use. This is essential for
2101  // metadata objects, and non-important for event data objects, which will
2102  // get a possibly different entry loaded in setAuxStore(...).
2103  store->getEntry(0);
2104 
2105  // Set up a manager for it.
2106  static constexpr bool SHARED_OWNER = false;
2107  m_inputObjects[std::string(mgr.branch()->GetName()) + "Dynamic"] =
2108  std::make_unique<TAuxManager>(store.get(), SHARED_OWNER);
2109 
2110  // Give this object to the store holder:
2111  storeHolder->setStore(store.release());
2112 
2113  // Return gracefully:
2114  return StatusCode::SUCCESS;
2115 }
2116 
2128  bool metadata) {
2129 
2130  // A little sanity check:
2131  assert(m_outputEventFormat != 0);
2132 
2133  // Do the conversion:
2134  TObjectManager* mgr = dynamic_cast<TObjectManager*>(&vmgr);
2135  if (!mgr) {
2136  // It's not an error any more when we don't get a TObjectManager.
2137  return StatusCode::SUCCESS;
2138  }
2139 
2140  // Check if we need to do anything here:
2141  if (!mgr->holder()->getClass()->InheritsFrom("SG::IAuxStoreIO")) {
2142  return StatusCode::SUCCESS;
2143  }
2144 
2145  // Get a pointer to the auxiliary store I/O interface:
2146  SG::IAuxStoreIO* aux = reinterpret_cast<SG::IAuxStoreIO*>(
2147  mgr->holder()->getAs(typeid(SG::IAuxStoreIO)));
2148  if (!aux) {
2149  ATH_MSG_FATAL("There is a logic error in the code!");
2150  return StatusCode::FAILURE;
2151  }
2152 
2153  // Check if we have rules defined for which auxiliary properties
2154  // to write out:
2156  if (!metadata) {
2157  auto item_itr = m_auxItemList.find(mgr->branch()->GetName());
2158  if (item_itr != m_auxItemList.end()) {
2159  sel.selectAux(item_itr->second);
2160  }
2161  }
2162 
2163  // Get the dynamic auxiliary variables held by this object, which
2164  // were selected to be written:
2165  const SG::auxid_set_t auxids =
2166  sel.getSelectedAuxIDs(aux->getSelectedAuxIDs());
2167 
2168  // If there are no dynamic auxiliary variables in the object, return
2169  // right away:
2170  if (auxids.empty()) {
2171  return StatusCode::SUCCESS;
2172  }
2173 
2174  // Decide what should be the prefix of all the dynamic branches:
2175  const std::string dynNamePrefix =
2176  Utils::dynBranchPrefix(mgr->branch()->GetName());
2177 
2178  // Select which container to add the variables to:
2180 
2181  // This iteration will determine the ordering of branches within
2182  // the tree, so sort auxids by name.
2184  typedef std::pair<std::string, SG::auxid_t> AuxVarSort_t;
2185  std::vector<AuxVarSort_t> varsort;
2186  varsort.reserve(auxids.size());
2187  for (SG::auxid_t id : auxids) {
2188  varsort.emplace_back(r.getName(id), id);
2189  }
2190  std::sort(varsort.begin(), varsort.end());
2191 
2192  // Extract all the dynamic variables from the object:
2193  for (const auto& p : varsort) {
2194 
2195  // The auxiliary ID:
2196  const SG::auxid_t id = p.second;
2197 
2198  // Construct a name for the branch that we will write:
2199  const std::string brName = dynNamePrefix + p.first;
2200 
2201  // Try to find the branch:
2202  Object_t::iterator bmgr = objects.find(brName);
2203 
2204  // Check if we already know about this variable:
2205  if (bmgr == objects.end()) {
2206 
2207  // Construct the full type name of the variable:
2208  const std::type_info* brType = aux->getIOType(id);
2209  if (!brType) {
2210  ATH_MSG_ERROR("No I/O type found for variable " << brName);
2211  return StatusCode::FAILURE;
2212  }
2213  const std::string brTypeName = Utils::getTypeName(*brType);
2214  std::string brProperTypeName = "<unknown>";
2215 
2216  // The branch that will hopefully be created:
2217  ::TBranch* br = 0;
2218 
2219  // Check if it's a primitive type or not:
2220  if (strlen(brType->name()) == 1) {
2221 
2222  // Making the "proper" type name is simple in this case:
2223  brProperTypeName = brTypeName;
2224 
2225  // Get the character describing this type for ROOT:
2226  const char rootType = Utils::rootType(brType->name()[0]);
2227  if (rootType == '\0') {
2228  ATH_MSG_ERROR("Type not known for variable \""
2229  << brName << "\" of type \"" << brTypeName << "\"");
2230  return StatusCode::FAILURE;
2231  }
2232 
2233  // Create the full description of the variable for ROOT:
2234  std::ostringstream leaflist;
2235  leaflist << brName << "/" << rootType;
2236 
2237  // Let's create a holder for this property:
2238  static constexpr bool IS_OWNER = false;
2239  auto auxmgr = std::make_unique<TPrimitiveAuxBranchManager>(
2240  id, nullptr, new THolder(aux->getIOData(id), nullptr, IS_OWNER));
2241 
2242  // ... and let's add it to the output TTree:
2243  static constexpr Int_t BASKET_SIZE = 32000;
2244  *(auxmgr->branchPtr()) =
2245  outTree.Branch(brName.c_str(), auxmgr->holder()->get(),
2246  leaflist.str().c_str(), BASKET_SIZE);
2247  if (!auxmgr->branch()) {
2248  ATH_MSG_ERROR("Failed to create branch \""
2249  << brName << "\" out of type \"" << brProperTypeName
2250  << "\"");
2251  // Clean up:
2252  *(auxmgr->holder()->getPtr()) = 0;
2253  return StatusCode::FAILURE;
2254  }
2255  br = auxmgr->branch();
2256 
2257  // Store it in the output list.
2258  objects[brName] = std::move(auxmgr);
2259 
2260  } else {
2261 
2262  // Check if we have a dictionary for this type:
2263  static constexpr Bool_t LOAD_IF_NOT_FOUND = kTRUE;
2264  static constexpr Bool_t SILENT = kTRUE;
2265  TClass* cl = TClass::GetClass(*brType, LOAD_IF_NOT_FOUND, SILENT);
2266  if (cl == nullptr) {
2267  // The dictionary needs to be loaded now. This could be an
2268  // issue. But let's hope for the best...
2269  cl = TClass::GetClass(brTypeName.c_str());
2270  // If still not found...
2271  if (cl == nullptr) {
2272  ATH_MSG_ERROR("Dictionary not available for variable \""
2273  << brName << "\" of type \"" << brTypeName << "\"");
2274  return StatusCode::FAILURE;
2275  }
2276  }
2277 
2278  // The proper type name comes from the dictionary in this case:
2279  brProperTypeName = cl->GetName();
2280 
2281  // Let's create a holder for this property:
2282  static constexpr bool IS_OWNER = false;
2283  auto auxmgr = std::make_unique<TAuxBranchManager>(
2284  id, nullptr, new THolder(aux->getIOData(id), cl, IS_OWNER));
2285 
2286  // ... and let's add it to the output TTree.
2287  static constexpr Int_t BASKET_SIZE = 32000;
2288  static constexpr Int_t SPLIT_LEVEL = 0;
2289  *(auxmgr->branchPtr()) = outTree.Branch(brName.c_str(), cl->GetName(),
2290  auxmgr->holder()->getPtr(),
2291  BASKET_SIZE, SPLIT_LEVEL);
2292  if (!auxmgr->branch()) {
2293  ATH_MSG_ERROR("Failed to create branch \""
2294  << brName << "\" out of type \"" << brProperTypeName
2295  << "\"");
2296  // Clean up:
2297  *(auxmgr->holder()->getPtr()) = 0;
2298  return StatusCode::FAILURE;
2299  }
2300  br = auxmgr->branch();
2301 
2302  // Store it in the output list.
2303  objects[brName] = std::move(auxmgr);
2304  }
2305 
2306  // If this is not the first event, fill up the already filled
2307  // events with (empty) content:
2308  if (outTree.GetEntries()) {
2309  void* ptr = br->GetAddress();
2310  br->SetAddress(0);
2311  for (::Long64_t i = 0; i < outTree.GetEntries(); ++i) {
2312  br->Fill();
2313  }
2314  br->SetAddress(ptr);
2315  }
2316 
2317  // If all went fine, let's add this branch to the event format
2318  // metadata:
2320  m_outputEventFormat->add(EventFormatElement(brName, brProperTypeName,
2321  mgr->branch()->GetName(),
2322  getHash(brName)));
2323  }
2324 
2325  // We don't need to do the rest:
2326  continue;
2327  }
2328 
2329  // Access the object manager:
2330  bmgr = objects.find(brName);
2331  if (bmgr == objects.end()) {
2332  ATH_MSG_FATAL("There is an internal logic error in the code...");
2333  return StatusCode::FAILURE;
2334  }
2335 
2336  // Replace the managed object:
2337  void* nc_data ATLAS_THREAD_SAFE = // we hold non-const pointers but check
2338  // on retrieve
2339  const_cast<void*>(static_cast<const void*>(aux->getIOData(id)));
2340  bmgr->second->setObject(nc_data);
2341  }
2342 
2343  // Return gracefully:
2344  return StatusCode::SUCCESS;
2345 }
2346 
2348 
2349  // Check if we have an output tree:
2350  if (hasOutput() == false) {
2351  ATH_MSG_ERROR("No output tree set up.");
2352  return StatusCode::FAILURE;
2353  }
2354 
2355  // Check if we have a filtering rule for this key:
2356  const std::set<std::string>* filter = 0;
2357  auto filter_itr = m_auxItemList.find(key);
2358  if (filter_itr != m_auxItemList.end()) {
2359  filter = &(filter_itr->second);
2360  }
2361 
2362  // Check if we need to add it to the event record:
2363  Object_t::iterator vitr = m_outputObjects.find(key);
2364  if (vitr == m_outputObjects.end()) {
2365 
2366  // Configure the object for variable filtering:
2367  if (filter) {
2368  store->selectAux(*filter);
2369  }
2370  // Tell the object where to write its contents:
2371  ATH_CHECK(store->writeTo(*m_outTree));
2372  // Record it to the output list.
2373  static constexpr bool OWNS_STORE = false;
2374  m_outputObjects[key] = std::make_unique<TAuxManager>(store, OWNS_STORE);
2375 
2376  // We're done:
2377  return StatusCode::SUCCESS;
2378  }
2379 
2380  // Check if the output has the right store:
2381  if (vitr->second->object() == store) {
2382  // We're done already:
2383  return StatusCode::SUCCESS;
2384  }
2385 
2386  // If not, update the output manager. This can happen when we copy
2387  // objects from the input to the output files, and we process
2388  // multiple input files.
2389 
2390  // Check if the output manager is of the right type:
2391  TAuxManager* mgr = dynamic_cast<TAuxManager*>(vitr->second.get());
2392  if (mgr == nullptr) {
2393  ATH_MSG_ERROR("Output object with key \""
2394  << key << "\" already exists, and is not of type TAuxStore");
2395  return StatusCode::FAILURE;
2396  }
2397 
2398  // Configure the object for variable filtering:
2399  if (filter) {
2400  store->selectAux(*filter);
2401  }
2402 
2403  // Connect the auxiliary store to the output tree:
2404  ATH_CHECK(store->writeTo(*m_outTree));
2405 
2406  // Update the manager:
2407  mgr->setObject(store);
2408 
2409  // Return gracefully:
2410  return StatusCode::SUCCESS;
2411 }
2412 
2413 } // namespace xAOD
xAOD::TEvent::m_inTreeNumber
::Int_t m_inTreeNumber
The number of the currently open tree in the input chain.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:202
xAOD::TEvent::m_inTreeMissing
bool m_inTreeMissing
Internal status flag showing that an input file is open, but it doesn't contain an event tree.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:196
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
xAOD::Event::keys
StatusCode keys(std::vector< std::string > &vkeys, bool metadata) const
Provide a list of all data object keys associated with a specific type.
xAOD::EventFormat_v1::end
const_iterator end() const
STL-like function for getting the end of the container.
Definition: EventFormat_v1.cxx:163
xAOD::TEvent::finishWritingTo
StatusCode finishWritingTo(::TFile *file)
Finish writing to an output file.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:447
SGTest::store
TestStore store
Definition: TestStore.cxx:23
beamspotman.r
def r
Definition: beamspotman.py:672
CurrentEventStore.h
Hold a pointer to the current event store.
xAOD::EventFormat_v1::get
const EventFormatElement * get(const std::string &key, bool quiet=false) const
Get the description of a given branch.
Definition: EventFormat_v1.cxx:91
xAOD::THolder::AUXELEMENT
@ AUXELEMENT
A type inheriting from SG::AuxElement.
Definition: THolder.h:106
ClassName.h
Recursively separate out template arguments in a C++ class name.
ATH_MSG_FATAL
#define ATH_MSG_FATAL(x)
Definition: AthMsgStreamMacros.h:34
xAOD::TEvent::m_inChainTracker
std::unique_ptr< TChainStateTracker > m_inChainTracker
Optional object for tracking the state changes of an input TChain.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:200
xAOD::TEvent::TEvent
TEvent(EAuxMode mode=kClassAccess)
Default constructor.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:77
xAOD::Event::ATLAS_THREAD_SAFE
SG::SGKeyMap< BranchInfo > m_branches ATLAS_THREAD_SAFE
Map from hashed sgkey to BranchInfo.
Definition: Event.h:358
xAOD::TEvent::m_auxMode
EAuxMode m_auxMode
The auxiliary access mode.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:190
TEventFormatRegistry.h
IAuxStoreHolder.h
checkxAOD.brName
brName
Definition: Tools/PyUtils/bin/checkxAOD.py:125
get_generator_info.result
result
Definition: get_generator_info.py:21
SG::IAuxStoreHolder::getStoreType
virtual AuxStoreType getStoreType() const =0
Return the type of the store object.
TPrimitiveAuxBranchManager.h
LArConditions2Ntuple.objects
objects
Definition: LArConditions2Ntuple.py:64
vtune_athena.format
format
Definition: vtune_athena.py:14
ATH_MSG_INFO
#define ATH_MSG_INFO(x)
Definition: AthMsgStreamMacros.h:31
xAOD::IOStats::stats
ReadStats & stats()
Access the object belonging to the current thread.
Definition: IOStats.cxx:17
L1CaloPhase1Monitoring.standalone
standalone
Definition: L1CaloPhase1Monitoring.py:139
xAOD::Event::name
const std::string & name() const override
Get the name of the instance.
Definition: EventIProxyDict.cxx:315
xAOD::TAuxManager::getStore
TAuxStore * getStore()
Get a type-specific pointer to the managed object.
Definition: TAuxManager.cxx:100
xAOD::TEvent::record
StatusCode record(void *obj, const std::string &typeName, const std::string &key, bool overwrite, bool metadata, bool isOwner) override
Record an object into a connected output file.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1638
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:640
xAOD::details::AuxStoreBase::getAuxIDs
virtual const SG::auxid_set_t & getAuxIDs() const override
Get the types(names) of variables handled by this container.
Definition: AuxStoreBase.cxx:106
TAuxBranchManager.h
xAOD::THolder::setOwner
void setOwner(::Bool_t state=kTRUE)
Set whether the holder should own its object.
Definition: THolder.cxx:257
xAOD::Event::m_inputObjects
Object_t m_inputObjects
Collection of all the managed input objects.
Definition: Event.h:308
SG::normalizedTypeinfoName
std::string normalizedTypeinfoName(const std::type_info &info)
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
Definition: normalizedTypeinfoName.cxx:120
xAOD::Event::m_outputMetaObjects
Object_t m_outputMetaObjects
Collection of all the managed output meta-objects.
Definition: Event.h:318
xAOD::Event::m_inputEventFormat
EventFormat m_inputEventFormat
Format of the current input file.
Definition: Event.h:321
SG::AuxElement
Base class for elements of a container that can have aux data.
Definition: AuxElement.h:483
xAOD::THolder::DATAVECTOR
@ DATAVECTOR
A DataVector container.
Definition: THolder.h:105
xAOD::THolder::getAs
virtual void * getAs(const std::type_info &tid, ::Bool_t silent=kFALSE) const
Return the object as a specific pointer.
Definition: THolder.cxx:370
xAOD::THolder
This class takes care of holding EDM objects in memory.
Definition: THolder.h:35
xAOD::TEvent::kAthenaAccess
@ kAthenaAccess
Access containers/objects like Athena does.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:72
StateLessPT_NewConfig.Format
Format
Definition: StateLessPT_NewConfig.py:149
xAOD::Details::IObjectManager::holder
const THolder * holder() const
Accessor to the Holder object.
Definition: IObjectManager.cxx:43
xAOD::Event::setActive
void setActive() const
Set this event object as the currently active one.
Definition: EventCore.cxx:54
xAOD::TEvent::getFile
::Int_t getFile(::Long64_t file, ::Int_t getall=0)
Load the first event for a given file from the input TChain.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:780
xAOD::TEvent::m_inChain
::TChain * m_inChain
The (optional) chain provided as input.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:198
tree
TChain * tree
Definition: tile_monitor.h:30
xAOD::TVirtualManager::getEntry
virtual ::Int_t getEntry(::Int_t getall=0)=0
Function for updating the object in memory if needed.
xAOD::TEvent::getNames
StatusCode getNames(const std::string &targetClassName, std::vector< std::string > &vkeys, bool metadata) const override
Function determining the list keys associated with a type name.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:903
xAOD::details::AuxStoreBase::EStructMode
EStructMode
"Structural" modes of the object
Definition: AuxStoreBase.h:30
xAOD::THolder::getPtr
void ** getPtr()
Return a typeless pointer to the held object's pointer.
Definition: THolder.cxx:225
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:70
xAOD::TDirectoryReset
Helper class for making sure the current directory is preserved.
Definition: TDirectoryReset.h:28
downloadSingle.dataType
string dataType
Definition: downloadSingle.py:18
TChainStateTracker.h
xAOD::TEvent::hasInput
bool hasInput() const override
Check if an input file is connected to the object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:893
xAOD::TAuxManager::getConstStore
const SG::IConstAuxStore * getConstStore() const
Get a convenience pointer to the managed object.
Definition: TAuxManager.cxx:105
xAOD::TAuxStore
"ROOT @c TTree implementation" of IAuxStore
Definition: TAuxStore.h:30
xAOD::TObjectManager::branchPtr
::TBranch ** branchPtr()
Pointer to the branch's pointer.
Definition: TObjectManager.cxx:62
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
xAOD::ReadStats::container
BranchStats * container(const std::string &name)
Access the description of a container. Creating it if necessary.
xAOD::TVirtualIncidentListener
Class providing an interface for classes listening to xAOD incidents.
Definition: TVirtualIncidentListener.h:25
xAOD::EventFormatElement
Class describing one branch of the ROOT file.
Definition: EventFormatElement.h:35
XAOD_MESSAGE
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
Definition: Control/xAODRootAccess/xAODRootAccess/tools/Message.h:19
vec
std::vector< size_t > vec
Definition: CombinationsGeneratorTest.cxx:9
xAOD::TEvent::~TEvent
virtual ~TEvent()
Destructor.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:91
python.TurnDataReader.dr
dr
Definition: TurnDataReader.py:111
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
Utils.h
xAOD::TVirtualManager
Interface class for the "manager classes".
Definition: TVirtualManager.h:24
ATH_MSG_VERBOSE
#define ATH_MSG_VERBOSE(x)
Definition: AthMsgStreamMacros.h:28
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
IOStats.h
xAOD::TEvent::kClassAccess
@ kClassAccess
Access auxiliary data using the aux containers.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:71
TVirtualIncidentListener.h
TDirectoryReset.h
SG::IAuxStoreIO::getIOType
virtual const std::type_info * getIOType(SG::auxid_t auxid) const =0
Return the type of the data to be stored for one aux data item.
trigbs_dumpHLTContentInBS.stats
stats
Definition: trigbs_dumpHLTContentInBS.py:91
xAOD::details::AuxStoreBase::EStructMode::kObjectStore
@ kObjectStore
The object describes a single object.
xAOD::details::AuxStoreBase::structMode
EStructMode structMode() const
Get what structure mode the object was constructed with.
Definition: AuxStoreBase.cxx:29
xAOD::Event::m_listeners
std::vector< TVirtualIncidentListener * > m_listeners
Listeners who should be notified when certain incidents happen.
Definition: Event.h:329
PerfStats.h
ReturnCheck.h
AuxVectorBase.h
Manage index tracking and synchronization of auxiliary data.
xAOD::details::AuxStoreBase::EStructMode::kContainerStore
@ kContainerStore
The object describes an entire container.
SG::AuxVectorBase
Manage index tracking and synchronization of auxiliary data.
Definition: AuxVectorBase.h:98
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
xAOD::TEvent::m_inMetaTree
::TTree * m_inMetaTree
Pointer to the metadata tree in the input file.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:204
xAOD::TEvent::connectAux
StatusCode connectAux(const std::string &prefix, bool standalone) override
Function setting up access to a set of auxiliary branches.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1329
xAOD::Event::Object_t
std::unordered_map< std::string, std::unique_ptr< TVirtualManager > > Object_t
Definition of the internal data structure type.
Definition: Event.h:305
xAOD::Event::m_inputMetaObjects
Object_t m_inputMetaObjects
Collection of all the managed input meta-objects.
Definition: Event.h:316
SG::IAuxStoreIO
Interface providing I/O for a generic auxiliary store.
Definition: IAuxStoreIO.h:44
xAOD::Utils::dynBranchPrefix
std::string dynBranchPrefix(const std::string &key)
This function is used to figure out what to name dynamic auxiliary branches coming from a container c...
Definition: Control/xAODRootAccess/Root/Utils.cxx:144
AthenaPoolTestRead.sc
sc
Definition: AthenaPoolTestRead.py:27
mergePhysValFiles.end
end
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:92
xAOD::ReadStats::nextEvent
void nextEvent()
Function incrementing the processed event counter.
xAOD::THolder::getClass
const ::TClass * getClass() const
Definition: THolder.cxx:401
xAOD::TEvent::hasOutput
bool hasOutput() const override
Check if an output file is connected to the object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:898
xAOD::TEvent::connectMetaAux
StatusCode connectMetaAux(const std::string &prefix, bool standalone) override
Function setting up access to a set of auxiliary branches for a metadata object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1401
covarianceTool.filter
filter
Definition: covarianceTool.py:514
SG::AuxTypeRegistry
Handle mappings between names and auxid_t.
Definition: AuxTypeRegistry.h:61
xAOD::TEvent::auxMode
EAuxMode auxMode() const
Get what auxiliary access mode the object was constructed with.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:108
python.checkMetadata.metadata
metadata
Definition: checkMetadata.py:175
BchCleanup.mgr
mgr
Definition: BchCleanup.py:294
runLayerRecalibration.branches
list branches
Definition: runLayerRecalibration.py:98
SG::IAuxStoreHolder::AuxStoreType
AuxStoreType
Type of the auxiliary store.
Definition: IAuxStoreHolder.h:66
SG::auxid_t
size_t auxid_t
Identifier for a particular aux data item.
Definition: AuxTypes.h:27
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
CxxUtils::ConcurrentBitset::size
bit_t size() const
Count the number of 1 bits in the set.
TFileAccessTracer.h
xAOD::details::AuxStoreBase::setStructMode
void setStructMode(EStructMode mode)
Set the structure mode of the object to a new value.
Definition: AuxStoreBase.cxx:34
xAOD::EventFormat_v1::begin
const_iterator begin() const
STL-like function for getting the beginning of the container.
Definition: EventFormat_v1.cxx:158
ATH_MSG_ERROR
#define ATH_MSG_ERROR(x)
Definition: AthMsgStreamMacros.h:33
ReadStats.h
xAOD::Event::m_auxItemList
std::unordered_map< std::string, std::set< std::string > > m_auxItemList
Rules for selecting which auxiliary branches to write.
Definition: Event.h:326
TAuxStore.h
xAOD::TEvent::m_inTree
::TTree * m_inTree
The main tree that we are reading from.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:193
xAOD::Utils::getTypeName
std::string getTypeName(const std::type_info &ti)
This function is necessary in order to create type names that ROOT can understand.
Definition: Control/xAODRootAccess/Root/Utils.cxx:354
lumiFormat.i
int i
Definition: lumiFormat.py:85
SG::AuxElement::setStore
void setStore(const SG::IConstAuxStore *store)
Set the store associated with this object.
Definition: AuxElement.cxx:241
xAOD::TAuxStore::readFrom
StatusCode readFrom(::TTree &tree, bool printWarnings=true)
Connect the object to an input TTree.
Definition: TAuxStore.cxx:864
xAOD::TEvent::getEntries
::Long64_t getEntries() const
Get how many entries are available from the current input file(s)
Definition: Control/xAODRootAccess/Root/TEvent.cxx:621
IAuxStoreIO.h
Interface providing I/O for a generic auxiliary store.
xAOD::e
setPy e
Definition: CompositeParticle_v1.cxx:166
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
xAOD::TEvent::getEntry
::Int_t getEntry(::Long64_t entry, ::Int_t getall=0)
Function loading a given entry of the input TTree.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:650
Message.h
CaloNoise_fillDB.dt
dt
Definition: CaloNoise_fillDB.py:56
xAOD::TIncident
Class describing a certain "incident" that is communicated to user code.
Definition: TIncident.h:58
sel
sel
Definition: SUSYToolsTester.cxx:92
SG::IAuxStoreIO::getSelectedAuxIDs
virtual SG::auxid_set_t getSelectedAuxIDs() const
Get a list of dynamic variables that need to be written out.
Definition: IAuxStoreIO.h:86
generateReferenceFile.files
files
Definition: generateReferenceFile.py:12
xAOD::Event::m_branchesMutex
upgrade_mutex_t m_branchesMutex
Mutex for multithread synchronization.
Definition: Event.h:354
TEvent.h
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
file
TFile * file
Definition: tile_monitor.h:29
dumpFileToPlots.treeName
string treeName
Definition: dumpFileToPlots.py:19
xAOD::Details::isStandalone
bool isStandalone(const TClass &cl)
Helper function deciding if a given type "is a standalone object".
Definition: IOUtils.cxx:65
ATH_CHECK
#define ATH_CHECK
Definition: AthCheckMacros.h:40
xAOD::ReadStats::setBranchNum
void setBranchNum(::Int_t num)
Set the total number of branches on the input.
Preparation.mode
mode
Definition: Preparation.py:107
python.getProblemFolderFromLogs.el
dictionary el
Definition: getProblemFolderFromLogs.py:48
CxxUtils::ConcurrentBitset::empty
bool empty() const
Return true if there are no 1 bits in the set.
xAOD::TEventFormatRegistry::instance
static const TEventFormatRegistry & instance()
Access the only instance of the object in memory.
Definition: TEventFormatRegistry.cxx:14
plotmaker.keyName
keyName
Definition: plotmaker.py:145
xAOD::IOStats::instance
static IOStats & instance()
Singleton object accessor.
Definition: IOStats.cxx:11
xAOD::Event::getInputObject
const void * getInputObject(SG::sgkey_t key, const std::type_info &ti, bool silent) override
Function for retrieving an input object in a non-template way.
Definition: EventTVirtualEvent.cxx:162
normalizedTypeinfoName.h
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
xAOD::TEvent::EVENT_TREE_NAME
static const char *const EVENT_TREE_NAME
Default name of the event tree.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:91
TObjectManager.h
SG::IAuxStoreHolder::setStore
virtual void setStore(IAuxStore *store)=0
Give an auxiliary store object to the holder object.
xAOD::TEvent::m_outTree
std::unique_ptr<::TTree > m_outTree
The tree that we are writing to.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:209
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
xAOD::Event::m_inputMissingObjects
std::set< std::string > m_inputMissingObjects
Objects that have been asked for, but were found to be missing in the current input.
Definition: Event.h:311
xAOD::AuxSelection
Class helping in dealing with dynamic branch selection.
Definition: AuxSelection.h:31
TAuxManager.h
xAOD::Event::m_outputObjects
Object_t m_outputObjects
Collection of all the managed output object.
Definition: Event.h:313
TActiveEvent.h
xAOD::EventFormat_v1
Event format metadata for xAOD files.
Definition: EventFormat_v1.h:38
IOUtils.h
xAOD::TEvent::readFrom
StatusCode readFrom(::TFile *file, bool useTreeCache=true, std::string_view treeName=EVENT_TREE_NAME)
Connect the object to a new input file.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:122
xAOD::ReadStats::readContainer
void readContainer(const std::string &name)
Function incrementing the read counter on a specific container.
xAOD::TFileAccessTracer
Helper class keeping track of the files that got accessed.
Definition: TFileAccessTracer.h:46
xAOD::TEvent::initStats
StatusCode initStats()
Function to initialise the statistics for all Tree content.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1808
xAOD::TObjectManager
Manager for EDM objects created by ROOT.
Definition: TObjectManager.h:29
SG::IAuxStoreIO::getIOData
virtual const void * getIOData(SG::auxid_t auxid) const =0
Return a pointer to the data to be stored for one aux data item.
xAOD::TAuxManager
Manager for TAuxStore objects.
Definition: TAuxManager.h:33
xAOD::TEvent::fill
::Int_t fill()
Function filling one event into the output tree.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:814
xAOD::TEventFormatRegistry::getEventFormat
EventFormat & getEventFormat(const TFile *file) const
Access the managed EventFormat object.
Definition: TEventFormatRegistry.cxx:20
xAOD::TObjectManager::getEntry
virtual ::Int_t getEntry(::Int_t getall=0) override
Function for updating the object in memory if needed.
Definition: TObjectManager.cxx:74
SG::IAuxStore
Interface for non-const operations on an auxiliary store.
Definition: IAuxStore.h:48
xAOD::TEvent::putAux
StatusCode putAux(::TTree &outTree, TVirtualManager &mgr, bool metadata)
Function saving the dynamically created auxiliary properties.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:2127
AuxSelection.h
xAOD::TEvent::setUpDynamicStore
StatusCode setUpDynamicStore(TObjectManager &mgr, ::TTree *tree)
Function adding dynamic variable reading capabilities to an auxiliary store object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:2041
xAOD::TEvent::EAuxMode
EAuxMode
Auxiliary store "mode".
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:69
xAOD::TEvent::getFiles
::Long64_t getFiles() const
Get how many files are available on the currently defined input.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:760
CxxUtils::ClassName::ExcBadClassName
Exception to signal a malformed class name.
Definition: CxxUtils/CxxUtils/ClassName.h:109
xAOD::Event::m_outputEventFormat
EventFormat * m_outputEventFormat
Format of the current output file.
Definition: Event.h:323
python.trfDecorators.silent
def silent(func)
Redirect stdout/err to /dev/null Useful wrapper to get rid of ROOT verbosity...
Definition: trfDecorators.py:24
ATH_MSG_WARNING
#define ATH_MSG_WARNING(x)
Definition: AthMsgStreamMacros.h:32
xAOD::Utils::getFirstBranchMatch
std::string getFirstBranchMatch(TTree *tree, const std::string &pre)
This function is used to search for a branch in a TTree that contains a given substring.
Definition: Control/xAODRootAccess/Root/Utils.cxx:394
xAOD::TEvent::m_entry
::Long64_t m_entry
The entry to look at from the input tree.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:206
xAOD::TEvent::connectMetaObject
StatusCode connectMetaObject(const std::string &key, bool silent) override
Function setting up access to a particular metadata object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1228
THolder.h
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
xAOD::TEvent::recordAux
SG::IAuxStore * recordAux(const std::string &key, SG::IAuxStoreHolder::AuxStoreType type=SG::IAuxStoreHolder::AST_ContainerStore)
Add an auxiliary store object to the output.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:562
xAOD::TVirtualManager::object
virtual const void * object() const =0
Function getting a const pointer to the object being handled.
xAOD::TEvent::setAuxStore
StatusCode setAuxStore(const std::string &key, Details::IObjectManager &mgr, bool metadata) override
Function connecting a DV object to its auxiliary store.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1465
xAOD::details::AuxStoreBase::EStructMode::kUndefinedStore
@ kUndefinedStore
The structure mode is not defined.
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
xAOD::Event::getHash
SG::sgkey_t getHash(const std::string &key) const override
Function returning the hash describing an object name.
Definition: EventTVirtualEvent.cxx:27
SG::auxid_set_t
A set of aux data identifiers.
Definition: AuxTypes.h:47
AthContainers_detail::upgrading_lock
Lock object for taking out upgradable locks.
Definition: threading.h:177
xAOD::Details::hasAuxStore
bool hasAuxStore(const TClass &cl)
Helper function deciding if a given type "has an auxiliary store".
Definition: IOUtils.cxx:40
merge.status
status
Definition: merge.py:16
xAOD::EventFormat_v1::const_iterator
KeyedData_t::const_iterator const_iterator
Iterator for looping over the elements of the object.
Definition: EventFormat_v1.h:67
xAOD::TEvent::kBranchAccess
@ kBranchAccess
Access auxiliary data branch-by-branch.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:70
no_sanitize_undefined.h
Helper to disable undefined behavior sanitizer for a function.
xAOD::TEvent::connectObject
StatusCode connectObject(const std::string &key, bool silent) override
Function setting up access to a particular object.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:1059
PowhegControl_ttFCNC_NLO.params
params
Definition: PowhegControl_ttFCNC_NLO.py:226
xAOD::TObjectManager::branch
::TBranch * branch()
Accessor to the branch.
Definition: TObjectManager.cxx:51
xAOD::EventFormat_v1::add
void add(const EventFormatElement &element, bool updatePersistent=true)
Add the description of a new branch.
Definition: EventFormat_v1.cxx:43
xAOD::Details::IObjectManager
Manager for EDM objects created by ROOT.
Definition: IObjectManager.h:20
xAOD::ReadStats
Class describing the access statistics of a collection of branches.
Definition: ReadStats.h:123
xAOD::Event
Base class for the event (xAOD::TEvent and xAOD::REvent) classes.
Definition: Event.h:59
SG::IConstAuxStore
Interface for const operations on an auxiliary store.
Definition: IConstAuxStore.h:64
python.PyAthena.obj
obj
Definition: PyAthena.py:132
SG::IAuxStoreHolder::AST_ObjectStore
@ AST_ObjectStore
The store describes a single object.
Definition: IAuxStoreHolder.h:67
SG::IAuxStoreHolder
Interface for objects taking part in direct ROOT I/O.
Definition: IAuxStoreHolder.h:36
xAOD::TObjectManager::setObject
virtual void setObject(void *obj) override
Function replacing the object being handled.
Definition: TObjectManager.cxx:162
TIncident.h
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:25
LArL1Calo_ComputeHVCorr.className
className
Definition: LArL1Calo_ComputeHVCorr.py:135
xAOD::Utils::rootType
char rootType(char typeidType)
This function is used internally in the code when creating primitive dynamic auxiliary branches.
Definition: Control/xAODRootAccess/Root/Utils.cxx:295
TActiveStore.h
LheEventFiller_Common.ef
ef
Definition: SFGen_i/share/common/LheEventFiller_Common.py:7
TStore.h
xAOD::TEvent
Tool for accessing xAOD files outside of Athena.
Definition: Control/xAODRootAccess/xAODRootAccess/TEvent.h:57
xAOD::TEvent::writeTo
StatusCode writeTo(::TFile *file, int autoFlush=200, std::string_view treeName=EVENT_TREE_NAME)
Connect the object to an output file.
Definition: Control/xAODRootAccess/Root/TEvent.cxx:408
xAOD::EventFormat_v1::exists
bool exists(const std::string &key) const
Check if a description exists about a given branch.
Definition: EventFormat_v1.cxx:65
AuxElement.h
Base class for elements of a container that can have aux data.
PlotCalibFromCool.br
br
Definition: PlotCalibFromCool.py:355
SG::IAuxStoreHolder::AST_ContainerStore
@ AST_ContainerStore
The store describes a container.
Definition: IAuxStoreHolder.h:68
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
xAOD::Details::isAuxStore
bool isAuxStore(const TClass &cl)
Helper function deciding if a given type "is an auxiliary store".
Definition: IOUtils.cxx:53
DataProxy.h