ATLAS Offline Software
REvent.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 // System include(s):
4 #include <cassert>
5 #include <sstream>
6 #include <iomanip>
7 #include <cstring>
8 
9 // ROOT include(s):
10 #include <TFile.h>
11 #include <TTree.h>
12 #include <TKey.h>
13 #include <TChain.h>
14 #include <TFriendElement.h>
15 #include <TChainElement.h>
16 #include <TBranch.h>
17 #include <TError.h>
18 #include <TMethodCall.h>
19 #include <TSystem.h>
20 
21 // Gaudi/Athena include(s):
28 #ifndef XAOD_STANDALONE
30 # include "SGTools/DataProxy.h"
31 #endif // not XAOD_STANDALONE
33 
34 // Interface include(s):
36 
37 // xAOD include(s):
38 #include "xAODCore/tools/IOStats.h"
41 #include "xAODCore/AuxSelection.h"
42 
43 // Local include(s):
44 #include "xAODRootAccess/REvent.h"
48 #include "xAODRootAccess/TStore.h"
64 
65 namespace {
66 
72  void removeVersionNames( std::string& name ) {
73 
74  size_t pos = 0;
75  while( ( pos = name.find( "_v1" ) ) != name.npos ) {
76  name.erase( pos, 3 );
77  }
78  while( ( pos = name.find( "_v2" ) ) != name.npos ) {
79  name.erase( pos, 3 );
80  }
81  while( ( pos = name.find( "_v3" ) ) != name.npos ) {
82  name.erase( pos, 3 );
83  }
84  while( ( pos = name.find( "_v4" ) ) != name.npos ) {
85  name.erase( pos, 3 );
86  }
87  while( ( pos = name.find( "_v5" ) ) != name.npos ) {
88  name.erase( pos, 3 );
89  }
90  while( ( pos = name.find( "_v6" ) ) != name.npos ) {
91  name.erase( pos, 3 );
92  }
93  while( ( pos = name.find( "_v7" ) ) != name.npos ) {
94  name.erase( pos, 3 );
95  }
96  while( ( pos = name.find( "_v8" ) ) != name.npos ) {
97  name.erase( pos, 3 );
98  }
99 
100  return;
101  }
102 
105  class ForceTrackIndices : public SG::AuxVectorBase {
106  public:
108  }; // class ForceTrackIndices
109 
111  void forceTrackIndices NO_SANITIZE_UNDEFINED ( SG::AuxVectorBase& vec ) {
112  // Treat the received object like it would be of type @c ForceTrackIndices
113  ForceTrackIndices& xvec = static_cast< ForceTrackIndices& >( vec );
114  xvec.initAuxVectorBase< DataVector< SG::IAuxElement > >( SG::OWN_ELEMENTS,
116  return;
117  }
118 
119 } // private namespace
120 
121 namespace xAOD {
122 
123  namespace Experimental {
124 
125  //
126  // Initialise the static data:
127  //
128  const ::Int_t REvent::CACHE_SIZE = -1;
129  const char* const REvent::EVENT_RNTUPLE_NAME = "EventData";
130  const char* const REvent::METADATA_TREE_NAME = "MetaData";
131 
133  static const REvent::EAuxMode DEFAULT_ACCESS_MODE = REvent::kClassAccess;
135  static const REvent::EAuxMode UNIT_TEST_ACCESS_MODE = REvent::kAthenaAccess;
136 
138  : m_auxMode( mode ),
139  m_inNtupleReader( nullptr ), m_inMetaTree( nullptr ), m_inMetaTreeIsTTree( true ),
140  m_entry( -1 ), m_outTree( nullptr ),
141  m_inputObjects(), m_inputMissingObjects(), m_outputObjects(),
142  m_inputMetaObjects(), m_outputMetaObjects(),
143  m_inputEventFormat(), m_outputEventFormat( nullptr ),
144  m_auxItemList(), m_listeners(), m_nameRemapping() {
145 
146  // Make sure that the I/O monitoring is active:
148 
149  // Make this the active event:
150  setActive();
151 
152  // If the user didn't ask for one particular access type, chose one
153  // based on the running environment:
154  if( m_auxMode == kUndefinedAccess ) {
155  if( gSystem->Getenv( "ROOTCORE_AUTO_UT" ) ||
156  gSystem->Getenv( "ROOTCORE_FAST_UT" ) ||
157  gSystem->Getenv( "ROOTCORE_SLOW_UT" ) ) {
158  ::Info( "xAOD::REvent::REvent",
159  "Using access mode \"%i\" for the unit test",
160  static_cast< int >( UNIT_TEST_ACCESS_MODE ) );
161  m_auxMode = UNIT_TEST_ACCESS_MODE;
162  } else {
163  m_auxMode = DEFAULT_ACCESS_MODE;
164  }
165  }
166  }
167 
169 
170  // ::Info( "xAOD::REvent::~REvent", "Entering");
171 
172 
173  Object_t::iterator itr = m_inputObjects.begin();
175  for( ; itr != end; ++itr ) {
176  delete itr->second;
177  }
178  itr = m_outputObjects.begin();
179  end = m_outputObjects.end();
180  for( ; itr != end; ++itr ) {
181  delete itr->second;
182  }
183  itr = m_inputMetaObjects.begin();
184  end = m_inputMetaObjects.end();
185  for( ; itr != end; ++itr ) {
186  delete itr->second;
187  }
188  itr = m_outputMetaObjects.begin();
189  end = m_outputMetaObjects.end();
190  for( ; itr != end; ++itr ) {
191  delete itr->second;
192  }
193 
194  // If this is set up as the active event at the moment, notify
195  // the active event object that this object will no longer be
196  // available.
197  if( TActiveEvent::event() == this ) {
198  TActiveEvent::setEvent( nullptr );
199  }
200 #ifndef XAOD_STANDALONE
201  if( SG::CurrentEventStore::store() == this ) {
203  }
204 #endif // not XAOD_STANDALONE
205  }
206 
210 
211  return m_auxMode;
212  }
213 
223  std::string REvent::dump() {
224 
225  // The internal stream object:
226  std::ostringstream ost;
227  ost << "<<<<<<<<<<<<<<<<<<<< xAOD::REvent Dump >>>>>>>>>>>>>>>>>>>>\n";
228 
229  // Loop over the EventFormat object:
232  for( ; ef_itr != ef_end; ++ef_itr ) {
233 
234  // Construct the type name:
235  std::string typeName = ef_itr->second.className();
236  removeVersionNames( typeName );
237 
238  // Get the type:
239  ::TClass* cl =
240  ::TClass::GetClass( ef_itr->second.className().c_str() );
241  const std::type_info* ti = ( cl ? cl->GetTypeInfo() : nullptr );
242  if( ( ! cl ) || ( ! cl->IsLoaded() ) || ( ! ti ) ) {
243  Warning( "xAOD::REvent::dump",
244  "Unknown type (%s) found in the event format",
245  ef_itr->second.className().c_str() );
246  continue;
247  }
248 
249  // Skip containers that are not available anyway:
250  if( ! contains( ef_itr->second.branchName(), *ti ) ) {
251  continue;
252  }
253 
254  // Do the printout:
255  ost << " Hash: 0x" << std::setw( 8 ) << std::setfill( '0' )
256  << std::hex << ef_itr->second.hash()
257  << " Key: \"" << ef_itr->second.branchName() << "\"\n";
258 
259  ost << " type: " << typeName << "\n";
260  const bool isNonConst = transientContains( ef_itr->second.branchName(),
261  *ti );
262  ost << " isConst: " << ( isNonConst ? "No" : "Yes" ) << "\n";
263  ost << " Data: "
264  << ( isNonConst ? getOutputObject( ef_itr->second.branchName(),
265  *ti ) :
266  getInputObject( ef_itr->second.branchName(), *ti ) ) << "\n";
267  }
268 
269  // Finish with the construction:
270  ost << "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
271  return ost.str();
272  }
273 
278  void REvent::printIOStats() const {
279 
280  // Simply do this via the xAODCore code:
281  IOStats::instance().stats().Print( "Summary" );
282 
283  return;
284  }
285 
292  StatusCode REvent::readFrom( const std::string& fileName ) {
293 
294  // If no file was specified, return gracefully:
295  if( fileName.size() == 0 ) return StatusCode::SUCCESS;
296 
297  // For meta data, need to open file as TFile to access the meta data tree
298  std::unique_ptr< TFile > infile( TFile::Open( fileName.c_str(), "READ" ) );
299  if( ! infile.get() ) {
300  ::Error( "xAOD::REvent::readFrom",
301  XAOD_MESSAGE( "Couldn't open file for metadata tree! File name %s"), fileName.c_str());
302  return StatusCode::FAILURE;
303  }
304 
305  // Clear the cached input objects:
306  Object_t::iterator itr = m_inputObjects.begin();
308  for( ; itr != end; ++itr ) {
309  delete itr->second;
310  }
311  m_inputObjects.clear();
312  m_inputMissingObjects.clear();
313  {
315  lock.upgrade();
316  m_branches.clear();
317  }
318 
319  // Clear the cached input meta-objects:
320  itr = m_inputMetaObjects.begin();
321  end = m_inputMetaObjects.end();
322  for( ; itr != end; ++itr ) {
323  delete itr->second;
324  }
325  m_inputMetaObjects.clear();
326 
327  // Reset the internal flags:
328  m_entry = -1;
329 
330  // Make sure we return to the current directory:
332 
333  // Look for the metadata tree:
334  m_inMetaTree =
335  dynamic_cast< ::TTree* >( infile->Get( METADATA_TREE_NAME ) );
336  if( ! m_inMetaTree ) {
337  ::Error( "xAOD::REvent::readFrom",
338  XAOD_MESSAGE( "Couldn't find metadata tree on input. Object "
339  "unusable!" ) );
340  return StatusCode::FAILURE;
341  }
342 
343  // Set metadata entry to be read
344  // NB: no reading is done calling LoadTree
345  if ( m_inMetaTree->LoadTree(0) < 0 ){
346  ::Error( "xAOD::REvent::readFrom",
347  XAOD_MESSAGE( "Failed to load entry for metadata tree=%s" ),
348  m_inMetaTree->GetName() );
349  return StatusCode::FAILURE;
350  }
351 
352  // A sanity check:
353  if( m_inMetaTree->GetEntries() != 1 ) {
354  ::Info( "xAOD::REvent::readFrom",
355  "Was expecting a metadata tree with size 1, instead of %i.",
356  static_cast< int >( m_inMetaTree->GetEntries() ) );
357  ::Info( "xAOD::REvent::readFrom",
358  "File most probably produced by hadd..." );
359  }
360 
361  // Make sure that the xAOD::EventFormat dictonary is loaded.
362  // This may not be the case if streamer information reading is turned
363  // off.
364  static const std::string eventFormatTypeName =
365  Utils::getTypeName( typeid( EventFormat ) );
366  ::TClass* cl = ::TClass::GetClass( eventFormatTypeName.c_str() );
367  if( ! cl ) {
368  ::Warning( "xAOD::REvent::readFrom",
369  "Couldn't load the EventFormat dictionary" );
370  }
371 
372  // Check if the EventFormat branch is available:
373  const std::string eventFormatBranchName =
374  Utils::getFirstBranchMatch( m_inMetaTree, "EventFormat");
375  if( ! m_inMetaTree->GetBranch( eventFormatBranchName.c_str() ) ) {
376  // This can happen when the file was produced by an Athena job that
377  // didn't have any input events itself. This means that the file
378  // doesn't actually have any useful metadata.
379  ::Info( "xAOD::REvent::readFrom", "Input file provides no event or "
380  "metadata" );
381  m_inNtupleReader = 0;
382  return StatusCode::SUCCESS;
383  }
384 
385  // Read in the event format object:
386  EventFormat* format = 0; ::TBranch* br = 0;
387  const Int_t status =
388  m_inMetaTree->SetBranchAddress( eventFormatBranchName.c_str(),
389  &format, &br );
390  if( status < 0 ) {
391  ::Error( "xAOD::REvent::readFrom",
392  XAOD_MESSAGE( "Failed to connect to EventFormat object" ) );
393  return StatusCode::FAILURE;
394  }
395 
396  // Read in the object to our private member:
397  br->GetEntry( 0 );
399 
400  // This is a strange place. The object has to be deleted, as it is the
401  // responsibility of the user code to do so. But if I also explicitly
402  // tell the branch to forget about the address of the pointer, then
403  // all hell breaks loose...
404  delete format;
405 
406 
407  // List all the other Metadata trees in the input file
408  // Having several metatrees can happen for augmented files for instance
409  // as one metadata tree per stream is produced
410  std::set<std::string> lOtherMetaTreeNames = {};
411  TList *lKeys = infile->GetListOfKeys();
412 
413  if (lKeys){
414  for (int iKey = 0; iKey < lKeys->GetEntries() ; iKey++){
415  // iterate over keys and add
416  std::string keyName = lKeys->At(iKey)->GetName();
417  // Make sure the key corresponds to a metadata tree but
418  // do not add the current metadata tree in the list of other trees
419  // and do not add the metadata tree handlers to the list
420  if ( (keyName != METADATA_TREE_NAME)
421  && (keyName.find("MetaData") != std::string::npos)
422  && !(keyName.find("MetaDataHdr") != std::string::npos)){
423  // Make sure key corresponds to a tree
424  const char *className = ((::TKey*)lKeys->At(iKey))->GetClassName();
425  static constexpr Bool_t LOAD = kFALSE;
426  static constexpr Bool_t SILENT = kTRUE;
427  ::TClass* cl = ::TClass::GetClass(className, LOAD, SILENT);
428  if ((cl != nullptr) && cl->InheritsFrom(::TTree::Class())){
429  lOtherMetaTreeNames.insert(std::move(keyName));
430  }
431  }
432  }
433  }
434  else {
435  ::Info( "xAOD::REvent::readFrom", XAOD_MESSAGE( "no keys found"));
436  }
437 
438  // Loop over the other metadata trees found (if any)
439  for (const std::string & metaTreeName : lOtherMetaTreeNames){
440  TTree *tmpMetaTree = dynamic_cast< ::TTree* >( infile->Get( metaTreeName.c_str() ) );
441 
442  if (!tmpMetaTree){
443  // Skip tree if could not read it
444  ::Warning( "xAOD::REvent::readFrom", "Could not read metadata tree=%s",metaTreeName.c_str());
445  continue;
446  }
447 
448  // Set metadata entry to be read
449  // NB: no reading is done calling LoadTree
450  if ( tmpMetaTree->LoadTree(0) < 0 ){
451  ::Error( "xAOD::REvent::readFrom",
452  XAOD_MESSAGE( "Failed to load entry for metadata tree=%s" ),
453  tmpMetaTree->GetName() );
454  return StatusCode::FAILURE;
455  }
456 
457  // Check if the EventFormat branch is available:
458  const std::string tmpEventFormatBranchName =
459  Utils::getFirstBranchMatch( tmpMetaTree, "EventFormat");
460  if( ! tmpMetaTree->GetBranch( tmpEventFormatBranchName.c_str() ) ) {
461  // skip the additionnal metadata tree
462  ::Warning( "xAOD::REvent::readFrom", "No EventFormat branch found in metadata tree=%s",tmpMetaTree->GetName() );
463  continue ;
464  }
465  // Read in the event format object:
466  EventFormat* tmpFormat = 0; ::TBranch* tmpBr = 0;
467  const Int_t status =
468  tmpMetaTree->SetBranchAddress( tmpEventFormatBranchName.c_str(),
469  &tmpFormat, &tmpBr );
470  if( status < 0 ) {
471  ::Error( "xAOD::REvent::readFrom",
472  XAOD_MESSAGE( "Failed to connect to EventFormat object for metadata tree = %s"), tmpMetaTree->GetName() );
473  return StatusCode::FAILURE;
474  }
475  // Read in the object
476  tmpBr->GetEntry( 0 );
477  // read all objects contained in the event format
478  for (const std::pair<const std::string, xAOD::EventFormatElement> &evtElem : *tmpFormat){
479  // if element is not existing
480  // then add it to the private event format member
481  if (!m_inputEventFormat.exists(evtElem.first)){
482  m_inputEventFormat.add(evtElem.second);
483  }
484  }
485  delete tmpFormat;
486  }
487 
488  // Save RNTuple reader
489 
490  const char* rnTupleName = EVENT_RNTUPLE_NAME;
491  m_inNtupleReader = ROOT::RNTupleReader::Open(rnTupleName, fileName);
492 
493  // m_inNtupleReader = &reader;
494  if ( !m_inNtupleReader ) {
495  ::Error( "xAOD::REvent::readFrom", XAOD_MESSAGE( "inNtupleReader is empty") );
496  return StatusCode::FAILURE;
497  }
498 
499  // m_inNtupleReader->PrintInfo();
500 
501  // Init the statistics collection:
502  RETURN_CHECK( "xAOD::REvent::readFrom", initStats() );
503  // Update the event counter in the statistics object:
505  if( m_inNtupleReader ) {
506  stats.setNEvents( stats.nEvents() + m_inNtupleReader->GetNEntries() );
507  }
508 
509  // Notify the listeners that a new file was opened:
510  const TIncident beginIncident( IncidentType::BeginInputFile );
511  for( TVirtualIncidentListener* listener : m_listeners ) {
512  listener->handle( beginIncident );
513  }
514  // For now implement a very simple scheme in which we claim already
515  // at the start that the entire file was processed. Since we have no way
516  // of ensuring that the user indeed does this. And we can't delay calling
517  // this function, as the user may likely close his/her output file before
518  // closing the last opened input file.
519  const TIncident endIncident( IncidentType::EndInputFile );
520  for( TVirtualIncidentListener* listener : m_listeners ) {
521  listener->handle( endIncident );
522  }
523 
524  // The initialisation was successful:
525  return StatusCode::SUCCESS;
526  }
527 
528  // /// This function should be called on a file opened be the user, before
529  // /// any event processing would occur. It sets up the output event tree.
530  // ///
531  // /// @param file The file that the event data should be written to
532  // /// @param autoFlush The auto-flush setting to use on the output TTree
533  // /// @param treeName Name of the output event tree
534  // /// @returns <code>kTRUE</code> if successful, <code>kFALSE</code> otherwise
535  // ///
536  // StatusCode REvent::writeTo( ::TFile* file, Int_t autoFlush,
537  // const char* treeName ) {
538 
539  // // Just a simple security check:
540  // if( ! file ) {
541  // ::Error( "xAOD::REvent::writeTo",
542  // XAOD_MESSAGE( "Null pointer given to the function!" ) );
543  // return StatusCode::FAILURE;
544  // }
545 
546  // // Check that the object is in the "right state":
547  // if( m_outTree ) {
548  // ::Error( "xAOD::REvent::writeTo",
549  // XAOD_MESSAGE( "Object already writing to a file. Close that "
550  // "file first!" ) );
551  // return StatusCode::FAILURE;
552  // }
553 
554  // // Make sure we return to the current directory:
555  // TDirectoryReset dr;
556 
557  // // Create the output TTree:
558  // file->cd();
559  // m_outTree = new ::TTree( treeName, "xAOD event tree" );
560  // m_outTree->SetDirectory( file );
561  // m_outTree->SetAutoSave( 1000000 );
562  // m_outTree->SetAutoFlush( autoFlush );
563 
564  // // Access the EventFormat object associated with this file:
565  // m_outputEventFormat =
566  // &( REventFormatRegistry::instance().getEventFormat( file ) );
567 
568  // // Return gracefully:
569  // return StatusCode::SUCCESS;
570  // }
571 
572  // /// This function needs to be called when the user is done writing events
573  // /// to a file, before (s)he would close the file itself.
574  // ///
575  // /// @param file The file that the event data is written to
576  // /// @returns <code>kTRUE</code> if successful, <code>kFALSE</code> otherwise
577  // ///
578  // StatusCode REvent::finishWritingTo( ::TFile* file ) {
579 
580  // // A small sanity check:
581  // if( ! m_outTree ) {
582  // ::Error( "xAOD::REvent::finishWritingTo",
583  // XAOD_MESSAGE( "The object doesn't seem to be connected to an "
584  // "output file!" ) );
585  // return StatusCode::FAILURE;
586  // }
587 
588  // // Make sure we return to the current directory:
589  // TDirectoryReset dr;
590 
591  // // Notify the listeners that they should write out their metadata, if they
592  // // have any.
593  // const TIncident incident( IncidentType::MetaDataStop );
594  // Listener_t::iterator l_itr = m_listeners.begin();
595  // Listener_t::iterator l_end = m_listeners.end();
596  // for( ; l_itr != l_end; ++l_itr ) {
597  // ( *l_itr )->handle( incident );
598  // }
599 
600  // // Write out the event tree, and delete it:
601  // m_outTree->AutoSave( "FlushBaskets" );
602  // m_outTree->SetDirectory( 0 );
603  // delete m_outTree;
604  // m_outTree = 0;
605 
606  // // Now go to the output file:
607  // file->cd();
608 
609  // // Check if there's already a metadata tree in the output:
610  // if( file->Get( METADATA_TREE_NAME ) ) {
611  // // Let's assume that the metadata is complete in the file already.
612  // return StatusCode::SUCCESS;
613  // }
614 
615  // // Create the metadata tree:
616  // ::TTree* metatree =
617  // new ::TTree( METADATA_TREE_NAME, "xAOD metadata tree" );
618  // metatree->SetAutoSave( 10000 );
619  // metatree->SetAutoFlush( -30000000 );
620  // metatree->SetDirectory( file );
621 
622  // // Create the only branch in it:
623  // metatree->Branch( "EventFormat",
624  // SG::normalizedTypeinfoName( typeid( xAOD::EventFormat ) ).c_str(),
625  // &m_outputEventFormat );
626 
627  // // Create a copy of the m_outputMetaObjects variable. This is necessary
628  // // because the putAux(...) function will modify this variable while we
629  // // loop over it.
630  // Object_t outputMetaObjects = m_outputMetaObjects;
631 
632  // // Now loop over all the metadata objects that need to be put into the
633  // // output file:
634  // for( auto& object : outputMetaObjects ) {
635  // // All metadata objects should be held by TObjectManager objects.
636  // // Anything else is an error.
637  // TObjectManager* mgr = dynamic_cast< TObjectManager* >( object.second );
638  // if( ! mgr ) {
639  // ::Error( "xAOD::REvent::finishWritingTo",
640  // XAOD_MESSAGE( "Internal logic error detected" ) );
641  // return StatusCode::FAILURE;
642  // }
643  // // Select a split level depending on whether this is an interface or an
644  // // auxiliary object:
645  // const ::Int_t splitLevel = ( object.first.find( "Aux." ) ==
646  // ( object.first.size() - 4 ) ? 1 : 0 );
647  // // Create the new branch:
648  // *( mgr->branchPtr() ) =
649  // metatree->Branch( object.first.c_str(),
650  // mgr->holder()->getClass()->GetName(),
651  // mgr->holder()->getPtr(), 32000, splitLevel );
652  // if( ! mgr->branch() ) {
653  // ::Error( "xAOD::REvent::finishWritingTo",
654  // XAOD_MESSAGE( "Failed to create metadata branch "
655  // "\"%s/%s\"" ),
656  // mgr->holder()->getClass()->GetName(),
657  // object.first.c_str() );
658  // return StatusCode::FAILURE;
659  // }
660  // // Set up the saving of all the dynamic auxiliary properties
661  // // of the object if it has any:
662  // RETURN_CHECK( "xAOD::REvent::finishWritingTo",
663  // putAux( *metatree, *( object.second ), 32000, 0,
664  // kTRUE ) );
665  // }
666 
667  // // Write the metadata objects:
668  // if( metatree->Fill() <= 0 ) {
669  // ::Error( "xAOD::REvent::finishWritingTo",
670  // XAOD_MESSAGE( "Failed to write event format metadata into "
671  // "the output" ) );
672  // metatree->SetDirectory( 0 );
673  // delete metatree;
674  // return StatusCode::FAILURE;
675  // }
676 
677  // // Now clean up:
678  // metatree->Write();
679  // metatree->SetDirectory( 0 );
680  // delete metatree;
681  // m_outputEventFormat = 0;
682  // Object_t::iterator obj_itr = m_outputObjects.begin();
683  // Object_t::iterator obj_end = m_outputObjects.end();
684  // for( ; obj_itr != obj_end; ++obj_itr ) {
685  // delete obj_itr->second;
686  // }
687  // m_outputObjects.clear();
688  // obj_itr = m_outputMetaObjects.begin();
689  // obj_end = m_outputMetaObjects.end();
690  // for( ; obj_itr != obj_end; ++obj_itr ) {
691  // delete obj_itr->second;
692  // }
693  // m_outputMetaObjects.clear();
694 
695  // // Return gracefully:
696  // return StatusCode::SUCCESS;
697  // }
698 
704  void REvent::setActive() const {
705 
706  // The active event and current store are thread-local globals:
707  REvent* nc_this ATLAS_THREAD_SAFE = const_cast<REvent*>(this);
708 
709  TActiveEvent::setEvent( static_cast<TVirtualEvent*>( nc_this ) );
710 
711 #ifndef XAOD_STANDALONE
713 #endif // not XAOD_STANDALONE
714 
715  // Return gracefully:
716  return;
717  }
718 
726  void REvent::setAuxItemList( const std::string& containerKey,
727  const std::string& itemList ) {
728 
729  // Decoded attributes:
730  std::set< std::string > attributes;
731 
732  // Split up the received string using "." as the separator:
733  if( itemList.size() ) {
734  std::stringstream ss( itemList );
735  std::string attr;
736  while( std::getline( ss, attr, '.' ) ) {
737  attributes.insert( attr );
738  }
739  }
740 
741  // Remember the setting:
742  m_auxItemList[ containerKey ] = std::move(attributes);
743 
744  return;
745  }
746 
755 
756  // Check that we received a valid pointer:
757  if( ! listener ) {
758  ::Error( "xAOD::REvent::addListener",
759  XAOD_MESSAGE( "Received a null pointer for the listener" ) );
760  return StatusCode::FAILURE;
761  }
762 
763  // Check if this listener is already in our list:
764  bool listenerKnown = false;
766  if( l == listener ) {
767  ::Warning( "xAOD::REvent::addListener",
768  "Listener %p was added previously already",
769  static_cast< void* >( listener ) );
770  listenerKnown = true;
771  break;
772  }
773  }
774 
775  // If we don't know it yet, let's add it now:
776  if( ! listenerKnown ) {
777  m_listeners.push_back( listener );
778  }
779 
780  // Return gracefully:
781  return StatusCode::SUCCESS;
782  }
783 
791 
792  // Find the pointer if we can...
794  m_listeners.end(), listener );
795 
796  // If we didn't find it:
797  if( itr == m_listeners.end() ) {
798  ::Error( "xAOD::REvent::removeListener",
799  XAOD_MESSAGE( "Listener %p not known" ),
800  static_cast< void* >( listener ) );
801  return StatusCode::FAILURE;
802  }
803 
804  // Remove it:
805  m_listeners.erase( itr );
806 
807  // Return gracefully:
808  return StatusCode::SUCCESS;
809  }
810 
815 
816  m_listeners.clear();
817  return;
818  }
819 
834  StatusCode REvent::addNameRemap( const std::string& onfile,
835  const std::string& newName ) {
836 
837  // Check if this name is known on the input or output already. As that's
838  // not good.
840  ::Error( "xAOD::REvent::addNameRemap",
841  XAOD_MESSAGE( "Can't use \"%s\" as the target name in the"
842  "\"%s\" -> \"%s\" remapping" ),
843  newName.c_str(), onfile.c_str(), newName.c_str() );
844  return StatusCode::FAILURE;
845  }
846 
847  // Check if this name was remapped to something already:
848  auto itr = m_nameRemapping.find( newName );
849  if( itr != m_nameRemapping.end() ) {
850  ::Warning( "xAOD::REvent::addNameRemap",
851  "Overriding existing name remapping \"%s\" -> \"%s\"",
852  itr->second.c_str(), itr->first.c_str() );
853  ::Warning( "xAOD::REvent::addNameRemap", " with: \"%s\" -> \"%s\"",
854  onfile.c_str(), newName.c_str() );
855  }
856 
858  m_nameRemapping[ newName ] = onfile;
859 
860  // Return gracefully:
861  return StatusCode::SUCCESS;
862  }
863 
869 
870  m_nameRemapping.clear();
871  return;
872  }
873 
877  void REvent::printNameRemap() const {
878 
879  // Print a header:
880  ::Info( "xAOD::REvent::printNameRemap", "Name remapping rules:" );
881 
882  // In case no remapping rules have been set:
883  if( ! m_nameRemapping.size() ) {
884  ::Info( "xAOD::REvent::printNameRemap", " NONE" );
885  return;
886  }
887 
888  // Otherwise:
889  for( auto itr = m_nameRemapping.begin(); itr != m_nameRemapping.end();
890  ++itr ) {
891  ::Info( "xAOD::REvent::printNameRemap", " \"%s\" -> \"%s\"",
892  itr->second.c_str(), itr->first.c_str() );
893  }
894 
895  // Return gracefully:
896  return;
897  }
898 
899  // /// This function can be used to create/retrieve a ROOT-specific auxiliary
900  // /// object container that can be used to write information in the output
901  // /// file. Any auxiliary information written this way will however only be
902  // /// readable in ROOT, using the <code>kBranchAccess</code> option.
903  // ///
904  // /// @param key The name/prefix of the auxiliary store object/branches
905  // /// @param type The type of the auxiliary store (object/container)
906  // /// @param basketSize Size of the baskets created by the store object
907  // /// @param splitLevel The split level of the branches created by the store
908  // /// @returns An auxiliary store object that will write to the output
909  // ///
910  // SG::IAuxStore* REvent::recordAux( const std::string& key,
911  // SG::IAuxStoreHolder::AuxStoreType type,
912  // ::Int_t basketSize, ::Int_t splitLevel ) {
913 
914  // // A sanity check:
915  // if( ! m_outTree ) {
916  // ::Error( "xAOD::REvent::recordAux",
917  // XAOD_MESSAGE( "No output tree given to the object" ) );
918  // return 0;
919  // }
920 
921  // // Check for an object with this name in the output list:
922  // Object_t::iterator itr = m_outputObjects.find( key );
923  // if( itr == m_outputObjects.end() ) {
924  // // Create one if if it doesn't exist yet...
925  // // Translate the store type:
926  // TAuxStore::EStructMode mode = TAuxStore::EStructMode::kUndefinedStore;
927  // switch( type ) {
928  // case SG::IAuxStoreHolder::AST_ObjectStore:
929  // mode = TAuxStore::EStructMode::kObjectStore;
930  // break;
931  // case SG::IAuxStoreHolder::AST_ContainerStore:
932  // mode = TAuxStore::EStructMode::kContainerStore;
933  // break;
934  // default:
935  // ::Error( "xAOD::REvent::recordAux",
936  // XAOD_MESSAGE( "Unknown store type (%i) requested" ),
937  // static_cast< int >( type ) );
938  // return 0;
939  // }
940  // // Create and record the object:
941  // TAuxStore* store = new TAuxStore( key, kTRUE, mode,
942  // basketSize, splitLevel );
943  // if( record( store, key, basketSize, splitLevel, kTRUE ).isFailure() ) {
944  // ::Error( "xAOD::REvent::recordAux",
945  // XAOD_MESSAGE( "Couldn't connect TAuxStore object to the "
946  // "output" ) );
947  // delete store;
948  // return 0;
949  // }
950  // // Update the iterator:
951  // itr = m_outputObjects.find( key );
952  // }
953 
954  // // A security check:
955  // if( itr == m_outputObjects.end() ) {
956  // ::Error( "xAOD::REvent::recordAux",
957  // XAOD_MESSAGE( "Internal logic error detected" ) );
958  // return 0;
959  // }
960 
961  // // Check that it is of the right type:
962  // TAuxManager* mgr = dynamic_cast< TAuxManager* >( itr->second );
963  // if( ! mgr ) {
964  // ::Error( "xAOD::REvent::recordAux",
965  // XAOD_MESSAGE( "Object of non-TAuxStore type registered "
966  // "with key \"%s\"" ), key.c_str() );
967  // return 0;
968  // }
969 
970  // // Extract the pointer out of it:
971  // TAuxStore* store = mgr->getStore();
972 
973  // // Give it to the user:
974  // return store;
975  // }
976 
977  // /// This function can be used to easily copy a given object/container to the
978  // /// output, without modifying the contents of it. It only needs to be called
979  // /// on the interface object/container, the copying of the auxiliary data is
980  // /// done automatically, and is steered by the SetAuxItemList function.
981  // ///
982  // /// @param key The key (branch name) of the object/container to copy
983  // /// @param basketSize Optional size for the basket associated with the
984  // /// output branch
985  // /// @param splitLevel Optional split level of the output branch
986  // ///
987  // StatusCode REvent::copy( const std::string& key,
988  // ::Int_t basketSize, ::Int_t splitLevel ) {
989 
990  // // Check if a name re-mapping should be applied or not:
991  // std::string keyToUse = key;
992  // auto remap_itr = m_nameRemapping.find( key );
993  // if( ( remap_itr != m_nameRemapping.end() ) &&
994  // ( ! m_inputEventFormat.exists( key ) ) &&
995  // m_inputEventFormat.exists( remap_itr->second ) ) {
996  // keyToUse = remap_itr->second;
997  // }
998 
999  // // Make sure that the branch got connected to:
1000  // RETURN_CHECK( "xAOD::REvent::copy", connectBranch( keyToUse ) );
1001 
1002  // // Make sure that the input object is properly updated:
1003  // Object_t::const_iterator vobjMgr = m_inputObjects.find( keyToUse );
1004  // if( vobjMgr == m_inputObjects.end() ) {
1005  // ::Error( "xAOD::REvent::copy",
1006  // XAOD_MESSAGE( "Internal logic error detected" ) );
1007  // return StatusCode::FAILURE;
1008  // }
1009  // TObjectManager* objMgr =
1010  // dynamic_cast< TObjectManager* >( vobjMgr->second );
1011  // if( ! objMgr ) {
1012  // ::Error( "xAOD::REvent::copy",
1013  // XAOD_MESSAGE( "Internal logic error detected" ) );
1014  // return StatusCode::FAILURE;
1015  // }
1016  // if( ! getInputObject( key,
1017  // *( objMgr->holder()->getClass()->GetTypeInfo() ) ) ) {
1018  // ::Error( "xAOD::REvent::copy",
1019  // XAOD_MESSAGE( "Internal logic error detected" ) );
1020  // return StatusCode::FAILURE;
1021  // }
1022 
1023  // // Put the interface object into the output:
1024  // RETURN_CHECK( "xAOD::REvent::copy",
1025  // record( objMgr->object(),
1026  // objMgr->holder()->getClass()->GetName(),
1027  // key, basketSize, splitLevel, kTRUE ) );
1028 
1029  // // Check if we have a filtering rule for the store:
1030  // const std::set< std::string >* filter = 0;
1031  // auto fitr = m_auxItemList.find( key + "Aux." );
1032  // if( fitr != m_auxItemList.end() ) {
1033  // filter = &( fitr->second );
1034  // }
1035 
1036  // // Put the auxiliary store object into the output:
1037  // Object_t::const_iterator vauxMgr = m_inputObjects.find( keyToUse +
1038  // "Aux." );
1039  // if( vauxMgr == m_inputObjects.end() ) {
1040  // // If there is no auxiliary store for this object/container, we're
1041  // // done already:
1042  // return StatusCode::SUCCESS;
1043  // }
1044  // // Check what type of auxiliary store this is:
1045  // if( m_auxMode == kClassAccess || m_auxMode == kAthenaAccess ) {
1046  // TObjectManager* auxMgr =
1047  // dynamic_cast< TObjectManager* >( vauxMgr->second );
1048  // if( ! auxMgr ) {
1049  // ::Error( "xAOD::REvent::copy",
1050  // XAOD_MESSAGE( "Internal logic error detected" ) );
1051  // return StatusCode::FAILURE;
1052  // }
1053  // RETURN_CHECK( "xAOD::REvent::copy",
1054  // record( auxMgr->object(),
1055  // auxMgr->holder()->getClass()->GetName(),
1056  // key + "Aux.", basketSize, splitLevel, kTRUE ) );
1057  // } else if( m_auxMode == kBranchAccess ) {
1058  // TAuxManager* auxMgr =
1059  // dynamic_cast< TAuxManager* >( vauxMgr->second );
1060  // if( ! auxMgr ) {
1061  // ::Error( "xAOD::REvent::copy",
1062  // XAOD_MESSAGE( "Internal logic error detected" ) );
1063  // return StatusCode::FAILURE;
1064  // }
1065  // // Set up the filtering:
1066  // if( filter ) {
1067  // auxMgr->getStore()->selectAux( *filter );
1068  // }
1069  // RETURN_CHECK( "xAOD::REvent::copy",
1070  // record( auxMgr->getStore(),
1071  // key + "Aux.", basketSize, splitLevel ) );
1072  // } else {
1073  // ::Fatal( "xAOD::REvent::copy",
1074  // XAOD_MESSAGE( "Internal logic error detected" ) );
1075  // }
1076 
1077  // // Return gracefully:
1078  // return StatusCode::SUCCESS;
1079  // }
1080 
1081  // /// This function is here to make it easy to write code that skims an input
1082  // /// file into an output file without applying any modification to the events.
1083  // ///
1084  // /// @param basketSize Optional size for the basket associated with the
1085  // /// output branch
1086  // /// @param splitLevel Optional split level of the output branch
1087  // /// @returns <code>StatusCode::SUCCESS</code> if the copy was
1088  // /// successful, or <code>StatusCode::FAILURE</code> if not
1089  // ///
1090  // StatusCode REvent::copy( ::Int_t basketSize, ::Int_t splitLevel ) {
1091 
1092  // // Make sure that an input TTree is available:
1093  // if( ! m_inTree ) {
1094  // ::Error( "xAOD::REvent::copy",
1095  // XAOD_MESSAGE( "No input TTree is open" ) );
1096  // return StatusCode::FAILURE;
1097  // }
1098 
1099  // // Loop over the known input containers:
1100  // EventFormat::const_iterator itr = m_inputEventFormat.begin();
1101  // EventFormat::const_iterator end = m_inputEventFormat.end();
1102  // for( ; itr != end; ++itr ) {
1103 
1104  // // Convenience reference:
1105  // const EventFormatElement& efe = itr->second;
1106 
1107  // // Ignore objects that don't exist on the input:
1108  // if( ! m_inTree->GetBranch( efe.branchName().c_str() ) ) {
1109  // continue;
1110  // }
1111  // // Skip all branches ending in "Aux.":
1112  // if( efe.branchName().find( "Aux." ) ==
1113  // ( efe.branchName().size() - 4 ) ) {
1114  // continue;
1115  // }
1116  // // Also skip dynamic branches:
1117  // if( efe.parentName() != "" ) {
1118  // continue;
1119  // }
1120  // // Check if the class in question is known:
1121  // ::TClass* cl = ::TClass::GetClass( efe.className().c_str() );
1122  // if( ( ! cl ) || ( ! cl->IsLoaded() ) ) {
1123  // continue;
1124  // }
1125 
1126  // // Make the copy then...
1127  // RETURN_CHECK( "xAOD::REvent::copy",
1128  // this->copy( efe.branchName(), basketSize, splitLevel ) );
1129  // }
1130 
1131  // // Return gracefully:
1132  // return StatusCode::SUCCESS;
1133  // }
1134 
1137  ::Long64_t REvent::getEntries() const {
1138 
1139  if( m_inNtupleReader ) {
1140  return m_inNtupleReader->GetNEntries();
1141  } else {
1142  ::Error( "xAOD::REvent::getEntries",
1143  XAOD_MESSAGE( "Function called on an uninitialised "
1144  "object" ) );
1145  return 0;
1146  }
1147  }
1148 
1163  ::Int_t REvent::getEntry( ::Long64_t entry, ::Int_t getall ) {
1164 
1165  // A little sanity check:
1166  if( ( ! m_inNtupleReader ) ) {
1167  ::Error( "xAOD::REvent::getEntry",
1168  XAOD_MESSAGE( "Function called on an uninitialised "
1169  "object" ) );
1170  return -1;
1171  }
1172 
1173  // Set entry value
1174  m_entry = entry;
1175 
1176  // Stats counter needs to know it's the next event:
1178 
1179  // If force-reading is not requested, we're done:
1180  if( ! getall ) {
1181 
1182  // Notify the listeners that a new event was loaded:
1183  const TIncident incident( IncidentType::BeginEvent );
1184  Listener_t::iterator l_itr = m_listeners.begin();
1185  Listener_t::iterator l_end = m_listeners.end();
1186  for( ; l_itr != l_end; ++l_itr ) {
1187  ( *l_itr )->handle( incident );
1188  }
1189 
1190  // No real reading was done:
1191  return 0;
1192  }
1193 
1194  // Loop over all input object managers, and force them to load their
1195  // content:
1196  ::Int_t result = 0;
1197  if( m_auxMode == kAthenaAccess ) {
1198  // In kAthenaAccess mode we need to use getInputObject(...) to load
1199  // all the input objects correctly.
1200  for( auto& inObj : m_inputObjects ) {
1201  static const std::string dynStorePostfix = "Aux.Dynamic";
1202  if( inObj.first.find( dynStorePostfix ) ==
1203  ( inObj.first.size() - dynStorePostfix.size() ) ) {
1204  // Ignore the dynamic store objects. They get loaded through
1205  // their parents.
1206  } else {
1207  // Load the objects and their auxiliary stores through the
1208  // getInputObject(...) function, which takes care of correctly
1209  // setting them up. The type is irrelevant here. We don't
1210  // really care about the exact type of the objects.
1211  getInputObject( inObj.first, typeid( int ), kTRUE, kFALSE );
1212  }
1213  }
1214  } else {
1215  // In a "reasonable" access mode, we do something very simple:
1216  for( auto& inObj : m_inputObjects ) {
1217  result += inObj.second->getEntry( getall );
1218  }
1219  }
1220 
1221  // Notify the listeners that a new event was loaded:
1222  const TIncident incident( IncidentType::BeginEvent );
1223  Listener_t::iterator l_itr = m_listeners.begin();
1224  Listener_t::iterator l_end = m_listeners.end();
1225  for( ; l_itr != l_end; ++l_itr ) {
1226  ( *l_itr )->handle( incident );
1227  }
1228 
1229  // Return the number of bytes read:
1230  return result;
1231  }
1232 
1233  // /// This function can be used to get the number of input files that the
1234  // /// object currently knows about. This is meant to be used to collect the
1235  // /// metadata from each of the input files, or to access the metadata using
1236  // /// a transient tree. (xAOD::TMetaTree)
1237  // ///
1238  // /// @returns The number of input files when reading from a TChain, 1 when
1239  // /// reading from a TFile, and 0 if the object is not connected to
1240  // /// any input
1241  // ///
1242  // ::Long64_t REvent::getFiles() const {
1243 
1244  // if( m_inChain ) {
1245  // return m_inChain->GetListOfFiles()->GetEntries();
1246  // } else if( m_inNtupleReader ) {
1247  // return 1;
1248  // } else {
1249  // return 0;
1250  // }
1251  // }
1252 
1253  // /// This function can be used to iterate over the input files specified for
1254  // /// the object. It should be most useful for collecting metadata about a set
1255  // /// of input files, if there's no regular event loop done to process them.
1256  // ///
1257  // /// @param file The file number to load
1258  // /// @param getall If set to 1, all connected branches are loaded
1259  // /// @returns The number of read bytes on success, or a negative number on
1260  // /// failure
1261  // ///
1262  // ::Int_t REvent::getFile( ::Long64_t file, ::Int_t getall ) {
1263 
1264  // // Check if the file number is valid:
1265  // if( ( file < 0 ) || ( file >= getFiles() ) ) {
1266  // ::Error( "xAOD::REvent::getFile",
1267  // XAOD_MESSAGE( "Function called with invalid file number "
1268  // "(%i)" ), static_cast< int >( file ) );
1269  // return -1;
1270  // }
1271 
1272  // // If we are not reading a TChain, return at this point. As the one and
1273  // // only file is open already...
1274  // if( ! m_inChain ) {
1275  // return 0;
1276  // }
1277 
1278  // // Trigger the "scanning" of the input files, so the TChain would know
1279  // // how many entries are in the various files.
1280  // getEntries();
1281 
1282  // // Calculate which entry/event we need to load:
1283  // ::Long64_t entry = 0;
1284  // for( ::Long64_t i = 0; i < file; ++i ) {
1285  // entry += m_inChain->GetTreeOffset()[ i ];
1286  // }
1287 
1288  // // Load this entry using the regular event opening function:
1289  // return getEntry( entry, getall );
1290  // }
1291 
1292  // /// This function needs to be called by the user at the end of processing
1293  // /// each event that is meant to be written out.
1294  // ///
1295  // /// @returns The number of bytes written if successful, a negative number
1296  // /// if not
1297  // ///
1298  // ::Int_t REvent::fill() {
1299 
1300  // // A little sanity check:
1301  // if( ! m_outTree ) {
1302  // ::Error( "xAOD::REvent::fill",
1303  // XAOD_MESSAGE( "Object not connected to an output file!" ) );
1304  // return 0;
1305  // }
1306 
1307  // // Make sure that all objects have been read in. The 99 as the value
1308  // // has a special meaning for TAuxStore. With this value it doesn't
1309  // // delete its transient (decoration) variables. Otherwise it does.
1310  // // (As it's supposed to, when moving to a new event.)
1311  // if( m_inNtupleReader ) {
1312  // if (getEntry( m_entry, 99 ) < 0) {
1313  // ::Error( "xAOD::REvent::fill",
1314  // XAOD_MESSAGE( "getEntry failed!" ) );
1315  // return 0;
1316  // }
1317  // }
1318 
1319  // // Prepare the objects for writing. Note that we need to iterate over a
1320  // // copy of the m_outputObjects container. Since the putAux(...) function
1321  // // called inside the loop may itself add elements to the m_outputObject
1322  // // container.
1323  // std::string unsetObjects;
1324  // Object_t outputObjectsCopy = m_outputObjects;
1325  // for( auto& itr : outputObjectsCopy ) {
1326  // // Check that a new object was provided in the event:
1327  // if( ! itr.second->create() ) {
1328  // // We are now going to fail. But let's collect the names of
1329  // // all the unset objects:
1330  // if( unsetObjects.size() ) {
1331  // unsetObjects.append( ", \"" + itr.first + "\"" );
1332  // } else {
1333  // unsetObjects.append( "\"" + itr.first + "\"" );
1334  // }
1335  // continue;
1336  // }
1337  // // Make sure that any dynamic auxiliary variables that
1338  // // were added to the object after it was put into the event,
1339  // // get added to the output:
1340  // if( ! putAux( *m_outTree, *( itr.second ) ) ) {
1341  // ::Error( "xAOD::REvent::fill",
1342  // XAOD_MESSAGE( "Failed to put dynamic auxiliary variables "
1343  // "in the output for object \"%s\"" ),
1344  // itr.first.c_str() );
1345  // return 0;
1346  // }
1347  // }
1348 
1349  // // Check if there were any unset objects:
1350  // if( unsetObjects.size() ) {
1351  // ::Error( "xAOD::REvent::fill",
1352  // XAOD_MESSAGE( "The following objects were not set in the "
1353  // "current event: %s" ), unsetObjects.c_str() );
1354  // return 0;
1355  // }
1356 
1357  // // Write the entry, and check the return value:
1358  // const ::Int_t ret = m_outTree->Fill();
1359  // if( ret <= 0 ) {
1360  // ::Error( "xAOD::REvent::fill",
1361  // XAOD_MESSAGE( "Output tree filling failed with return "
1362  // "value: %i" ), ret );
1363  // }
1364 
1365  // // Reset the object managers:
1366  // Object_t::iterator ncitr = m_outputObjects.begin();
1367  // Object_t::iterator ncend = m_outputObjects.end();
1368  // for( ; ncitr != ncend; ++ncitr ) {
1369  // ncitr->second->reset();
1370  // }
1371 
1372  // // Return the value:
1373  // return ret;
1374  // }
1375 
1388 
1389  // If we *are* reading an input file:
1390  if( m_inNtupleReader ) {
1391  return &m_inputEventFormat;
1392  }
1393 
1394  // If not, let's complain:
1395  ::Warning( "xAOD::REvent::inputEventFormat",
1396  "No input file is connected at the moment" );
1397  return 0;
1398  }
1399 
1400  // /// This function makes it possible for the user to investigate the
1401  // /// content that is being written to the output file.
1402  // ///
1403  // /// Notice that this doesn't necessarily mean that all the objects for
1404  // /// which metadata is stored, would necessarily be part of the output
1405  // /// TTree that this object is connected to.
1406  // ///
1407  // /// @returns The event format object if a file is being written, or a null
1408  // /// pointer if not.
1409  // ///
1410  // const EventFormat* REvent::outputEventFormat() const {
1411 
1412  // // If we *are* reading an input file:
1413  // if( m_outTree ) {
1414  // return m_outputEventFormat;
1415  // }
1416 
1417  // // If not, let's complain:
1418  // ::Warning( "xAOD::REvent::outputEventFormat",
1419  // "No output file is connected at the moment" );
1420  // return 0;
1421  // }
1422 
1433  SG::sgkey_t REvent::getHash( const std::string& key ) const {
1434 
1435  // For empty keys let's finish quickly:
1436  if( key == "" ) return 0;
1437 
1438  // If the key is used in the input file, let's use the same hash for
1439  // the output file as well:
1440  if( m_inputEventFormat.exists( key ) ) {
1441  return m_inputEventFormat.get( key )->hash();
1442  }
1443 
1444  // If it's a new key, make a new hash for it from scratch:
1445  return Utils::hash( key );
1446  }
1447 
1455  SG::sgkey_t REvent::getKey( const void* obj ) const {
1456 
1457  // Make use of the getName function:
1458  return getHash( getName( obj ) );
1459  }
1460 
1468  const std::string& REvent::getName( const void* obj ) const {
1469 
1470  // First look among the output objects:
1471  Object_t::const_iterator obj_itr = m_outputObjects.begin();
1472  Object_t::const_iterator obj_end = m_outputObjects.end();
1473  for( ; obj_itr != obj_end; ++obj_itr ) {
1474 
1475  // Check if this is our object:
1476  if( obj_itr->second->object() != obj ) continue;
1477 
1478  // If it is, let's return right away:
1479  return obj_itr->first;
1480  }
1481 
1482  // Now look among the input objects:
1483  obj_itr = m_inputObjects.begin();
1484  obj_end = m_inputObjects.end();
1485  for( ; obj_itr != obj_end; ++obj_itr ) {
1486 
1487  // Check if this is our object:
1488  if( obj_itr->second->object() != obj ) continue;
1489 
1490  // If it is, let's return:
1491  return obj_itr->first;
1492  }
1493 
1494  // If it's not there either, check if it's in an active TStore object:
1495  const TStore* store = TActiveStore::store();
1496  if( store && store->contains( obj ) ) {
1497  // Get the name from the store then:
1498  return store->getName( obj );
1499  }
1500 
1501  // We didn't find the object in the event...
1502  ::Warning( "xAOD::REvent::getName",
1503  "Didn't find object with pointer %p in the event",
1504  obj );
1505  static const std::string dummy;
1506  return dummy;
1507  }
1508 
1509  void REvent::getNames(const std::string& targetClassName,
1510  std::vector<std::string>& vkeys,
1511  bool metadata) const {
1512  // The results go in here
1513  std::set<std::string> keys;
1514 
1515  // Get list of branches from
1516  // the input metadata tree or input tree
1517  std::vector<TObjArray*> fullListOfBranches = {};
1518  if (metadata){
1519  if (m_inMetaTree){
1520  // No friend tree expected for metadata tree
1521  ::Info("xAOD::REvent::getNames", "scanning input objects");
1522  // Only add the list of branches of the metadata tree
1523  fullListOfBranches.push_back(m_inMetaTree->GetListOfBranches());
1524  }
1525  }
1526  else {
1527  ::Error("xAOD::REvent::getNames", "Cannot (yet) get names for event object of typename %s",
1528  targetClassName.c_str());
1529  return;
1530  }
1531 
1532 
1533 
1534  // RDS: assuming meta data is available. Otherwise, we need to find equivalent of all the branch names
1535  // else {
1536  // if (m_inTree){
1537  // ::Info("xAOD::REvent::getNames", "scanning input objects");
1538  // // Add the list of branches of the main tree
1539  // fullListOfBranches.push_back(m_inTree->GetListOfBranches());
1540  // // If input tree has friend trees
1541  // // add as well the list of friend tree branches
1542  // if (m_inTree->GetListOfFriends()){
1543  // // Get the list of friends
1544  // TList *fList = m_inTree->GetListOfFriends();
1545  // // Loop over friend elements
1546  // for (TObject * feObj : *fList){
1547  // if (feObj){
1548  // // Get corresponding friend tree
1549  // TTree *friendTree = dynamic_cast<TFriendElement*>(feObj)->GetTree();
1550  // // Add list of branches of the friend tree
1551  // fullListOfBranches.push_back(friendTree->GetListOfBranches());
1552  // }
1553  // }
1554  // }
1555  // }
1556  // }
1557 
1558  // Loop over all list of branches (if any)
1559  for (const TObjArray * in : fullListOfBranches){
1560  // Loop over all branches inside the current list of branches
1561  for ( Int_t index = 0; index < in->GetEntriesFast(); ++index ) {
1562  const TObject * obj = in->At(index);
1563  if ( ! obj ) continue;
1564  const TBranch * element = dynamic_cast<const TBranch*>(obj);
1565  if (!element) {
1566  ::Error("xAOD::REvent::getNames", "Failure inspecting input objects");
1567  break;
1568  }
1569  std::string objClassName = element->GetClassName();
1570  std::string key = obj->GetName();
1571  ::Info("xAOD::REvent::getNames",
1572  "Inspecting %s / %s",
1573  objClassName.c_str(), key.c_str());
1574  if (objClassName == targetClassName) {
1575  ::Info("xAOD::REvent::getNames",
1576  "Matched %s to key %s",
1577  targetClassName.c_str(), key.c_str());
1578  keys.insert(std::move(key));
1579  }
1580  }
1581  }
1582 
1583  const Object_t& inAux = ( metadata ?
1585 
1586  ::Info("xAOD::REvent::getNames",
1587  "scanning input Aux objects for %s", targetClassName.c_str());
1588  for( const auto& object : inAux ) {
1589  // All metadata objects should be held by TObjectManager objects.
1590  // Anything else is an error.
1591  TObjectManager* mgr = dynamic_cast< TObjectManager* >( object.second );
1592  if ( ! mgr ) continue;
1593  const std::string& objClassName = mgr->holder()->getClass()->GetName();
1594  const std::string& key = object.first;
1595  ::Info("xAOD::REvent::getNames",
1596  "Inspecting %s / %s",
1597  objClassName.c_str(), key.c_str());
1598  if (objClassName == targetClassName) {
1599  ::Info("xAOD::REvent::getNames",
1600  "Matched %s to key %s",
1601  targetClassName.c_str(), key.c_str());
1602  keys.insert(key);
1603  }
1604  }
1605 
1606 
1607  // check output objects
1608  TTree *tree = ( metadata ? nullptr : m_outTree );
1609  if (tree) {
1610  const TObjArray * out = tree->GetListOfBranches();
1611  ::Info("xAOD::REvent::getNames", "scanning output objects");
1612 
1613  for ( Int_t index = 0; index < out->GetEntriesFast(); ++index ) {
1614  const TObject * obj = out->At(index);
1615  if ( ! obj ) continue;
1616  const TBranch * element = dynamic_cast<const TBranch*>(obj);
1617  if (!element) {
1618  ::Error("xAOD::REvent::getNames", "Failure inspecting input objects");
1619  break;
1620  }
1621  std::string objClassName = element->GetClassName();
1622  std::string key = obj->GetName();
1623  ::Info("xAOD::REvent::getNames",
1624  "Inspecting %s / %s",
1625  objClassName.c_str(), key.c_str());
1626  if (objClassName == targetClassName) {
1627  ::Info("xAOD::REvent::getNames",
1628  "Matched %s to key %s",
1629  targetClassName.c_str(), key.c_str());
1630  keys.insert(key);
1631  }
1632  }
1633  } else {
1634  ::Info("xAOD::REvent::getNames", "no output tree connected");
1635  }
1636 
1637 
1638  const Object_t& outAux = ( metadata ?
1640 
1641  // Search though EventFormat for entries where class matches the provided
1642  // typeName
1643  ::Info("xAOD::REvent::getNames",
1644  "scanning output Aux objects for %s", targetClassName.c_str());
1645  for( const auto& object : outAux ) {
1646  // All metadata objects should be held by TObjectManager objects.
1647  // Anything else is an error.
1648  TObjectManager* mgr = dynamic_cast< TObjectManager* >( object.second );
1649  if ( ! mgr ) continue;
1650  const std::string& objClassName = mgr->holder()->getClass()->GetName();
1651  const std::string& key = object.first;
1652  ::Info("xAOD::REvent::getNames",
1653  "Inspecting %s / %s",
1654  objClassName.c_str(), key.c_str());
1655  if (objClassName == targetClassName) {
1656  ::Info("xAOD::REvent::getNames",
1657  "Matched %s to key %s",
1658  targetClassName.c_str(), key.c_str());
1659  keys.insert(key);
1660  }
1661  }
1662 
1663  vkeys.insert(vkeys.end(), keys.begin(), keys.end());
1664  }
1665 
1673  const std::string& REvent::getName( SG::sgkey_t hash ) const {
1674 
1675  // If the branch is known from the input:
1676  if( m_inputEventFormat.exists( hash ) ) {
1677  return m_inputEventFormat.get( hash )->branchName();
1678  }
1679 
1680  // If the branch is known on the output:
1681  if( m_outputEventFormat &&
1683  return m_outputEventFormat->get( hash )->branchName();
1684  }
1685 
1686  // If this is an object in the active store:
1687  const TStore* store = TActiveStore::store();
1688  if( store && store->contains( hash ) ) {
1689  return store->getName( hash );
1690  }
1691 
1692  // If it is unknown:
1693  static const std::string dummy;
1694  return dummy;
1695  }
1696 
1708  const std::type_info& ti ) {
1709 
1710  // Get a string name for this key:
1711  const std::string& name = getName( key );
1712  if( ! name.length() ) {
1713  return 0;
1714  }
1715 
1716  // Forward the call to the function using an std::string key:
1717  return getOutputObject( name, ti );
1718  }
1719 
1732  const std::type_info& ti,
1733  bool silent ) {
1734 
1735  // Get a string name for this key:
1736  const std::string& name = getName( key );
1737  if( ( ! name.length() ) && ( ! silent ) ) {
1738  Warning( "xAOD::REvent::getInputObject",
1739  "Key 0x%08x unknown", key );
1740  return 0;
1741  }
1742 
1743  // Forward the call to the function using an std::string key:
1744  return getInputObject( name, ti, silent );
1745  }
1746 
1755 
1756  // A little sanity check:
1757  if( ! m_inNtupleReader ) {
1758  ::Error( "xAOD::REvent::initStats",
1759  XAOD_MESSAGE( "Function called on an uninitialised "
1760  "object" ) );
1761  return StatusCode::FAILURE;
1762  }
1763 
1764  // Reset the number of input branches information:
1766 
1767  // Loop over the EventFormat information
1770  for( ; itr != end; ++itr ) {
1771 
1772  // Get the name of the branch in question:
1773  const std::string& branchName = itr->second.branchName();
1774 
1775  // If it's an auxiliary container, scan it using RAuxStore:
1776  if( branchName.find( "Aux." ) != std::string::npos ) {
1777 
1778  // But first decide whether it describes a container, or just
1779  // a single object. Since the file may have been written in
1780  // kBranchAccess mode, it's not necessarily a good idea to check
1781  // the type of the auxiliary class. So let's check the interface
1782  // class instead.
1783  //
1784  // Get the name of the interface object/container:
1785  const std::string intName =
1786  branchName.substr( 0, branchName.size() - 4 );
1787 
1788  if( ! m_inputEventFormat.exists( intName ) ) {
1789  // When this happens, it may still be that both the interface and
1790  // the auxiliary container is missing from the file. As we didn't
1791  // check yet whether the auxiliary container is in place or not.
1792  // So, before printing a warning, let's check for this.
1793  // Unfortunately the check is pretty expensive, but this should
1794  // not be performance critical code after all...
1795  ::Bool_t auxFound = kFALSE;
1796  // const std::string dynName = Utils::dynBranchPrefix( branchName );
1797 
1798  // std::vector<TObjArray*> fullListOfBranches = {};
1799  // // Add the list of branches of the main tree
1800  // fullListOfBranches.push_back(m_inTree->GetListOfBranches());
1801  // // If input tree has friend trees
1802  // // add as well the list of friend tree branches
1803  // if (m_inTree->GetListOfFriends()){
1804  // // Get the list of friends
1805  // TList *fList = m_inTree->GetListOfFriends();
1806  // // Loop over friend elements
1807  // for (TObject * feObj : *fList){
1808  // if (feObj){
1809  // // Get corresponding friend tree
1810  // TTree *friendTree = dynamic_cast<TFriendElement*>(feObj)->GetTree();
1811  // // Add list of branches of the friend tree
1812  // fullListOfBranches.push_back(friendTree->GetListOfBranches());
1813  // }
1814  // }
1815  // }
1816 
1817  // for (TObjArray* branches : fullListOfBranches){
1818  // for( Int_t i = 0; i < branches->GetEntriesFast(); ++i ){
1819  // if (!branches->At( i )) continue ;
1820 
1821  // const TString name( branches->At( i )->GetName() );
1822  // if( name.BeginsWith( branchName ) ||
1823  // name.BeginsWith( dynName ) ) {
1824  // auxFound = kTRUE;
1825  // break;
1826  // }
1827  // }
1828  // }
1829  if( auxFound ) {
1830  ::Warning( "xAOD::REvent::initStats",
1831  "Couldn't find interface object/container "
1832  "\"%s\" belonging to branch \"%s\"",
1833  intName.c_str(), branchName.c_str() );
1834  }
1835  continue;
1836  }
1837 
1838  // Get the type of the interface:
1839  const EventFormatElement* el = m_inputEventFormat.get( intName );
1840  ::TClass* cl = ::TClass::GetClass( el->className().c_str() );
1841  if( ( ! cl ) || ( ! cl->IsLoaded() ) ) {
1842  ::Warning( "xAOD::REvent::initStats",
1843  "Couldn't find dictionary for type \"%s\"",
1844  el->className().c_str() );
1845  continue;
1846  }
1847 
1848  // Get the dictionary for the DataVector base class:
1849  static const std::type_info& baseTi = typeid( SG::AuxVectorBase );
1850  static const std::string baseName =
1851  SG::normalizedTypeinfoName( baseTi );
1852  static ::TClass* const baseCl = ::TClass::GetClass( baseName.c_str() );
1853  if( ! baseCl ) {
1854  ::Error( "xAOD::REvent::initStats",
1855  XAOD_MESSAGE( "Couldn't get dictionary for type "
1856  "\"%s\"" ), baseName.c_str() );
1857  return StatusCode::FAILURE;
1858  }
1859 
1860  // The type of the auxiliary store is finally deduced from the
1861  // inheritance of the interface container.
1863  ( cl->InheritsFrom( baseCl ) ? RAuxStore::EStructMode::kContainerStore :
1865 
1866  // Scan the branches using a temporary RAuxStore instance:
1867  static constexpr bool TOP_STORE = true;
1868  RAuxStore temp( branchName, TOP_STORE, mode );
1869  // static constexpr bool PRINT_WARNINGS = false;
1870  RETURN_CHECK( "xAOD::REvent::initStats",
1871  temp.readFrom( *m_inNtupleReader ) );
1872 
1873  // Conveninence variable:
1875 
1876  // Teach the cache about all the branches:
1877  for (SG::auxid_t id : temp.getAuxIDs()) {
1878  stats.branch(branchName, id);
1879  }
1880 
1881  // Increment the number of known branches:
1882  stats.setBranchNum(stats.branchNum() + temp.getAuxIDs().size());
1883  }
1884  // // If it's an interface container:
1885  // else {
1886  // // Try to access the branch:
1887  // const ::TBranch* container =
1888  // m_inTree->GetBranch( branchName.c_str() );
1889  // // If it exists, let's remember it:
1890  // if( container ) {
1891  // IOStats::instance().stats().container( branchName );
1892  // }
1893  // }
1894  }
1895 
1896  // Return gracefully:
1897  return StatusCode::SUCCESS;
1898  }
1899 
1912  void* REvent::getOutputObject( const std::string& key,
1913  const std::type_info& ti,
1914  ::Bool_t metadata ) const {
1915 
1916  // Select which object container to use:
1917  const Object_t& objects = ( metadata ?
1919 
1920  // Check if the object can be found:
1921  Object_t::const_iterator itr = objects.find( key );
1922  if( itr == objects.end() ) {
1923  // Do the following only for event data:
1924  if( ! metadata ) {
1925  // It's not in the event. Let's check if we find it in an active
1926  // TStore object...
1928  if( ( ! store ) || ( ! store->contains( key, ti ) ) ||
1929  store->isConst( key, ti ) ) {
1930  // Nope, not there either...
1931  return 0;
1932  }
1933  // Let's return the object from the TStore:
1934  void* result = store->getObject( key, ti );
1935  return result;
1936  } else {
1937  // For metadata we don't use external resources.
1938  return 0;
1939  }
1940  }
1941 
1942  // If the object is not set in this event yet, we can't continue:
1943  if( ! itr->second->isSet() ) {
1944  return 0;
1945  }
1946 
1947  // If it does exist, check if it's the right kind of object:
1948  TObjectManager* mgr =
1949  dynamic_cast< TObjectManager* >( itr->second );
1950  if( ! mgr ) {
1951  ::Error( "xAOD::REvent::getOutputObject",
1952  XAOD_MESSAGE( "Object of wrong type found for key \"%s\"" ),
1953  key.c_str() );
1954  return 0;
1955  }
1956 
1957  // Ask the holder object for the object of this type:
1958  void* result = mgr->holder()->getAs( ti );
1959  if( ! result ) {
1960  ::Warning( "xAOD::REvent::getOutputObject",
1961  "Couldn't retrieve object as \"%s\"",
1962  Utils::getTypeName( ti ).c_str() );
1963  return 0;
1964  }
1965 
1966  // Return the object:
1967  return result;
1968  }
1969 
1982  const void* REvent::getInputObject( const std::string& key,
1983  const std::type_info& ti,
1984  ::Bool_t silent,
1985  ::Bool_t metadata ) {
1986 
1987  // Check if a name remapping should be applied or not:
1988  std::string keyToUse = key;
1989  auto remap_itr = m_nameRemapping.find( key );
1990  if( ( remap_itr != m_nameRemapping.end() ) &&
1991  ( ! m_inputEventFormat.exists( key ) ) &&
1992  m_inputEventFormat.exists( remap_itr->second ) ) {
1993  keyToUse = remap_itr->second;
1994  }
1995 
1996  // The following catches the cases when we ask for a transient
1997  // ConstDataVector object to be returned as "const DataVector".
1999  if( store && store->contains( keyToUse, ti ) &&
2000  store->isConst( keyToUse, ti ) ) {
2001  const void* result = store->getConstObject( keyToUse, ti );
2002  return result;
2003  }
2004 
2005  // A sanity check before checking for an object from the input file:
2006  if( ( ( ! m_inNtupleReader ) || ( m_entry < 0 ) ) &&
2007  ( ! metadata ) ) {
2008  return 0;
2009  }
2010  if( ( ! m_inMetaTree ) && metadata ) {
2011  return 0;
2012  }
2013 
2014  // Make sure that the requested branch is connected to:
2015  if( metadata ) {
2016  if( ! connectMetaBranch( keyToUse, silent ).isSuccess() ) {
2017  return 0;
2018  }
2019  } else {
2020  if( ! connectBranch( keyToUse, silent ).isSuccess() ) {
2021  return 0;
2022  }
2023  }
2024 
2025  // Select which object container to use:
2026  Object_t& objects = ( metadata ?
2028 
2029  // Access the object's manager:
2030  Object_t::iterator itr = objects.find( keyToUse );
2031  if( itr == objects.end() ) {
2032  ::Fatal( "xAOD::REvent::getInputObject",
2033  XAOD_MESSAGE( "There is an internal logic error in the "
2034  "code..." ) );
2035  return 0;
2036  }
2037 
2038  // Now we separate into metadata using TTree and event data using RNTuple
2039 
2040  const void* result = 0;
2041 
2042  if( ! metadata ) {
2043 
2044  // Event data
2045 
2046  // This has to be an ObjectManager object:
2047  RObjectManager* mgr =
2048  dynamic_cast< RObjectManager* >( itr->second );
2049  if( ! mgr ) {
2050  if( key == keyToUse ) {
2051  ::Error( "xAOD::REvent::getInputObject",
2052  XAOD_MESSAGE( "Object of wrong type found for key "
2053  "\"%s\"" ),
2054  key.c_str() );
2055  } else {
2056  ::Error( "xAOD::REvent::getInputObject",
2057  XAOD_MESSAGE( "Object of wrong type found for key "
2058  "\"%s\"/\"%s\"" ), key.c_str(),
2059  keyToUse.c_str() );
2060  }
2061  return 0;
2062  }
2063 
2064  // Make sure that the current entry is loaded for event data objects:
2065  if( mgr->getEntry() ) {
2066  // Connect the auxiliary store to objects needing it. This call also
2067  // takes care of updating the dynamic store of auxiliary containers,
2068  // when they are getting accessed directly.
2069  if( ! setAuxStore( *mgr ).isSuccess() ) {
2070  ::Error( "xAOD::REvent::getInputObject",
2071  XAOD_MESSAGE( "Failed to set the auxiliary store for "
2072  "%s/%s" ),
2073  mgr->holder()->getClass()->GetName(),
2074  keyToUse.c_str() );
2075  return 0;
2076  }
2077  }
2078 
2079  // Ask the holder object for the object of this type:
2080  result = mgr->holder()->getAsConst( ti, silent );
2081  if( ! result ) {
2082  if( ! silent ) {
2083  ::Warning( "xAOD::REvent::getInputObject",
2084  "Could not retrieve object with key \"%s\" "
2085  "as \"%s\"", keyToUse.c_str(),
2086  Utils::getTypeName( ti ).c_str() );
2087  }
2088  return 0;
2089  }
2090  }
2091  else {
2092 
2093  // metadata
2094 
2095  // Check if metadata is in RNTuple technology - not yet implemented
2096  if ( !m_inMetaTreeIsTTree ) {
2097  ::Error( "xAOD::REvent::getInputObject",
2098  XAOD_MESSAGE( "Metadata is in RNTuple technology which is not yet implemented. key %s" ), key.c_str() );
2099  return 0;
2100  }
2101 
2102  // This has to be an ObjectManager object:
2103  TObjectManager* mgr =
2104  dynamic_cast< TObjectManager* >( itr->second );
2105  if( ! mgr ) {
2106  if( key == keyToUse ) {
2107  ::Error( "xAOD::REvent::getInputObject",
2108  XAOD_MESSAGE( "Object of wrong type found for key "
2109  "\"%s\"" ),
2110  key.c_str() );
2111  } else {
2112  ::Error( "xAOD::REvent::getInputObject",
2113  XAOD_MESSAGE( "Object of wrong type found for key "
2114  "\"%s\"/\"%s\"" ), key.c_str(),
2115  keyToUse.c_str() );
2116  }
2117  return 0;
2118  }
2119 
2120  // Ask the holder object for the object of this type:
2121  result = mgr->holder()->getAsConst( ti, silent );
2122  if( ! result ) {
2123  if( ! silent ) {
2124  ::Warning( "xAOD::REvent::getInputObject",
2125  "Could not retrieve object with key \"%s\" "
2126  "as \"%s\"", keyToUse.c_str(),
2127  Utils::getTypeName( ti ).c_str() );
2128  }
2129  return 0;
2130  }
2131  }
2132 
2133  // We succeeded:
2134  return result;
2135  }
2136 
2138  // Declared public so we can call it from python.
2139  StatusCode REvent::record( void* /*obj*/, const std::string& /*typeName*/,
2140  const std::string& /*key*/) {
2141  // RDS: to be implemented
2142  return StatusCode::SUCCESS;
2143  }
2144 
2145 
2146  // /// This is the function doing the heavy lifting when recording a new
2147  // /// object into the output tree/file. It makes sure that the object is
2148  // /// saved together with all of its dynamic auxiliary data if it has any.
2149  // ///
2150  // /// @param obj A typeless pointer to the object that we want to record
2151  // /// @param typeName The type name of the output object
2152  // /// @param key The key (branch name) of the object to record
2153  // /// @param basketSize The basket size of the output branch
2154  // /// @param splitLevel The split level of the output branch
2155  // /// @param overwrite Flag selecting if it is allowed to overwrite an
2156  // /// already existing object (used internally)
2157  // /// @param metadata Flag selecting if we are writing an event or a
2158  // /// metadata object
2159  // /// @param isOwner Flag selecting if we should take ownership of the object
2160  // /// or not
2161  // /// @returns <code>kTRUE</code> if the operation was successful, or
2162  // /// <code>kFALSE</code> if it was not
2163  // ///
2164  // StatusCode REvent::record( void* obj, const std::string& typeName,
2165  // const std::string& key,
2166  // ::Int_t basketSize, ::Int_t splitLevel,
2167  // ::Bool_t overwrite, ::Bool_t metadata,
2168  // ::Bool_t isOwner ) {
2169 
2170  // // Check if we have an output tree when writing an event:
2171  // if( ! m_outTree && ! metadata ) {
2172  // ::Error( "xAOD::REvent::record",
2173  // XAOD_MESSAGE( "No output tree defined. Did you forget to "
2174  // "call writeTo(...)?" ) );
2175  // return StatusCode::FAILURE;
2176  // }
2177  // assert( m_outputEventFormat != 0 );
2178 
2179  // // If this is metadata, just take ownership of it. The object will only
2180  // // be recorded into the output file when calling finishWritingTo(...).
2181  // if( metadata ) {
2182  // // Check whether we already have such an object:
2183  // if( ( ! overwrite ) &&
2184  // ( m_outputMetaObjects.find( key ) !=
2185  // m_outputMetaObjects.end() ) ) {
2186  // ::Error( "xAOD::REvent::record",
2187  // XAOD_MESSAGE( "Meta-object %s/%s already recorded" ),
2188  // typeName.c_str(), key.c_str() );
2189  // return StatusCode::FAILURE;
2190  // }
2191  // // Check if we have a dictionary for this object:
2192  // TClass* cl = TClass::GetClass( typeName.c_str() );
2193  // if( ! cl ) {
2194  // ::Error( "xAOD::REvent::record",
2195  // XAOD_MESSAGE( "Didn't find dictionary for type: %s" ),
2196  // typeName.c_str() );
2197  // return StatusCode::FAILURE;
2198  // }
2199  // // Let's create a holder for the object:
2200  // THolder* hldr = new THolder( obj, cl, isOwner );
2201  // TObjectManager* mgr =
2202  // new TObjectManager( 0, hldr, m_auxMode == kAthenaAccess );
2203  // m_outputMetaObjects[ key ] = mgr;
2204  // // We're done. The rest will be done later on.
2205  // return StatusCode::SUCCESS;
2206  // }
2207 
2208  // // Check if we accessed this object on the input. If yes, then this
2209  // // key may not be used for recording.
2210  // if( ( ! overwrite ) &&
2211  // ( m_inputObjects.find( key ) != m_inputObjects.end() ) ) {
2212  // ::Error( "xAOD::REvent::record",
2213  // XAOD_MESSAGE( "Object %s/%s already accessed from the input, "
2214  // "can't be overwritten in memory" ),
2215  // typeName.c_str(), key.c_str() );
2216  // return StatusCode::FAILURE;
2217  // }
2218 
2219  // // Override the default 0 split level with a split level of 1 for
2220  // // auxiliary container objects.
2221  // if( ( splitLevel == 0 ) &&
2222  // ( key.find( "Aux." ) == ( key.size() - 4 ) ) ) {
2223  // splitLevel = 1;
2224  // }
2225 
2226  // // Check if we need to add it to the event record:
2227  // Object_t::iterator vitr = m_outputObjects.find( key );
2228  // if( vitr == m_outputObjects.end() ) {
2229 
2230  // // Check if we have a dictionary for this object:
2231  // TClass* cl = TClass::GetClass( typeName.c_str() );
2232  // if( ! cl ) {
2233  // ::Error( "xAOD::REvent::record",
2234  // XAOD_MESSAGE( "Didn't find dictionary for type: %s" ),
2235  // typeName.c_str() );
2236  // return StatusCode::FAILURE;
2237  // }
2238 
2239  // // Check if this is a new object "type" or not:
2240  // if( ! m_outputEventFormat->exists( key ) ) {
2241  // m_outputEventFormat->add( EventFormatElement( key, cl->GetName(),
2242  // "", getHash( key ) ) );
2243  // }
2244 
2245  // // Let's create a holder for the object:
2246  // THolder* hldr = new THolder( obj, cl, isOwner );
2247  // TObjectManager* mgr =
2248  // new TObjectManager( 0, hldr, m_auxMode == kAthenaAccess );
2249  // m_outputObjects[ key ] = mgr;
2250 
2251  // // ... and let's add it to the output TTree:
2252  // *( mgr->branchPtr() ) =
2253  // m_outTree->Branch( key.c_str(), cl->GetName(),
2254  // hldr->getPtr(), basketSize, splitLevel );
2255  // if( ! mgr->branch() ) {
2256  // ::Error( "xAOD::REvent::record",
2257  // XAOD_MESSAGE( "Failed to create branch \"%s\" out of "
2258  // "type \"%s\"" ),
2259  // key.c_str(), cl->GetName() );
2260  // // Clean up:
2261  // hldr->setOwner( kFALSE );
2262  // delete mgr;
2263  // return StatusCode::FAILURE;
2264  // }
2265 
2266  // // Set up the saving of all the dynamic auxiliary properties
2267  // // of the object if it has any:
2268  // RETURN_CHECK( "xAOD::REvent::record",
2269  // putAux( *m_outTree, *mgr, basketSize, splitLevel,
2270  // kFALSE ) );
2271 
2272  // // Return at this point, as we don't want to run the rest of
2273  // // the function's code:
2274  // return StatusCode::SUCCESS;
2275  // }
2276 
2277  // // Access the object manager:
2278  // TObjectManager* omgr = dynamic_cast< TObjectManager* >( vitr->second );
2279  // if( ! omgr ) {
2280  // ::Error( "xAOD::REvent::record",
2281  // XAOD_MESSAGE( "Manager object of the wrong type "
2282  // "encountered" ) );
2283  // return StatusCode::FAILURE;
2284  // }
2285 
2286  // // Check that the type of the object matches that of the previous
2287  // // object:
2288  // if( typeName != omgr->holder()->getClass()->GetName() ) {
2289  // // This may still be, when the ROOT dictionary name differs from the
2290  // // "simple type name" known to C++. So let's get the ROOT name of the
2291  // // new type:
2292  // TClass* cl = TClass::GetClass( typeName.c_str() );
2293  // if( ( ! cl ) || ::strcmp( cl->GetName(),
2294  // omgr->holder()->getClass()->GetName() ) ) {
2295  // ::Error( "xAOD::REvent::record",
2296  // XAOD_MESSAGE( "For output key \"%s\" the previous type "
2297  // "was \"%s\", the newly requested type is "
2298  // "\"%s\"" ),
2299  // key.c_str(), omgr->holder()->getClass()->GetName(),
2300  // typeName.c_str() );
2301  // return StatusCode::FAILURE;
2302  // }
2303  // }
2304 
2305  // // Replace the managed object:
2306  // omgr->setObject( obj );
2307 
2308  // // Replace the auxiliary objects:
2309  // return putAux( *m_outTree, *omgr, basketSize, splitLevel, kFALSE );
2310  // }
2311 
2312  // /// This function is used internally when copying an object with its
2313  // /// auxiliary store from the input file, and branch access mode is
2314  // /// activated for the event object.
2315  // ///
2316  // /// The assumption is that the store object already knows what prefix
2317  // /// it should be using. The key parameter only specifies under what
2318  // /// ID the object should be handled in the output object list.
2319  // ///
2320  // /// @param store The store object to connect to the output
2321  // /// @param key The "key" with which to record the object
2322  // /// @param basketSize The basket size of the output branches
2323  // /// @param splitLevel The split level of the output branches
2324  // /// @returns <code>kTRUE</code> if the operation was successful, or
2325  // /// <code>kFALSE</code> if it was not
2326  // ///
2327  // StatusCode REvent::record( TAuxStore* store, const std::string& key,
2328  // ::Int_t /*basketSize*/, ::Int_t /*splitLevel*/,
2329  // ::Bool_t ownsStore ) {
2330 
2331  // // Check if we have an output tree:
2332  // if( ! m_outTree ) {
2333  // ::Error( "xAOD::REvent::record",
2334  // XAOD_MESSAGE( "No output tree defined. Did you forget to "
2335  // "call writeTo(...)?" ) );
2336  // return StatusCode::FAILURE;
2337  // }
2338 
2339  // // Check if we have a filtering rule for this key:
2340  // const std::set< std::string >* filter = 0;
2341  // auto filter_itr = m_auxItemList.find( key );
2342  // if( filter_itr != m_auxItemList.end() ) {
2343  // filter = &( filter_itr->second );
2344  // }
2345 
2346  // // Check if we need to add it to the event record:
2347  // Object_t::iterator vitr = m_outputObjects.find( key );
2348  // if( vitr == m_outputObjects.end() ) {
2349 
2350  // // Configure the object for variable filtering:
2351  // if( filter ) {
2352  // store->selectAux( *filter );
2353  // }
2354  // // Tell the object where to write its contents:
2355  // RETURN_CHECK( "xAOD::REvent::record", store->writeTo( *m_outTree ) );
2356  // // Record it to the output list:
2357  // TAuxManager* mgr = new TAuxManager( store, ownsStore );
2358  // m_outputObjects[ key ] = mgr;
2359 
2360  // // We're done:
2361  // return StatusCode::SUCCESS;
2362  // }
2363 
2364  // // Check if the output has the right store:
2365  // if( vitr->second->object() == store ) {
2366  // // We're done already:
2367  // return StatusCode::SUCCESS;
2368  // }
2369 
2370  // // If not, update the output manager. This can happen when we copy
2371  // // objects from the input to the output files, and we process
2372  // // multiple input files.
2373 
2374  // // Check if the output manager is of the right type:
2375  // TAuxManager* mgr = dynamic_cast< TAuxManager* >( vitr->second );
2376  // if( ! mgr ) {
2377  // ::Error( "xAOD::REvent::record",
2378  // XAOD_MESSAGE( "Output object with key %s already exists, "
2379  // "and is not of type TAuxStore" ),
2380  // key.c_str() );
2381  // return StatusCode::FAILURE;
2382  // }
2383 
2384  // // Configure the object for variable filtering:
2385  // if( filter ) {
2386  // store->selectAux( *filter );
2387  // }
2388 
2389  // // Connect the auxiliary store to the output tree:
2390  // RETURN_CHECK( "xAOD::REvent::record", store->writeTo( *m_outTree ) );
2391 
2392  // // Update the manager:
2393  // mgr->setObject( store );
2394 
2395  // // Return gracefully:
2396  // return StatusCode::SUCCESS;
2397  // }
2398 
2417  StatusCode REvent::connectBranch( const std::string& key,
2418  ::Bool_t silent ) {
2419 
2420  // A little sanity check:
2421  if( ! m_inNtupleReader ) {
2422  ::Error( "xAOD::REvent::connectBranch",
2423  XAOD_MESSAGE( "Function called on un-initialised object" ) );
2424  return StatusCode::FAILURE;
2425  }
2426 
2427  // Increment the access counter on this container:
2429 
2430  // Check if the branch is already connected:
2431  if( m_inputObjects.find( key ) != m_inputObjects.end() ) {
2432  return StatusCode::SUCCESS;
2433  }
2434  // Check if it was already found to be missing.
2435  if( m_inputMissingObjects.find( key ) != m_inputMissingObjects.end() ) {
2436  if( ! silent ) {
2437  ::Warning( "xAOD::REvent::connectBranch",
2438  "Branch \"%s\" not available on input",
2439  key.c_str() );
2440  }
2441  return StatusCode::RECOVERABLE;
2442  }
2443 
2444  // Check if we have metadata about this branch:
2445  const xAOD::EventFormatElement* ef = 0;
2446 
2447  // RNTuples are missing '.' for <cont>Aux.
2448  auto key_ef = key;
2449  auto key_to_read = key;
2450  if (key.rfind("Aux.") != std::string::npos) {
2451  // key_ef.pop_back();
2452  std::replace(key_to_read.begin(), key_to_read.end(), '.', ':');
2453  }
2454 
2455  if( ! m_inputEventFormat.exists( key_ef ) ) {
2456  if( ! silent ) {
2457  ::Warning( "xAOD::REvent::connectBranch",
2458  "No metadata available for branch: %s ef key %s",
2459  key.c_str(), key_ef.c_str() );
2460  }
2461  } else {
2462  ef = m_inputEventFormat.get( key_ef );
2463  }
2464 
2465 
2466  // Check if the field exists in our input RNTuple: RDS: still need to check if this works for missing fields
2467  if (m_inNtupleReader->GetDescriptor().FindFieldId(key_to_read.c_str()) == ROOT::kInvalidDescriptorId) {
2468  // Field doesn't exist
2469  if( ! silent ) {
2470  ::Warning( "xAOD::REvent::connectBranch", "Key \"%s\" not available on input", key.c_str() );
2471  }
2472  m_inputMissingObjects.insert( key );
2473  return StatusCode::RECOVERABLE;
2474  }
2475 
2476 
2477  // RDS: may need some logic here to get type from inputEventFormat rather than the view
2478  // to read in with automatic schema evolution
2479 
2480  // Get class name from the field
2481  ROOT::RNTupleView<void> view = m_inNtupleReader->GetView<void>(key_to_read.c_str(), nullptr);
2482  std::string className = view.GetField().GetTypeName();
2483 
2484  if( className == "" ) {
2485  if( ef ) {
2486  // This is a fairly weird situation, but let's fall back to taking
2487  // the class name from the metadata object in this case.
2488  className = ef->className();
2489  } else {
2490  ::Error( "xAOD::REvent::connectBranch",
2491  XAOD_MESSAGE( "Couldn't find an appropriate type with a "
2492  "dictionary for branch \"%s\"" ),
2493  key.c_str() );
2494  return StatusCode::FAILURE;
2495  }
2496  }
2497  ::TClass* realClass = ::TClass::GetClass( className.c_str() );
2498  if( ( ( ! realClass ) || ( ! realClass->IsLoaded() ) ) && ef ) {
2499  // We may need to do an actual schema evolution here, in which
2500  // case let's fall back on the class name coming from the metadata
2501  // object.
2502  className = ef->className();
2503  realClass = ::TClass::GetClass( className.c_str() );
2504  }
2505  if( ( ! realClass ) || ( ! realClass->IsLoaded() ) ) {
2506  // Now we're in trouble...
2507  ::Error( "xAOD::REvent::connectBranch",
2508  XAOD_MESSAGE( "Couldn't find an appropriate type with a "
2509  "dictionary for branch \"%s\"" ),
2510  key.c_str() );
2511  return StatusCode::FAILURE;
2512  }
2513 
2514  // Make sure that the current object is the "active event":
2515  setActive();
2516 
2517  // // The data type is always "other" for us:
2518  // static const ::EDataType dataType = kOther_t;
2519 
2520  // Check if the output already has this object. If it does, let's
2521  // assume that we have been copying the object to the output. Which
2522  // means that we need to resume filling the same memory address that
2523  // the output holder points to.
2524  void* ptr = 0;
2525 
2526  // RDS: no output yet
2527 
2528  // Object_t::const_iterator out_itr = m_outputObjects.find( key );
2529  // if( out_itr != m_outputObjects.end() ) {
2530  // // It needs to be an object manager...
2531  // TObjectManager* mgr =
2532  // dynamic_cast< TObjectManager* >( out_itr->second );
2533  // if( ! mgr ) {
2534  // ::Error( "xAOD::REvent::connectBranch",
2535  // XAOD_MESSAGE( "Couldn't access output manager for: %s" ),
2536  // key.c_str() );
2537  // return StatusCode::FAILURE;
2538  // }
2539  // // Get the pointer out of it:
2540  // ptr = mgr->holder()->get();
2541  // }
2542 
2543  // If there is no output object, then let's create one ourselves.
2544  // This is the only way in which we can have the memory management of
2545  // THolder do the right thing with this object.
2546  if( ! ptr ) {
2547  ptr = realClass->New();
2548  }
2549 
2550  // Create the new manager object that will hold this EDM object:
2551  THolder* hldr = new THolder( ptr, realClass );
2552 
2553  RObjectManager* mgr =
2554  new RObjectManager( m_inNtupleReader->GetView<void>(key_to_read.c_str(), hldr->get()),
2555  m_entry, hldr, ( m_auxMode == kAthenaAccess ) );
2556  m_inputObjects[ key ] = mgr;
2557 
2558  // If it's an auxiliary store object, set it up correctly:
2559  if( isAuxStore( *mgr->holder() ) ) {
2560  RETURN_CHECK( "xAOD::REvent::connectBranch",
2561  setUpDynamicStore( *mgr, m_inNtupleReader.get() ) );
2562  // setUpDynamicStore( *mgr, m_inNtupleReader ) );
2563  }
2564 
2565  // Return here if the object can't have an auxiliary store:
2566  if( ! hasAuxStore( *mgr->holder() ) ) return StatusCode::SUCCESS;
2567 
2568  // If there may be an auxiliary object connected to this one,
2569  // connect that as well:
2570  return connectAux( key + "Aux.", isStandalone( *mgr->holder() ) );
2571  // RDS: comment - "Aux:" with ":" is only needed REvent::setAuxStore, I think!
2572  // return connectAux( key + "Aux:", isStandalone( *mgr->holder() ) );
2573  }
2574 
2584  ::Bool_t silent ) {
2585 
2586  // A little sanity check:
2587  if( ! m_inMetaTree ) {
2588  ::Error( "xAOD::REvent::connectMetaBranch",
2589  XAOD_MESSAGE( "Function called on un-initialised object" ) );
2590  return StatusCode::FAILURE;
2591  }
2592 
2593  // Check if the branch is already connected:
2594  if( m_inputMetaObjects.find( key ) != m_inputMetaObjects.end() ) {
2595  return StatusCode::SUCCESS;
2596  }
2597 
2598  // Check if the branch exists in our metadata tree:
2599  ::TBranch* br = m_inMetaTree->GetBranch( key.c_str() );
2600  if( ! br ) {
2601  if( ! silent ) {
2602  ::Warning( "xAOD::REvent::connectMetaBranch",
2603  "Branch \"%s\" not available on input",
2604  key.c_str() );
2605  }
2606  return StatusCode::RECOVERABLE;
2607  }
2608 
2609  // Check that we have an entry in the branch:
2610  if( ! br->GetEntries() ) {
2611  if( ! silent ) {
2612  ::Warning( "xAOD::REvent::connectMetaBranch",
2613  "Branch \"%s\" doesn't hold any data",
2614  key.c_str() );
2615  }
2616  return StatusCode::RECOVERABLE;
2617  }
2618 
2619  // Make sure that it's not in "MakeClass mode":
2620  br->SetMakeClass( 0 );
2621 
2622  // Extract the type of the branch:
2623  ::TClass* cl = 0;
2624  ::EDataType dt = kOther_t;
2625  if( br->GetExpectedType( cl, dt ) || ( ! cl ) ) {
2626  ::Error( "xAOD::REvent::connectMetaBranch",
2627  XAOD_MESSAGE( "Couldn't get the type for metadata "
2628  "branch %s" ), key.c_str() );
2629  return StatusCode::FAILURE;
2630  }
2631 
2632  // Create the object, and all of the managers around it:
2633  void* ptr = cl->New();
2634  THolder* hldr = new THolder( ptr, cl );
2635  TObjectManager* mgr =
2636  new TObjectManager( 0, hldr, m_auxMode == kAthenaAccess );
2637  m_inputMetaObjects[ key ] = mgr;
2638 
2639  // Now try to connect to the branch:
2640  const ::Int_t status = m_inMetaTree->SetBranchAddress( key.c_str(),
2641  hldr->getPtr(),
2642  mgr->branchPtr(),
2643  cl, dt,
2644  kTRUE );
2645  if( status < 0 ) {
2646  ::Error( "xAOD::REvent::connectMetaBranch",
2647  XAOD_MESSAGE( "Couldn't connect variable of type \"%s\" to "
2648  "input branch \"%s\". Return code: %i" ),
2649  cl->GetName(), key.c_str(), status );
2650  // Clean up:
2651  *( hldr->getPtr() ) = 0;
2652  delete mgr;
2653  m_inputMetaObjects.erase( key );
2654  return StatusCode::FAILURE;
2655  }
2656 
2657  // Read in the object:
2658  if( mgr->getEntry() < 0 ) {
2659  ::Error( "xAOD::REvent::connectMetaBranch",
2660  XAOD_MESSAGE( "Couldn't read in metadata object with key "
2661  "\"%s\"" ), key.c_str() );
2662  return StatusCode::FAILURE;
2663  }
2664 
2665  // If it's an auxiliary store object, set it up correctly:
2666  if( isAuxStore( *mgr->holder() ) ) {
2667  RETURN_CHECK( "xAOD::REvent::connectMetaBranch",
2669  }
2670 
2671  // Return here if the object can't have an auxiliary store:
2672  if( ! hasAuxStore( *mgr->holder() ) ) return StatusCode::SUCCESS;
2673 
2674  // If there may be an auxiliary object connected to this one,
2675  // connect that as well:
2676  RETURN_CHECK( "xAOD::REvent::connectMetaBranch",
2677  connectMetaAux( key + "Aux.", isStandalone( *mgr->holder() ) ) );
2678 
2679  // And now connect the first object to its auxiliary store:
2680  RETURN_CHECK( "xAOD::REvent::connectMetaBranch",
2681  setAuxStore( *mgr ) );
2682 
2683  // We succeeded:
2684  return StatusCode::SUCCESS;
2685  } // connectMetaBranch
2686 
2697  StatusCode REvent::connectAux( const std::string& prefix,
2698  ::Bool_t standalone ) {
2699 
2700  // A simple test...
2701  if( ! m_inNtupleReader ) {
2702  ::Error( "xAOD::REvent::connectAux",
2703  XAOD_MESSAGE( "No input tree is available" ) );
2704  return StatusCode::FAILURE;
2705  }
2706 
2707  // RDS: I am not sure how to check if an object of name prefix 'exists' - so skip the check for the moment
2708 
2709  // // Check if we know anything about this auxiliary object:
2710  // if( ( ! m_inNtupleReader->GetView<void>(prefix.c_str(), nullptr) ) &&
2711  // ( m_auxMode == kClassAccess || m_auxMode == kAthenaAccess ) ) {
2712  // // If not, then let's just return right away. Not having
2713  // // an auxiliary object with this name is not an error per se.
2714  // return StatusCode::SUCCESS;
2715  // }
2716 
2717  // Check if the branch is already connected:
2718  if( m_inputObjects.find( prefix ) != m_inputObjects.end() ) {
2719  return StatusCode::SUCCESS;
2720  }
2721 
2722  // Do different things based on the "auxiliary mode" we are in:
2724 
2725  // In "class access mode" let's first connect the concrete auxiliary
2726  // object to the input:
2727  auto result = connectBranch( prefix );
2728  if( ! result.isSuccess() ) {
2729  ::Error( "xAOD::REvent::connectAux", XAOD_MESSAGE( "Failed to execute connectBranch : for prefix %s" ),
2730  prefix.c_str() );
2731  return result;
2732  }
2733 
2734  // Access the object's manager:
2735  Object_t::const_iterator mgr_itr = m_inputObjects.find( prefix );
2736  if( mgr_itr == m_inputObjects.end() ) {
2737  ::Fatal( "xAOD::REvent::connectAux",
2738  XAOD_MESSAGE( "There's a logic error in the code" ) );
2739  }
2740  const RObjectManager* omgr =
2741  dynamic_cast< const RObjectManager* >( mgr_itr->second );
2742  if( ! omgr ) {
2743  ::Fatal( "xAOD::REvent::connectAux",
2744  XAOD_MESSAGE( "There's a logic error in the code" ) );
2745  return StatusCode::FAILURE;
2746  }
2747 
2748  // Check if we can switch out the internal store of this object:
2749  static const TClass* const holderClass =
2750  TClass::GetClass( typeid( SG::IAuxStoreHolder ) );
2751  if( ! omgr->holder()->getClass()->InheritsFrom( holderClass ) ) {
2752  // Nope... So let's just end the journey here.
2753  return StatusCode::SUCCESS;
2754  }
2755 
2756  // Try to get the object as an IAuxStoreHolder:
2757  SG::IAuxStoreHolder* storeHolder =
2758  reinterpret_cast< SG::IAuxStoreHolder* >(
2759  omgr->holder()->getAs( typeid( SG::IAuxStoreHolder ) ) );
2760  if( ! storeHolder ) {
2761  ::Fatal( "xAOD::REvent::connectAux",
2762  XAOD_MESSAGE( "There's a logic error in the code" ) );
2763  }
2764 
2765  // A sanity check to see whether the store's type is in sync with the
2766  // object's type that it will be connected to:
2767  if( ( standalone && ( storeHolder->getStoreType() !=
2769  ( ( ! standalone ) &&
2770  ( storeHolder->getStoreType() !=
2772  ::Error( "xAOD::REvent::connectAux",
2773  XAOD_MESSAGE( "Requested store types inconsistent "
2774  "for: %s" ), prefix.c_str() );
2775  ::Error( "xAOD::REvent::connectAux",
2776  XAOD_MESSAGE( "standalone = %s, getStoreType() = %i" ),
2777  ( standalone ? "kTRUE" : "kFALSE" ),
2778  static_cast< int >( storeHolder->getStoreType() ) );
2779  return StatusCode::FAILURE;
2780  }
2781 
2782  // Return gracefully:
2783  return StatusCode::SUCCESS;
2784 
2785  } else if( m_auxMode == kBranchAccess ) {
2786 
2787  // In "branch access mode" let's create a TAuxStore object, and let
2788  // that take care of the auxiliary store access:
2789  RAuxStore* store =
2790  new RAuxStore( prefix, kTRUE,
2793  // We're using this object to read from the input, it needs to be
2794  // locked:
2795  store->lock();
2797  m_inputObjects[ prefix ] = mgr;
2798 
2799  // Now connect the object to the input tree:
2800  RETURN_CHECK( "xAOD::REvent::connectAux",
2801  store->readFrom( *m_inNtupleReader ) );
2802 
2803  // Return gracefully:
2804  return StatusCode::SUCCESS;
2805  }
2806 
2807  // There was some problem:
2808  ::Error( "xAOD::REvent::connectAux",
2809  XAOD_MESSAGE( "Unknown auxiliary access mode set (%i)" ),
2810  static_cast< int >( m_auxMode ) );
2811  return StatusCode::FAILURE;
2812  }
2813 
2824  ::Bool_t standalone ) {
2825 
2826  // Check if the branch is already connected:
2827  if( m_inputMetaObjects.find( prefix ) != m_inputMetaObjects.end() ) {
2828  return StatusCode::SUCCESS;
2829  }
2830 
2831  // A sanity check:
2832  if( ! m_inMetaTree ) {
2833  ::Fatal( "xAOD::REvent::connectMetaAux",
2834  XAOD_MESSAGE( "Internal logic error detected" ) );
2835  return StatusCode::FAILURE;
2836  }
2837 
2838  // Do different things based on the "auxiliary mode" we are in:
2840 
2841  // In "class access mode" let's first connect the concrete auxiliary
2842  // object to the input:
2843  RETURN_CHECK( "xAOD::REvent::connectMetaAux",
2845 
2846  // Access the object's manager:
2847  Object_t::const_iterator mgr_itr = m_inputMetaObjects.find( prefix );
2848  if( mgr_itr == m_inputMetaObjects.end() ) {
2849  ::Fatal( "xAOD::REvent::connectMetaAux",
2850  XAOD_MESSAGE( "There's a logic error in the code" ) );
2851  }
2852  const TObjectManager* omgr =
2853  dynamic_cast< const TObjectManager* >( mgr_itr->second );
2854  if( ! omgr ) {
2855  ::Fatal( "xAOD::REvent::connectMetaAux",
2856  XAOD_MESSAGE( "There's a logic error in the code" ) );
2857  return StatusCode::FAILURE;
2858  }
2859 
2860  // Check if we can switch out the internal store of this object:
2861  static const TClass* const holderClass =
2862  TClass::GetClass( typeid( SG::IAuxStoreHolder ) );
2863  if( ! omgr->holder()->getClass()->InheritsFrom( holderClass ) ) {
2864  // Nope... So let's just end the journey here.
2865  return StatusCode::SUCCESS;
2866  }
2867 
2868  // Try to get the object as an IAuxStoreHolder:
2869  SG::IAuxStoreHolder* storeHolder =
2870  reinterpret_cast< SG::IAuxStoreHolder* >(
2871  omgr->holder()->getAs( typeid( SG::IAuxStoreHolder ) ) );
2872  if( ! storeHolder ) {
2873  ::Fatal( "xAOD::REvent::connectMetaAux",
2874  XAOD_MESSAGE( "There's a logic error in the code" ) );
2875  }
2876 
2877  // A sanity check to see whether the store's type is in sync with the
2878  // object's type that it will be connected to:
2879  if( ( standalone && ( storeHolder->getStoreType() !=
2881  ( ( ! standalone ) &&
2882  ( storeHolder->getStoreType() !=
2884  ::Error( "xAOD::REvent::connectMetaAux",
2885  XAOD_MESSAGE( "Requested store types inconsistent" ) );
2886  ::Error( "xAOD::REvent::connectMetaAux",
2887  XAOD_MESSAGE( "standalone = %s, getStoreType() = %i" ),
2888  ( standalone ? "kTRUE" : "kFALSE" ),
2889  static_cast< int >( storeHolder->getStoreType() ) );
2890  return StatusCode::FAILURE;
2891  }
2892 
2893  // Return gracefully:
2894  return StatusCode::SUCCESS;
2895 
2896  } else if( m_auxMode == kBranchAccess ) {
2897 
2898  // In "branch access mode" let's create a TAuxStore object, and let
2899  // that take care of the auxiliary store access:
2900  TAuxStore* store =
2901  new TAuxStore( prefix, kTRUE,
2904  // We use this object to read data from the input, it needs to be
2905  // locked:
2906  store->lock();
2907  TAuxManager* mgr = new TAuxManager( store );
2909 
2910  // Now connect the object to the input tree:
2911  RETURN_CHECK( "xAOD::REvent::connectMetaAux",
2912  store->readFrom( *m_inMetaTree ) );
2913 
2914  // Tell the auxiliary store which entry to use:
2915  store->getEntry( 0 );
2916 
2917  // Return gracefully:
2918  return StatusCode::SUCCESS;
2919  }
2920 
2921  // There was some problem:
2922  ::Error( "xAOD::REvent::connectMetaAux",
2923  XAOD_MESSAGE( "Unknown auxiliary access mode set (%i)" ),
2924  static_cast< int >( m_auxMode ) );
2925  return StatusCode::FAILURE;
2926  }
2927 
2928 
2937  StatusCode REvent::setUpDynamicStore( RObjectManager& mgr, ROOT::RNTupleReader* ntupleReader ) {
2938 
2939  // Check if we can call setName(...) on the object:
2940  ::TMethodCall setNameCall;
2941  // Don't use this code in Athena access mode. And just accept that access
2942  // monitoring is disabled in this case...
2943  if( m_auxMode != kAthenaAccess ) {
2944  setNameCall.InitWithPrototype( mgr.holder()->getClass(),
2945  "setName", "const char*" );
2946  if( setNameCall.IsValid() ) {
2947  // Yes, there is such a function. Let's call it with the branch
2948  // name:
2949  const ::TString params =
2950  ::TString::Format( "\"%s\"", mgr.fieldName().c_str() );
2951  const char* charParams = params.Data();
2952  setNameCall.Execute( mgr.holder()->get(), charParams );
2953  } else {
2954  // This is weird. What sort of auxiliary container is this? :-/
2955  ::Warning( "xAOD::REvent::setUpDynamicStore",
2956  "Couldn't find setName(...) function for container %s "
2957  " (type: %s)",
2958  mgr.fieldName().c_str(),
2959  mgr.holder()->getClass()->GetName() );
2960  }
2961  }
2962 
2963  // Check if we can switch out the internal store of this object:
2964  static const TClass* const holderClass =
2965  TClass::GetClass( typeid( SG::IAuxStoreHolder ) );
2966  if( ! mgr.holder()->getClass()->InheritsFrom( holderClass ) ) {
2967  // Nope... So let's just end the journey here.
2968  return StatusCode::SUCCESS;
2969  }
2970 
2971  // Try to get the object as an IAuxStoreHolder:
2972  SG::IAuxStoreHolder* storeHolder =
2973  reinterpret_cast< SG::IAuxStoreHolder* >(
2974  mgr.holder()->getAs( typeid( SG::IAuxStoreHolder ) ) );
2975  if( ! storeHolder ) {
2976  ::Fatal( "xAOD::REvent::setUpDynamicStore",
2977  XAOD_MESSAGE( "There's a logic error in the code" ) );
2978  return StatusCode::FAILURE;
2979  }
2980 
2981  // Create a RAuxStore instance that will read the dynamic variables
2982  // of this container. Notice that the RAuxManager doesn't own the
2983  // RAuxStore object. It will be owned by the SG::IAuxStoreHolder
2984  // object.
2985  RAuxStore* store =
2986  new RAuxStore( mgr.fieldName(), kFALSE,
2987  ( storeHolder->getStoreType() ==
2991  // This object is used to read data from the input, it needs to be
2992  // locked:
2993  store->lock();
2994  RAuxManager* amgr = new RAuxManager( store, m_entry, kFALSE );
2995  m_inputObjects[ mgr.fieldName() +
2996  "Dynamic" ] = amgr;
2997  RETURN_CHECK( "xAOD::REvent::setUpDynamicStore", store->readFrom( *ntupleReader ) );
2998  // Tell the auxiliary store which entry to use. This is essential for
2999  // metadata objects, and non-important for event data objects, which will
3000  // get a possibly different entry loaded in setAuxStore(...).
3001 
3003  RETURN_CHECK( "xAOD::REvent::setUpDynamicStore", store->getEntry( 0, 0 ));
3004 
3005  // Give this object to the store holder:
3006  storeHolder->setStore( store );
3007 
3008  // Return gracefully:
3009  return StatusCode::SUCCESS;
3010 
3011  }
3012 
3013 
3023 
3024  // Check if we can call setName(...) on the object:
3025  ::TMethodCall setNameCall;
3026  // Don't use this code in Athena access mode. And just accept that access
3027  // monitoring is disabled in this case...
3028  if( m_auxMode != kAthenaAccess ) {
3029  setNameCall.InitWithPrototype( mgr.holder()->getClass(),
3030  "setName", "const char*" );
3031  if( setNameCall.IsValid() ) {
3032  // Yes, there is such a function. Let's call it with the branch
3033  // name:
3034  const ::TString params =
3035  ::TString::Format( "\"%s\"", mgr.branch()->GetName() );
3036  const char* charParams = params.Data();
3037  setNameCall.Execute( mgr.holder()->get(), charParams );
3038  } else {
3039  // This is weird. What sort of auxiliary container is this? :-/
3040  ::Warning( "xAOD::REvent::setUpDynamicStore",
3041  "Couldn't find setName(...) function for container %s "
3042  " (type: %s)",
3043  mgr.branch()->GetName(),
3044  mgr.holder()->getClass()->GetName() );
3045  }
3046  }
3047 
3048  // Check if we can switch out the internal store of this object:
3049  static const TClass* const holderClass =
3050  TClass::GetClass( typeid( SG::IAuxStoreHolder ) );
3051  if( ! mgr.holder()->getClass()->InheritsFrom( holderClass ) ) {
3052  // Nope... So let's just end the journey here.
3053  return StatusCode::SUCCESS;
3054  }
3055 
3056  // Try to get the object as an IAuxStoreHolder:
3057  SG::IAuxStoreHolder* storeHolder =
3058  reinterpret_cast< SG::IAuxStoreHolder* >(
3059  mgr.holder()->getAs( typeid( SG::IAuxStoreHolder ) ) );
3060  if( ! storeHolder ) {
3061  ::Fatal( "xAOD::REvent::setUpDynamicStore",
3062  XAOD_MESSAGE( "There's a logic error in the code" ) );
3063  return StatusCode::FAILURE;
3064  }
3065 
3066  // Create a TAuxStore instance that will read the dynamic variables
3067  // of this container. Notice that the TAuxManager doesn't own the
3068  // TAuxStore object. It will be owned by the SG::IAuxStoreHolder
3069  // object.
3070  TAuxStore* store =
3071  new TAuxStore( mgr.branch()->GetName(), kFALSE,
3072  ( storeHolder->getStoreType() ==
3076  // This object is used to read data from the input, it needs to be
3077  // locked:
3078  store->lock();
3079  TAuxManager* amgr = new TAuxManager( store, kFALSE );
3080  m_inputObjects[ std::string( mgr.branch()->GetName() ) +
3081  "Dynamic" ] = amgr;
3082  RETURN_CHECK( "xAOD::REvent::setUpDynamicStore",
3083  store->readFrom( *tree ) );
3084  // Tell the auxiliary store which entry to use. This is essential for
3085  // metadata objects, and non-important for event data objects, which will
3086  // get a possibly different entry loaded in setAuxStore(...).
3087  store->getEntry( 0 );
3088 
3089  // Give this object to the store holder:
3090  storeHolder->setStore( store );
3091 
3092  // Return gracefully:
3093  return StatusCode::SUCCESS;
3094  }
3095 
3107  ::Bool_t metadata ) {
3108 
3109  // Check if we need to do anything:
3110  if( ( ! hasAuxStore( *mgr.holder() ) ) && ( ! isAuxStore( *mgr.holder() ) ) ) {
3111  return StatusCode::SUCCESS;
3112  }
3113 
3114  // Get the branch name of the object in question:
3115  const std::string key = mgr.fieldName();
3116 
3117  // Select which object container to use:
3118  Object_t& objects = ( metadata ?
3120 
3121 
3122  // Look up the auxiliary object's manager:
3123  TVirtualManager* auxMgr = nullptr;
3124  std::string auxKey;
3125  if( isAuxStore( *mgr.holder() ) ) {
3126  auxMgr = &mgr;
3127  auxKey = std::move(key);
3128  } else {
3129  auto itr = objects.find( key + "Aux." );
3130  if( itr == objects.end() ) {
3131  // Apparently there's no auxiliary object for this DV, so let's
3132  // give up:
3133  return StatusCode::SUCCESS;
3134  }
3135  auxMgr = itr->second;
3136  // auxKey = key + "Aux.";
3137  auxKey = key + "Aux:";
3138  }
3139 
3140  if( ! metadata ) {
3141  // Make sure the auxiliary object is up to date:
3142  ::Int_t readBytes = auxMgr->getEntry(m_entry);
3143 
3144  // Check if there is a separate auxiliary object for the dynamic
3145  // variables:
3146  const std::string dynAuxKey = auxKey + "Dynamic";
3147  auto dynAuxMgr = objects.find( dynAuxKey );
3148 
3149  if( ( dynAuxMgr != objects.end() ) &&
3150  ( readBytes || ( m_auxMode == kAthenaAccess ) ||
3151  ( auxMgr == &mgr ) ) ) {
3152 
3153  // Do different things based on the access mode:
3154  if( m_auxMode != kAthenaAccess ) {
3155  // In "normal" access modes just tell the dynamic store object
3156  // to switch to a new event.
3157  dynAuxMgr->second->getEntry();
3158  } else {
3159  // In "Athena mode" this object has already been deleted when
3160  // the main auxiliary store object was switched to the new
3161  // event. So let's re-create it:
3162  if ( metadata ) {
3163  xAOD::TObjectManager& auxMgrRef =
3164  dynamic_cast< xAOD::TObjectManager& >( *auxMgr );
3165  RETURN_CHECK( "xAOD::REvent::setAuxStore", setUpDynamicStore( auxMgrRef, m_inMetaTree ));
3166  }
3167  else {
3168  RObjectManager& auxMgrRef =
3169  dynamic_cast< RObjectManager& >( *auxMgr );
3170  RETURN_CHECK( "xAOD::REvent::setAuxStore", setUpDynamicStore( auxMgrRef, m_inNtupleReader.get() ));
3171  // RETURN_CHECK( "xAOD::REvent::setAuxStore", setUpDynamicStore( auxMgrRef, m_inNtupleReader ));
3172  }
3173  // Now tell the newly created dynamic store object which event
3174  // it should be looking at:
3175  auto dynAuxMgr = objects.find( dynAuxKey );
3176  if( dynAuxMgr == objects.end() ) {
3177  ::Error( "xAOD::REvent::setAuxStore",
3178  XAOD_MESSAGE( "Internal logic error detected" ) );
3179  return StatusCode::FAILURE;
3180  }
3181  dynAuxMgr->second->getEntry();
3182  }
3183  }
3184  }
3185 
3186  // Stop here if we've set up an auxiliary store.
3187  if( auxMgr == &mgr ) {
3188  return StatusCode::SUCCESS;
3189  }
3190 
3191  // Access the auxiliary base class of the object/vector:
3192  SG::AuxVectorBase* vec = 0;
3193  SG::AuxElement* aux = 0;
3194  switch( mgr.holder()->typeKind() ) {
3195  case THolder::DATAVECTOR:
3196  {
3197  void* vvec = mgr.holder()->getAs( typeid( SG::AuxVectorBase ) );
3198  vec = reinterpret_cast< SG::AuxVectorBase* >( vvec );
3199  }
3200  break;
3201  case THolder::AUXELEMENT:
3202  {
3203  void* vaux = mgr.holder()->getAs( typeid( SG::AuxElement ) );
3204  aux = reinterpret_cast< SG::AuxElement* >( vaux );
3205  }
3206  break;
3207  default:
3208  break;
3209  }
3210 
3211  // Check whether index tracking is enabled for the type. If not, then
3212  // we need to fix it...
3213  if( vec && ( ! vec->trackIndices() ) ) {
3214  forceTrackIndices( *vec );
3215  }
3216 
3217  // Check if we were successful:
3218  if( ( ! vec ) && ( ! aux ) ) {
3219  ::Fatal( "xAOD::REvent::setAuxStore",
3220  XAOD_MESSAGE( "Couldn't access class \"%s\" as "
3221  "SG::AuxVectorBase or SG::AuxElement" ),
3222  mgr.holder()->getClass()->GetName() );
3223  }
3224 
3225  // Get the auxiliary store object:
3226  const SG::IConstAuxStore* store = 0;
3227  if( m_auxMode == kBranchAccess ) {
3228  // Get the concrete auxiliary manager:
3229  TAuxManager* amgr = dynamic_cast< TAuxManager* >( auxMgr );
3230  if( ! amgr ) {
3231  ::Fatal( "xAOD::REvent::setAuxStore",
3232  XAOD_MESSAGE( "Auxiliary manager for \"%s\" is not of the "
3233  "right type" ), auxKey.c_str() );
3234  return StatusCode::FAILURE;
3235  }
3236  store = amgr->getConstStore();
3237  // If the store still doesn't know its type, help it now:
3239  const TAuxStore::EStructMode mode = ( vec ?
3242  amgr->getStore()->setStructMode( mode );
3243  }
3244  } else if( m_auxMode == kClassAccess || m_auxMode == kAthenaAccess ) {
3245 
3246  // Get the concrete auxiliary manager:
3247  RObjectManager* omgr =
3248  dynamic_cast< RObjectManager* >( auxMgr );
3249  if( ! omgr ) {
3250  ::Fatal( "xAOD::REvent::setAuxStore",
3251  XAOD_MESSAGE( "Auxiliary manager for \"%s\" is not of the "
3252  "right type" ), auxKey.c_str() );
3253  return StatusCode::FAILURE;
3254  }
3255  void* p = omgr->holder()->getAs( typeid( SG::IConstAuxStore ) );
3256  store = reinterpret_cast< const SG::IConstAuxStore* >( p );
3257 
3258  }
3259  if( ! store ) {
3260  ::Fatal( "xAOD::REvent::setAuxStore",
3261  XAOD_MESSAGE( "Logic error detected in the code" ) );
3262  }
3263 
3264  // Connect the two:
3265  if( vec ) {
3266  vec->setStore( store );
3267  } else if( aux ) {
3268  aux->setStore( store );
3269  } else {
3270  ::Fatal( "xAOD::REvent::setAuxStore",
3271  XAOD_MESSAGE( "Logic error detected in the code" ) );
3272  }
3273 
3274  // We succeeded:
3275  return StatusCode::SUCCESS;
3276  }
3277 
3287 
3288  // Check if we need to do anything:
3289  if( ( ! hasAuxStore( *mgr.holder() ) ) && ( ! isAuxStore( *mgr.holder() ) ) ) {
3290  return StatusCode::SUCCESS;
3291  }
3292 
3293  // Get the branch name of the object in question:
3294  const std::string key = mgr.branch()->GetName();
3295 
3296  // RDS: this should only be called for the metadata store (old: Select which object container to use:)
3298 
3299 
3300  // Look up the auxiliary object's manager:
3301  TVirtualManager* auxMgr = nullptr;
3302  std::string auxKey;
3303  if( isAuxStore( *mgr.holder() ) ) {
3304  auxMgr = &mgr;
3305  auxKey = std::move(key);
3306  } else {
3307  auto itr = objects.find( key + "Aux." );
3308  if( itr == objects.end() ) {
3309  // Apparently there's no auxiliary object for this DV, so let's
3310  // give up:
3311  return StatusCode::SUCCESS;
3312  }
3313  auxMgr = itr->second;
3314  auxKey = key + "Aux.";
3315  }
3316 
3317  // if( ! metadata ) {
3318  // // Make sure the auxiliary object is up to date:
3319  // ::Int_t readBytes = auxMgr->getEntry();
3320 
3321  // // Check if there is a separate auxiliary object for the dynamic
3322  // // variables:
3323  // const std::string dynAuxKey = auxKey + "Dynamic";
3324  // auto dynAuxMgr = objects.find( dynAuxKey );
3325 
3326  // if( ( dynAuxMgr != objects.end() ) &&
3327  // ( readBytes || ( m_auxMode == kAthenaAccess ) ||
3328  // ( auxMgr == &mgr ) ) ) {
3329  // // Do different things based on the access mode:
3330  // if( m_auxMode != kAthenaAccess ) {
3331  // // In "normal" access modes just tell the dynamic store object
3332  // // to switch to a new event.
3333  // dynAuxMgr->second->getEntry();
3334  // } else {
3335  // // In "Athena mode" this object has already been deleted when
3336  // // the main auxiliary store object was switched to the new
3337  // // event. So let's re-create it:
3338  // xAOD::TObjectManager& auxMgrRef =
3339  // dynamic_cast< xAOD::TObjectManager& >( *auxMgr );
3340  // RETURN_CHECK( "xAOD::REvent::setAuxStore",
3341  // setUpDynamicStore( auxMgrRef,
3342  // ( metadata ?
3343  // m_inMetaTree :
3344  // m_inTree ) ) );
3345  // // Now tell the newly created dynamic store object which event
3346  // // it should be looking at:
3347  // auto dynAuxMgr = objects.find( dynAuxKey );
3348  // if( dynAuxMgr == objects.end() ) {
3349  // ::Error( "xAOD::REvent::setAuxStore",
3350  // XAOD_MESSAGE( "Internal logic error detected" ) );
3351  // return StatusCode::FAILURE;
3352  // }
3353  // dynAuxMgr->second->getEntry();
3354  // }
3355  // }
3356  // }
3357 
3358  // Stop here if we've set up an auxiliary store.
3359  if( auxMgr == &mgr ) {
3360  return StatusCode::SUCCESS;
3361  }
3362 
3363  // Access the auxiliary base class of the object/vector:
3364  SG::AuxVectorBase* vec = 0;
3365  SG::AuxElement* aux = 0;
3366  switch( mgr.holder()->typeKind() ) {
3367  case THolder::DATAVECTOR:
3368  {
3369  void* vvec = mgr.holder()->getAs( typeid( SG::AuxVectorBase ) );
3370  vec = reinterpret_cast< SG::AuxVectorBase* >( vvec );
3371  }
3372  break;
3373  case THolder::AUXELEMENT:
3374  {
3375  void* vaux = mgr.holder()->getAs( typeid( SG::AuxElement ) );
3376  aux = reinterpret_cast< SG::AuxElement* >( vaux );
3377  }
3378  break;
3379  default:
3380  break;
3381  }
3382 
3383  // Check whether index tracking is enabled for the type. If not, then
3384  // we need to fix it...
3385  if( vec && ( ! vec->trackIndices() ) ) {
3386  forceTrackIndices( *vec );
3387  }
3388 
3389  // Check if we were successful:
3390  if( ( ! vec ) && ( ! aux ) ) {
3391  ::Fatal( "xAOD::REvent::setAuxStore",
3392  XAOD_MESSAGE( "Couldn't access class \"%s\" as "
3393  "SG::AuxVectorBase or SG::AuxElement" ),
3394  mgr.holder()->getClass()->GetName() );
3395  }
3396 
3397  // Get the auxiliary store object:
3398  const SG::IConstAuxStore* store = 0;
3399  if( m_auxMode == kBranchAccess ) {
3400  // Get the concrete auxiliary manager:
3401  TAuxManager* amgr = dynamic_cast< TAuxManager* >( auxMgr );
3402  if( ! amgr ) {
3403  ::Fatal( "xAOD::REvent::setAuxStore",
3404  XAOD_MESSAGE( "Auxiliary manager for \"%s\" is not of the "
3405  "right type" ), auxKey.c_str() );
3406  return StatusCode::FAILURE;
3407  }
3408  store = amgr->getConstStore();
3409  // If the store still doesn't know its type, help it now:
3411  const TAuxStore::EStructMode mode = ( vec ?
3414  amgr->getStore()->setStructMode( mode );
3415  }
3416  } else if( m_auxMode == kClassAccess || m_auxMode == kAthenaAccess ) {
3417  // Get the concrete auxiliary manager:
3418  TObjectManager* omgr =
3419  dynamic_cast< TObjectManager* >( auxMgr );
3420  if( ! omgr ) {
3421  ::Fatal( "xAOD::REvent::setAuxStore",
3422  XAOD_MESSAGE( "Auxiliary manager for \"%s\" is not of the "
3423  "right type" ), auxKey.c_str() );
3424  return StatusCode::FAILURE;
3425  }
3426  void* p = omgr->holder()->getAs( typeid( SG::IConstAuxStore ) );
3427  store = reinterpret_cast< const SG::IConstAuxStore* >( p );
3428  }
3429  if( ! store ) {
3430  ::Fatal( "xAOD::REvent::setAuxStore",
3431  XAOD_MESSAGE( "Logic error detected in the code" ) );
3432  }
3433 
3434  // Connect the two:
3435  if( vec ) {
3436  vec->setStore( store );
3437  } else if( aux ) {
3438  aux->setStore( store );
3439  } else {
3440  ::Fatal( "xAOD::REvent::setAuxStore",
3441  XAOD_MESSAGE( "Logic error detected in the code" ) );
3442  }
3443 
3444  // We succeeded:
3445  return StatusCode::SUCCESS;
3446  }
3447 
3448 
3449 
3450  // /// This function is used internally to set up the writing of the auxiliary
3451  // /// store variables that were dynamically created on an object. (And not
3452  // /// statically defined to be part of that object.)
3453  // ///
3454  // /// @param outTree The TTree to put the auxiliary branches into
3455  // /// @param mgr The object manager of the output object
3456  // /// @param basketSize Size of the buffer associated with the branches
3457  // /// @param splitLevel The split level to use for the created branches
3458  // /// @param metadata Flag specifying whether the info written is metadata or
3459  // /// not
3460  // /// @returns <code>kTRUE</code> if the setup was successful, or
3461  // /// <code>kFALSE</code> if it was not
3462  // ///
3463  // StatusCode REvent::putAux( ::TTree& outTree, TVirtualManager& vmgr,
3464  // ::Int_t basketSize, ::Int_t splitLevel,
3465  // ::Bool_t metadata ) {
3466 
3467  // // A little sanity check:
3468  // assert( m_outputEventFormat != 0 );
3469 
3470  // // Do the conversion:
3471  // TObjectManager* mgr = dynamic_cast< TObjectManager* >( &vmgr );
3472  // if( ! mgr ) {
3473  // // It's not an error any more when we don't get a TObjectManager.
3474  // return StatusCode::SUCCESS;
3475  // }
3476 
3477  // // Check if we need to do anything here:
3478  // if( ! mgr->holder()->getClass()->InheritsFrom( "SG::IAuxStoreIO" ) ) {
3479  // return StatusCode::SUCCESS;
3480  // }
3481 
3482  // // Get a pointer to the auxiliary store I/O interface:
3483  // SG::IAuxStoreIO* aux =
3484  // reinterpret_cast< SG::IAuxStoreIO* >(
3485  // mgr->holder()->getAs( typeid( SG::IAuxStoreIO ) ) );
3486  // if( ! aux ) {
3487  // ::Fatal( "xAOD::REvent::putAux",
3488  // XAOD_MESSAGE( "There is a logic error in the code!" ) );
3489  // }
3490 
3491  // // Check if we have rules defined for which auxiliary properties
3492  // // to write out:
3493  // xAOD::AuxSelection sel;
3494  // if( ! metadata ) {
3495  // auto item_itr = m_auxItemList.find( mgr->branch()->GetName() );
3496  // if( item_itr != m_auxItemList.end() ) {
3497  // sel.selectAux( item_itr->second );
3498  // }
3499  // }
3500 
3501  // // Get the dynamic auxiliary variables held by this object, which
3502  // // were selected to be written:
3503  // const SG::auxid_set_t auxids = sel.getSelectedAuxIDs (aux->getSelectedAuxIDs());
3504 
3505  // // If there are no dynamic auxiliary variables in the object, return
3506  // // right away:
3507  // if( auxids.empty() ) {
3508  // return StatusCode::SUCCESS;
3509  // }
3510 
3511  // // Decide what should be the prefix of all the dynamic branches:
3512  // const std::string dynNamePrefix =
3513  // Utils::dynBranchPrefix( mgr->branch()->GetName() );
3514 
3515  // // Select which container to add the variables to:
3516  // Object_t& objects = ( metadata ? m_outputMetaObjects : m_outputObjects );
3517 
3518  // // This iteration will determine the ordering of branches within
3519  // // the tree, so sort auxids by name.
3520  // const SG::AuxTypeRegistry& r = SG::AuxTypeRegistry::instance();
3521  // typedef std::pair< std::string, SG::auxid_t > AuxVarSort_t;
3522  // std::vector< AuxVarSort_t > varsort;
3523  // varsort.reserve( auxids.size() );
3524  // for( SG::auxid_t id : auxids ) {
3525  // varsort.emplace_back( r.getName( id ), id );
3526  // }
3527  // std::sort( varsort.begin(), varsort.end() );
3528 
3529  // // Extract all the dynamic variables from the object:
3530  // for( const auto& p : varsort ) {
3531 
3532  // // The auxiliary ID:
3533  // const SG::auxid_t id = p.second;
3534 
3535  // // Construct a name for the branch that we will write:
3536  // const std::string brName = dynNamePrefix + p.first;
3537 
3538  // // Try to find the branch:
3539  // Object_t::iterator bmgr = objects.find( brName );
3540 
3541  // // Check if we already know about this variable:
3542  // if( bmgr == objects.end() ) {
3543 
3544  // // Construct the full type name of the variable:
3545  // const std::type_info* brType = aux->getIOType( id );
3546  // if( ! brType ) {
3547  // ::Error( "xAOD::REvent::putAux",
3548  // XAOD_MESSAGE( "No I/O type found for variable %s" ),
3549  // brName.c_str() );
3550  // return StatusCode::FAILURE;
3551  // }
3552  // const std::string brTypeName =
3553  // Utils::getTypeName( *brType );
3554  // std::string brProperTypeName = "<unknown>";
3555 
3556  // // The branch that will hopefully be created:
3557  // ::TBranch* br = 0;
3558 
3559  // // Check if it's a primitive type or not:
3560  // if( strlen( brType->name() ) == 1 ) {
3561 
3562  // // Making the "proper" type name is simple in this case:
3563  // brProperTypeName = brTypeName;
3564 
3565  // // Get the character describing this type for ROOT:
3566  // const char rootType = Utils::rootType( brType->name()[ 0 ] );
3567  // if( rootType == '\0' ) {
3568  // ::Error( "xAOD::REvent::putAux",
3569  // XAOD_MESSAGE( "Type not known for variable \"%s\" "
3570  // "of type \"%s\"" ),
3571  // brName.c_str(), brTypeName.c_str() );
3572  // return StatusCode::FAILURE;
3573  // }
3574 
3575  // // Create the full description of the variable for ROOT:
3576  // std::ostringstream leaflist;
3577  // leaflist << brName << "/" << rootType;
3578 
3579  // // Let's create a holder for this property:
3580  // THolder* hldr = new THolder( aux->getIOData( id ),
3581  // 0, kFALSE );
3582  // TPrimitiveAuxBranchManager* auxmgr =
3583  // new TPrimitiveAuxBranchManager( id, 0, hldr );
3584  // objects[ brName ] = auxmgr;
3585 
3586  // // ... and let's add it to the output TTree:
3587  // *( auxmgr->branchPtr() ) =
3588  // outTree.Branch( brName.c_str(), hldr->get(),
3589  // leaflist.str().c_str(),
3590  // basketSize );
3591  // if( ! auxmgr->branch() ) {
3592  // ::Error( "xAOD::REvent::putAux",
3593  // XAOD_MESSAGE( "Failed to create branch \"%s\" out "
3594  // "of type \"%s\"" ),
3595  // brName.c_str(), brProperTypeName.c_str() );
3596  // // Clean up:
3597  // *( auxmgr->holder()->getPtr() ) = 0;
3598  // delete auxmgr;
3599  // objects.erase( brName );
3600  // return StatusCode::FAILURE;
3601  // }
3602  // br = auxmgr->branch();
3603 
3604  // } else {
3605 
3606  // // Check if we have a dictionary for this type:
3607  // TClass* cl = TClass::GetClass( *brType, kTRUE, kTRUE );
3608  // if( ! cl ) {
3609  // // The dictionary needs to be loaded now. This could be an
3610  // // issue. But let's hope for the best...
3611  // cl = TClass::GetClass( brTypeName.c_str() );
3612  // // If still not found...
3613  // if( ! cl ) {
3614  // ::Error( "xAOD::REvent::putAux",
3615  // XAOD_MESSAGE( "Dictionary not available for "
3616  // "variable \"%s\" of type \"%s\"" ),
3617  // brName.c_str(), brTypeName.c_str() );
3618  // return StatusCode::FAILURE;
3619  // }
3620  // }
3621 
3622  // // The proper type name comes from the dictionary in this case:
3623  // brProperTypeName = cl->GetName();
3624 
3625  // // Let's create a holder for this property:
3626  // THolder* hldr = new THolder( aux->getIOData( id ),
3627  // cl, kFALSE );
3628  // TAuxBranchManager* auxmgr =
3629  // new TAuxBranchManager( id, 0, hldr );
3630  // objects[ brName ] = auxmgr;
3631 
3632  // if (!cl->CanSplit() && strncmp (cl->GetName(), "SG::PackedContainer<", 20) == 0)
3633  // splitLevel = 0;
3634 
3635  // // ... and let's add it to the output TTree:
3636  // *( auxmgr->branchPtr() ) =
3637  // outTree.Branch( brName.c_str(),
3638  // cl->GetName(),
3639  // hldr->getPtr(), basketSize, splitLevel );
3640  // if( ! auxmgr->branch() ) {
3641  // ::Error( "xAOD::REvent::putAux",
3642  // XAOD_MESSAGE( "Failed to create branch \"%s\" out "
3643  // "of type \"%s\"" ),
3644  // brName.c_str(), brProperTypeName.c_str() );
3645  // // Clean up:
3646  // *( auxmgr->holder()->getPtr() ) = 0;
3647  // delete auxmgr;
3648  // objects.erase( brName );
3649  // return StatusCode::FAILURE;
3650  // }
3651  // br = auxmgr->branch();
3652 
3653  // }
3654 
3655  // // If this is not the first event, fill up the already filled
3656  // // events with (empty) content:
3657  // if( outTree.GetEntries() ) {
3658  // void* ptr = br->GetAddress();
3659  // br->SetAddress( 0 );
3660  // for( ::Long64_t i = 0; i < outTree.GetEntries(); ++i ) {
3661  // br->Fill();
3662  // }
3663  // br->SetAddress( ptr );
3664  // }
3665 
3666  // // If all went fine, let's add this branch to the event format
3667  // // metadata:
3668  // if( ! m_outputEventFormat->exists( brName ) ) {
3669  // m_outputEventFormat->add(
3670  // EventFormatElement( brName,
3671  // brProperTypeName,
3672  // mgr->branch()->GetName(),
3673  // getHash( brName ) ) );
3674  // }
3675 
3676  // // We don't need to do the rest:
3677  // continue;
3678  // }
3679 
3680  // // Access the object manager:
3681  // bmgr = objects.find( brName );
3682  // if( bmgr == objects.end() ) {
3683  // ::Fatal( "xAOD::REvent::putAux",
3684  // XAOD_MESSAGE( "There is an internal logic error in the "
3685  // "code..." ) );
3686  // }
3687 
3688  // // Replace the managed object:
3689  // void* nc_data ATLAS_THREAD_SAFE = // we hold non-const pointers but check on retrieve
3690  // const_cast< void* >( static_cast< const void* >( aux->getIOData( id ) ) );
3691  // bmgr->second->setObject( nc_data );
3692  // }
3693 
3694  // // Return gracefully:
3695  // return StatusCode::SUCCESS;
3696  // }
3697 
3706 
3708 
3709  ::Bool_t REvent::hasAuxStore( const THolder& holder ) {
3710 
3711  // The classes whose children can have an auxiliary store attached
3712  // to them:
3713  static const TClass* const dvClass =
3714  ::TClass::GetClass( typeid( SG::AuxVectorBase ) );
3715  static const TClass* const aeClass =
3716  ::TClass::GetClass( typeid( SG::AuxElement ) );
3717 
3718  // Do the check:
3719  return ( holder.getClass()->InheritsFrom( dvClass ) ||
3720  holder.getClass()->InheritsFrom( aeClass ) );
3721  }
3722 
3730  ::Bool_t REvent::isAuxStore( const THolder& holder ) {
3731 
3732  // The classes whose children are considered auxiliary stores:
3733  static const TClass* const storeClass =
3734  ::TClass::GetClass( typeid( SG::IConstAuxStore ) );
3735  static const TClass* const storeHolderClass =
3736  ::TClass::GetClass( typeid( SG::IAuxStoreHolder ) );
3737 
3738  // Do the check:
3739  return ( holder.getClass()->InheritsFrom( storeClass ) ||
3740  holder.getClass()->InheritsFrom( storeHolderClass ) );
3741  }
3742 
3753  ::Bool_t REvent::isStandalone( const THolder& holder ) {
3754 
3755  // The classes whose children can have an auxiliary store attached
3756  // to them:
3757  static const TClass* const dvClass =
3758  TClass::GetClass( typeid( SG::AuxVectorBase ) );
3759  static const TClass* const aeClass =
3760  TClass::GetClass( typeid( SG::AuxElement ) );
3761 
3762  // Do the check:
3763  if( holder.getClass()->InheritsFrom( aeClass ) ) {
3764  return kTRUE;
3765  } else if( holder.getClass()->InheritsFrom( dvClass ) ) {
3766  return kFALSE;
3767  }
3768 
3769  // Some logic error happened:
3770  ::Error( "xAOD::REvent::isStandalone",
3771  XAOD_MESSAGE( "Received type (%s) that can't have an "
3772  "auxiliary store" ),
3773  holder.getClass()->GetName() );
3774  return kFALSE;
3775  }
3776 
3787  ::Bool_t REvent::contains( const std::string& key,
3788  const std::type_info& ti,
3789  ::Bool_t metadata ) {
3790 
3791  return ( getOutputObject( key, ti, metadata ) ||
3792  getInputObject( key, ti, kTRUE, metadata ) );
3793  }
3794 
3806  ::Bool_t REvent::transientContains( const std::string& key,
3807  const std::type_info& ti,
3808  ::Bool_t metadata ) const {
3809 
3810  return getOutputObject( key, ti, metadata );
3811  }
3812 
3815  }
3816 
3817  } // namespace Experimental
3818 
3819 } // namespace xAOD
xAOD::Experimental::REvent::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: REvent.h:492
xAOD::iterator
JetConstituentVector::iterator iterator
Definition: JetConstituentVector.cxx:68
xAOD::Experimental::REvent::transientContains
::Bool_t transientContains(const std::string &key) const
Function checking if an object is already in memory.
xAOD::EventFormat_v1::end
const_iterator end() const
STL-like function for getting the end of the container.
Definition: EventFormat_v1.cxx:163
xAOD::TVirtualEvent
Base interface for getting objects out of the input file.
Definition: TVirtualEvent.h:32
replace
std::string replace(std::string s, const std::string &s2, const std::string &s3)
Definition: hcg.cxx:307
SGTest::store
TestStore store
Definition: TestStore.cxx:23
xAOD::Experimental::REvent::kBranchAccess
@ kBranchAccess
Access auxiliary data branch-by-branch.
Definition: REvent.h:119
CurrentEventStore.h
Hold a pointer to the current event store.
xAOD::Experimental::REvent::m_outputObjects
Object_t m_outputObjects
Collection of all the managed output object.
Definition: REvent.h:494
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
RETURN_CHECK
#define RETURN_CHECK(CONTEXT, EXP)
Helper macro for checking return codes in a compact form in the code.
Definition: ReturnCheck.h:26
xAOD::Experimental::REvent
Tool for accessing xAOD files outside of Athena, version RNTuple.
Definition: REvent.h:105
SG::AuxVectorBase::initAuxVectorBase
void initAuxVectorBase(SG::OwnershipPolicy ownPolicy, SG::IndexTrackingPolicy indexTrackingPolicy)
Initialize index tracking mode.
TEventFormatRegistry.h
IAuxStoreHolder.h
python.trigbs_prescaleL1.ost
ost
Definition: trigbs_prescaleL1.py:104
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.
xAOD::Experimental::REvent::contains
::Bool_t contains(const std::string &key)
Function checking if an object is available from the store.
TPrimitiveAuxBranchManager.h
PowhegControl_ttHplus_NLO.ss
ss
Definition: PowhegControl_ttHplus_NLO.py:83
run.infile
string infile
Definition: run.py:13
LArConditions2Ntuple.objects
objects
Definition: LArConditions2Ntuple.py:64
vtune_athena.format
format
Definition: vtune_athena.py:14
find
std::string find(const std::string &s)
return a remapped string
Definition: hcg.cxx:135
xAOD::Experimental::REvent::m_branchesMutex
upgrade_mutex_t m_branchesMutex
Definition: REvent.h:532
xAOD::Experimental::REvent::removeListener
StatusCode removeListener(TVirtualIncidentListener *listener)
Remove an incident listener object.
Definition: REvent.cxx:790
xAOD::IOStats::stats
ReadStats & stats()
Access the object belonging to the current thread.
Definition: IOStats.cxx:17
xAOD::Experimental::REvent::Object_t
std::unordered_map< std::string, TVirtualManager * > Object_t
Definition of the internal data structure type.
Definition: REvent.h:458
L1CaloPhase1Monitoring.standalone
standalone
Definition: L1CaloPhase1Monitoring.py:139
xAOD::Experimental::REvent::dump
std::string dump()
Function creating a user-readable dump of the current input.
Definition: REvent.cxx:223
xAOD::TAuxManager::getStore
TAuxStore * getStore()
Get a type-specific pointer to the managed object.
Definition: TAuxManager.cxx:100
RAuxManager.h
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:101
TAuxBranchManager.h
xAOD::Experimental::REvent::getEntries
::Long64_t getEntries() const
Get how many entries are available from the current input file(s)
Definition: REvent.cxx:1137
xAOD::Experimental::REvent::EAuxMode
EAuxMode
Auxiliary store "mode".
Definition: REvent.h:118
xAOD::Experimental::REvent::getOutputObject
void * getOutputObject(SG::sgkey_t key, const std::type_info &ti) override
This function is used by the TVirtualEvent interface to access an output object with a given hashed k...
Definition: REvent.cxx:1707
xAOD::TActiveEvent::setEvent
static void setEvent(TVirtualEvent *ptr)
Set the active event pointer.
Definition: TActiveEvent.cxx:21
xAOD::Experimental::RObjectManager
Manager for EDM objects created by ROOT.
Definition: RObjectManager.h:43
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
RAuxStore.h
index
Definition: index.py:1
SG::AuxElement
Base class for elements of a container that can have aux data.
Definition: AuxElement.h:483
xAOD::Experimental::RObjectManager::holder
const THolder * holder() const
Accessor to the Holder object.
Definition: RObjectManager.cxx:36
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
StateLessPT_NewConfig.Format
Format
Definition: StateLessPT_NewConfig.py:149
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::ReadStats::Print
void Print(::Option_t *option="") const
Print information about the collected statistics.
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
xAOD::THolder::get
const void * get() const
Return a typeless const pointer to the held object.
Definition: THolder.cxx:215
SG::ALWAYS_TRACK_INDICES
@ ALWAYS_TRACK_INDICES
Always track indices, regardless of the setting of the ownership policy.
Definition: IndexTrackingPolicy.h:43
python.AthDsoLogger.out
out
Definition: AthDsoLogger.py:70
SG::CurrentEventStore::setStore
static IProxyDict * setStore(IProxyDict *store)
Set the current store.
Definition: CurrentEventStore.cxx:36
xAOD::TDirectoryReset
Helper class for making sure the current directory is preserved.
Definition: TDirectoryReset.h:28
xAOD::RAuxStore
"ROOT @c RNTuple implementation" of IAuxStore
Definition: RAuxStore.h:38
TChainStateTracker.h
NO_SANITIZE_UNDEFINED
#define NO_SANITIZE_UNDEFINED
Definition: no_sanitize_undefined.h:28
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::TActiveStore::store
static TStore * store()
Access the currently active TStore object.
Definition: TActiveStore.cxx:16
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
SG::CurrentEventStore::store
static IProxyDict * store()
Fetch the current store.
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:157
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:39
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
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
xAOD::Experimental::REvent::getEntry
::Int_t getEntry(::Long64_t entry, ::Int_t getall=0)
Function loading a given entry of the input TTree.
Definition: REvent.cxx:1163
xAOD::EventFormatElement::branchName
const std::string & branchName() const
Get the branch/key name.
Definition: EventFormatElement.cxx:30
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
IOStats.h
TVirtualIncidentListener.h
TDirectoryReset.h
xAOD::Experimental::REvent::setPrintEventProxyWarnings
void setPrintEventProxyWarnings(bool)
Function to silence warnings associated with broken element links.
Definition: REvent.cxx:3813
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
PerfStats.h
xAOD::Experimental::REvent::addNameRemap
StatusCode addNameRemap(const std::string &onfile, const std::string &newName)
Add a name re-mapping rule.
Definition: REvent.cxx:834
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
xAOD::EventFormatElement::hash
sgkey_t hash() const
Get the hash belonging to this branch/key.
Definition: EventFormatElement.cxx:48
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::Experimental::REvent::METADATA_TREE_NAME
static const char *const METADATA_TREE_NAME
Name of the metadata tree.
Definition: REvent.h:467
python.checkMetadata.metadata
metadata
Definition: checkMetadata.py:175
BchCleanup.mgr
mgr
Definition: BchCleanup.py:294
xAOD::TActiveEvent::event
static TVirtualEvent * event()
Access the currently active TVirtualEvent object.
Definition: TActiveEvent.cxx:16
CxxUtils::vec
typename vecDetail::vec_typedef< T, N >::type vec
Define a nice alias for the vectorized type.
Definition: vec.h:207
REvent.h
xAOD::Experimental::REvent::m_nameRemapping
std::unordered_map< std::string, std::string > m_nameRemapping
Container name re-mapping rules.
Definition: REvent.h:513
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.
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
ReadStats.h
TAuxStore.h
xAOD::Experimental::REvent::connectMetaBranch
StatusCode connectMetaBranch(const std::string &key, ::Bool_t silent=kFALSE)
Function setting up access to a branch in the metadata tree.
Definition: REvent.cxx:2583
xAOD::Experimental::REvent::getInputObject
const void * getInputObject(SG::sgkey_t key, const std::type_info &ti, bool silent=false) override
Function for retrieving an input object in a non-template way.
Definition: REvent.cxx:1731
xAOD::Experimental::REvent::hasAuxStore
::Bool_t hasAuxStore(const THolder &holder)
RDS: for the three following methods, moving to directly take THolder rather than have one for TObjec...
Definition: REvent.cxx:3709
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:353
SG::OWN_ELEMENTS
@ OWN_ELEMENTS
this data object owns its elements
Definition: OwnershipPolicy.h:17
xAOD::Experimental::REvent::kAthenaAccess
@ kAthenaAccess
Access containers/objects like Athena does.
Definition: REvent.h:121
SG::AuxElement::setStore
void setStore(const SG::IConstAuxStore *store)
Set the store associated with this object.
Definition: AuxElement.cxx:241
IAuxStoreIO.h
Interface providing I/O for a generic auxiliary store.
xAOD::Experimental::REvent::printIOStats
void printIOStats() const
Function printing the I/O statistics of the current process.
Definition: REvent.cxx:278
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
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
vertexingJO_ITK_init.itemList
list itemList
Definition: vertexingJO_ITK_init.py:95
xAOD::Experimental::REvent::m_inputObjects
Object_t m_inputObjects
Collection of all the managed input objects.
Definition: REvent.h:488
xAOD::Experimental::REvent::record
StatusCode record(void *obj, const std::string &typeName, const std::string &key)
Internal function for recording an object into the output.
Definition: REvent.cxx:2139
xAOD::Experimental::REvent::isStandalone
::Bool_t isStandalone(const THolder &holder)
Function checking if an object is standalone (not a container)
Definition: REvent.cxx:3753
CalibDbCompareRT.dummy
dummy
Definition: CalibDbCompareRT.py:59
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
xAOD::Experimental::REvent::getHash
SG::sgkey_t getHash(const std::string &key) const override
Function returning the hash describing an object name.
Definition: REvent.cxx:1433
xAOD::Experimental::REvent::printNameRemap
void printNameRemap() const
Print the current name re-mapping rules.
Definition: REvent.cxx:877
xAOD::ReadStats::setBranchNum
void setBranchNum(::Int_t num)
Set the total number of branches on the input.
Preparation.mode
mode
Definition: Preparation.py:107
xAOD::Experimental::REvent::kUndefinedAccess
@ kUndefinedAccess
Undefined, to be selected by the object.
Definition: REvent.h:122
xAOD::Experimental::REvent::m_outTree
::TTree * m_outTree
The tree that we are writing to.
Definition: REvent.h:485
python.getProblemFolderFromLogs.el
dictionary el
Definition: getProblemFolderFromLogs.py:48
xAOD::Experimental::REvent::connectBranch
StatusCode connectBranch(const std::string &key, ::Bool_t silent=kFALSE)
Function setting up access to a particular branch.
Definition: REvent.cxx:2417
plotmaker.keyName
keyName
Definition: plotmaker.py:145
xAOD::Experimental::REvent::setAuxStore
StatusCode setAuxStore(RObjectManager &mgr, ::Bool_t metadata=kFALSE)
Function connecting a DV object to its auxiliary store.
Definition: REvent.cxx:3106
xAOD::Experimental::REvent::m_inNtupleReader
std::unique_ptr< ROOT::RNTupleReader > m_inNtupleReader
The main event reader: RNTupleReader.
Definition: REvent.h:473
xAOD::IOStats::instance
static IOStats & instance()
Singleton object accessor.
Definition: IOStats.cxx:11
DataVector
Derived DataVector<T>.
Definition: DataVector.h:794
xAOD::Experimental::REvent::m_inputEventFormat
EventFormat m_inputEventFormat
Format of the current input file.
Definition: REvent.h:502
xAOD::Experimental::REvent::CACHE_SIZE
static const ::Int_t CACHE_SIZE
Size of a possible TTreeCache (30 MB)
Definition: REvent.h:463
normalizedTypeinfoName.h
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
xAOD::Experimental::REvent::~REvent
virtual ~REvent()
Destructor.
Definition: REvent.cxx:168
TObjectManager.h
xAOD::Experimental::REvent::setActive
void setActive() const
Set this event object as the currently active one.
Definition: REvent.cxx:704
xAOD::Experimental::REvent::connectMetaAux
StatusCode connectMetaAux(const std::string &prefix, ::Bool_t standalone)
Function setting up access to a set of auxiliary branches for a metadata object.
Definition: REvent.cxx:2823
xAOD::Experimental::REvent::m_listeners
Listener_t m_listeners
Listeners who should be notified when certain incidents happen.
Definition: REvent.h:510
SG::IAuxStoreHolder::setStore
virtual void setStore(IAuxStore *store)=0
Give an auxiliary store object to the holder object.
print
void print(char *figname, TCanvas *c1)
Definition: TRTCalib_StrawStatusPlots.cxx:26
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
xAOD::TVirtualEvent::keys
void keys(std::vector< std::string > &vkeys, bool metadata=false) const
provide list of all keys associated with provided type.
TAuxManager.h
xAOD::RAuxStore::readFrom
StatusCode readFrom(ROOT::RNTupleReader &reader)
Connect the object to an input RNTuple.
Definition: RAuxStore.cxx:615
xAOD::Experimental::REvent::m_auxMode
EAuxMode m_auxMode
The auxiliary access mode.
Definition: REvent.h:470
TActiveEvent.h
xAOD::Experimental::REvent::setAuxItemList
void setAuxItemList(const std::string &containerKey, const std::string &itemList)
Configure which dynamic variables to write out for a given store.
Definition: REvent.cxx:726
xAOD::Experimental::REvent::REvent
REvent(EAuxMode mode=kUndefinedAccess)
Default constructor.
Definition: REvent.cxx:137
xAOD::EventFormat_v1
Event format metadata for xAOD files.
Definition: EventFormat_v1.h:38
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:240
xAOD::Experimental::REvent::setUpDynamicStore
StatusCode setUpDynamicStore(TObjectManager &mgr, ::TTree *tree)
Function adding dynamic variable reading capabilities to an auxiliary store object metadata still use...
Definition: REvent.cxx:3022
xAOD::ReadStats::readContainer
void readContainer(const std::string &name)
Function incrementing the read counter on a specific container.
MakeNewFileFromOldAndSubstitution.newName
dictionary newName
Definition: ICHEP2016/MakeNewFileFromOldAndSubstitution.py:95
xAOD::TObjectManager
Manager for EDM objects created by ROOT.
Definition: TObjectManager.h:29
xAOD::Experimental::REvent::readFrom
StatusCode readFrom(const std::string &fileName)
This function takes care of connecting the event object to a new input file.
Definition: REvent.cxx:292
xAOD::Experimental::REvent::ATLAS_THREAD_SAFE
SG::SGKeyMap< BranchInfo > m_branches ATLAS_THREAD_SAFE
Map from hashed sgkey to BranchInfo.
Definition: REvent.h:535
SG::sgkey_t
uint32_t sgkey_t
Type used for hashed StoreGate key+CLID pairs.
Definition: CxxUtils/CxxUtils/sgkey_t.h:32
xAOD::TAuxManager
Manager for TAuxStore objects.
Definition: TAuxManager.h:33
xAOD::PerfStats::instance
static PerfStats & instance()
Function accessing the singleton instance.
python.LumiBlobConversion.pos
pos
Definition: LumiBlobConversion.py:16
xAOD::Experimental::REvent::addListener
StatusCode addListener(TVirtualIncidentListener *listener)
Register an incident listener object.
Definition: REvent.cxx:754
AuxSelection.h
xAOD::Experimental::REvent::m_entry
::Long64_t m_entry
The entry to look at from the input tree.
Definition: REvent.h:482
DeMoScan.index
string index
Definition: DeMoScan.py:362
xAOD::TStore
A relatively simple transient store for objects created in analysis.
Definition: TStore.h:47
python.trfDecorators.silent
def silent(func)
Redirect stdout/err to /dev/null Useful wrapper to get rid of ROOT verbosity...
Definition: trfDecorators.py:24
xAOD::Experimental::REvent::m_auxItemList
std::unordered_map< std::string, std::set< std::string > > m_auxItemList
Rules for selecting which auxiliary branches to write.
Definition: REvent.h:507
CaloCondBlobAlgs_fillNoiseFromASCII.hash
dictionary hash
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:108
xAOD::Experimental::REvent::m_printEventProxyWarnings
Bool_t m_printEventProxyWarnings
Option to silence common warnings that seem to be harmless.
Definition: REvent.h:516
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:393
xAOD::RAuxManager
Manager for RAuxStore objects.
Definition: RAuxManager.h:27
xAOD::TObjectManager::holder
const THolder * holder() const
Accessor to the Holder object.
Definition: TObjectManager.cxx:82
xAOD::Experimental::REvent::m_inMetaTreeIsTTree
::Bool_t m_inMetaTreeIsTTree
Boolean indicating the technology of the metadata tree, i.e. TTree of RNTuple.
Definition: REvent.h:479
xAOD::Experimental::REvent::clearNameRemap
void clearNameRemap()
Clear the current name re-mapping.
Definition: REvent.cxx:868
THolder.h
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
xAOD::Experimental::REvent::EVENT_RNTUPLE_NAME
static const char *const EVENT_RNTUPLE_NAME
Name of the event tree.
Definition: REvent.h:465
xAOD::Experimental::REvent::kClassAccess
@ kClassAccess
Access auxiliary data using the aux containers.
Definition: REvent.h:120
xAOD::Experimental::REvent::isAuxStore
::Bool_t isAuxStore(const THolder &holder)
Function checking if a given object may be an auxiliary store.
Definition: REvent.cxx:3730
xAOD::details::AuxStoreBase::EStructMode::kUndefinedStore
@ kUndefinedStore
The structure mode is not defined.
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
AthContainers_detail::upgrading_lock
Lock object for taking out upgradable locks.
Definition: threading.h:177
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
no_sanitize_undefined.h
Helper to disable undefined behavior sanitizer for a function.
xAOD::Experimental::REvent::getKey
SG::sgkey_t getKey(const void *obj) const override
Function returning the hash describing a known object.
Definition: REvent.cxx:1455
xAOD::Experimental::REvent::initStats
StatusCode initStats()
Function to initialise the statistics for all Tree content.
Definition: REvent.cxx:1754
xAOD::Experimental::REvent::inputEventFormat
const EventFormat * inputEventFormat() const
RDS: Only valid for TChains, i.e.
Definition: REvent.cxx:1387
jobOptions.fileName
fileName
Definition: jobOptions.SuperChic_ALP2.py:39
PowhegControl_ttFCNC_NLO.params
params
Definition: PowhegControl_ttFCNC_NLO.py:226
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::Experimental::REvent::m_outputEventFormat
EventFormat * m_outputEventFormat
Format of the current output file.
Definition: REvent.h:504
xAOD::Experimental::REvent::m_inputMetaObjects
Object_t m_inputMetaObjects
Collection of all the managed input meta-objects.
Definition: REvent.h:497
xAOD::ReadStats
Class describing the access statistics of a collection of branches.
Definition: ReadStats.h:123
SG::IConstAuxStore
Interface for const operations on an auxiliary store.
Definition: IConstAuxStore.h:64
xAOD::Experimental::REvent::getName
const std::string & getName(const void *obj) const override
Function returning the key describing a known object.
Definition: REvent.cxx:1468
python.PyAthena.obj
obj
Definition: PyAthena.py:132
xAOD::Experimental::REvent::clearListeners
void clearListeners()
Remove all listeners from the object.
Definition: REvent.cxx:814
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::Utils::hash
SG::sgkey_t hash(const std::string &name)
This function provides a hashed version of the key (branch) names used in the xAOD file,...
Definition: Control/xAODRootAccess/Root/Utils.cxx:125
TIncident.h
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:25
xAOD::Experimental::REvent::name
const std::string & name() const override
Get the name of the instance.
Definition: REventProxyDict.cxx:463
LArL1Calo_ComputeHVCorr.className
className
Definition: LArL1Calo_ComputeHVCorr.py:135
python.TransformConfig.attributes
def attributes(self)
Definition: TransformConfig.py:383
TActiveStore.h
LheEventFiller_Common.ef
ef
Definition: SFGen_i/share/common/LheEventFiller_Common.py:7
xAOD::Experimental::REvent::m_inMetaTree
::TTree * m_inMetaTree
Pointer to the metadata tree in the input file.
Definition: REvent.h:476
xAOD::Experimental::REvent::m_outputMetaObjects
Object_t m_outputMetaObjects
Collection of all the managed output meta-objects.
Definition: REvent.h:499
TStore.h
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
xAOD::Experimental::REvent::auxMode
EAuxMode auxMode() const
Get what auxiliary access mode the object was constructed with.
Definition: REvent.cxx:209
AuxElement.h
Base class for elements of a container that can have aux data.
xAOD::Experimental::REvent::getNames
void getNames(const std::string &targetClassName, std::vector< std::string > &vkeys, bool metadata=false) const override
Function determining the list keys associated with a type name.
Definition: REvent.cxx:1509
RObjectManager.h
xAOD::Experimental::REvent::connectAux
StatusCode connectAux(const std::string &prefix, ::Bool_t standalone)
Function setting up access to a set of auxiliary branches.
Definition: REvent.cxx:2697
PlotCalibFromCool.br
br
Definition: PlotCalibFromCool.py:355
SG::IAuxStoreHolder::AST_ContainerStore
@ AST_ContainerStore
The store describes a container.
Definition: IAuxStoreHolder.h:68
drawFromPickle.view
view
Definition: drawFromPickle.py:294
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
DataProxy.h