ATLAS Offline Software
Loading...
Searching...
No Matches
MakeTransientTree.cxx
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3//
4
5// System include(s):
6#include <cstring>
7#include <iostream>
8#include <memory>
9
10// ROOT include(s):
11#include <TFile.h>
12#include <TChain.h>
13#include <TROOT.h>
14#include <TError.h>
15#include <TClass.h>
16#include <TDirectory.h>
17
18// Local include(s):
26
27namespace {
28
46 class TEventNotifier : public ::TObject {
47
48 public:
50 TEventNotifier()
51 : m_tree( 0 ), m_event( 0 ) {}
53 TEventNotifier( ::TTree* tree, xAOD::TEvent* event )
54 : m_tree( tree ), m_event( event ) {}
55
57 void Setup( ::TTree* tree, xAOD::TEvent* event ) {
58 m_tree = tree;
59 m_event = event;
60 return;
61 }
62
64 virtual ::Bool_t Notify() {
65 if( ( ! m_tree ) || ( ! m_event ) ) {
66 ::Error( "TEventNotifier::Notify",
67 XAOD_MESSAGE( "Function called on uninitialised "
68 "object" ) );
69 return kFALSE;
70 }
71 if( ! m_event->readFrom( m_tree ) ) {
72 ::Error( "TEventNotifier::Notify",
73 XAOD_MESSAGE( "Couldn't notify TEvent object of TTree "
74 "update" ) );
75 return kFALSE;
76 }
77 return kTRUE;
78 }
79
80 private:
82 ::TTree* m_tree;
84 xAOD::TEvent* m_event;
85
86 }; // TEventNotifier
87
102 class TTransObjectHolder {
103
104 private:
106 class TVirtualTransObject {
107 public:
109 virtual ~TVirtualTransObject() {}
110 }; // class TVirtualTransObject
111
113 template< typename T >
114 class TTransObject : public TVirtualTransObject {
115 public:
117 TTransObject( std::unique_ptr< T >&& obj )
118 : m_obj( std::move( obj ) ) {}
120 ~TTransObject() ATLAS_NOT_THREAD_SAFE {
121 // If ROOT is already deleted, then at least some of the objects
122 // are probably also deleted by now.
123 if( ! ROOT::Internal::gROOTLocal ) {
124 (void)m_obj.release();
125 }
126 // If we're in global cleanup, then they may also have been deleted.
127 if (TTransObjectHolder::s_inCleanup)
128 (void)m_obj.release();
129 }
130 private:
131 std::unique_ptr< T > m_obj;
132 }; // struct TTransObject
133
134 public:
136 TTransObjectHolder() : m_objects() {}
137
139 template< typename T >
140 void add( std::unique_ptr< T >&& obj ) {
141 m_objects.push_back( std::unique_ptr< TVirtualTransObject >(
142 new TTransObject< T >( std::move( obj ) ) ) );
143 return;
144 }
145
147 void clear() {
148 m_objects.clear();
149 return;
150 }
151
152 // Used to flag that we're cleaning up global objects at the end
153 // of the job.
154 struct Canary
155 {
156 ~Canary() { TTransObjectHolder::s_inCleanup = true; }
157 };
158 private:
160 std::vector< std::unique_ptr< TVirtualTransObject > > m_objects;
161
163 inline static std::atomic<bool> s_inCleanup{false};
164 }; // class TTransObjectHolder
165
166
167} // private namespace
168
169namespace xAOD {
170
172 static ::TTransObjectHolder s_objectHolder;
174 static ::TTransObjectHolder::Canary s_canary;
175
176 //
177 // Forward declare the private functions:
178 //
179 ::TTree* MakeTransientTree ATLAS_NOT_THREAD_SAFE ( TEvent& event, const char* treeName );
180 ::TTree* MakeTransientMetaTree ATLAS_NOT_THREAD_SAFE ( TEvent& event, ::TTree* persMetaTree );
181
182 TTransTrees MakeTransientTrees ATLAS_NOT_THREAD_SAFE ( ::TFile* ifile,
183 const char* treeName,
184 TEvent::EAuxMode mode ) {
185
186 // Create a TEvent object that will take care of retrieving objects
187 // from the persistent trees:
188 std::unique_ptr< TEvent > event( new TEvent( mode ) );
189 if( ! event->readFrom( ifile, kTRUE, treeName ) ) {
190 ::Error( "xAOD::MakeTransientTrees",
191 XAOD_MESSAGE( "Couldn't set up the reading of the input "
192 "file" ) );
193 return TTransTrees( 0, 0 );
194 }
195
196 // Access the metadata tree of the file:
197 ::TTree* metaTree = dynamic_cast< ::TTree* >( ifile->Get( "MetaData" ) );
198 if( ! metaTree ) {
199 ::Error( "xAOD::MakeTransientTrees",
200 XAOD_MESSAGE( "Couldn't access metadata tree \"MetaData\" "
201 "in the input file" ) );
202 return TTransTrees( 0, 0 );
203 }
204
205 // Create the transient tree using this TEvent object:
206 ::TTree* ev = MakeTransientTree( *event, treeName );
207 ::TTree* meta = MakeTransientMetaTree( *event, metaTree );
208
209 // If no problem happened so far, let's put in the TEvent object into
210 // the object holder:
211 s_objectHolder.add( std::move( event ) );
212
213 // Return the tree pointers:
214 return TTransTrees( ev, meta );
215 }
216
217 void ClearTransientTrees ATLAS_NOT_THREAD_SAFE () {
218
219 s_objectHolder.clear();
220 return;
221 }
222
223 ::TTree* MakeTransientTree ATLAS_NOT_THREAD_SAFE ( TEvent& event, const char* treeName ) {
224
225 // Get the input file's format:
226 const EventFormat* ef = event.inputEventFormat();
227 if( ! ef ) {
228 ::Error( "xAOD::MakeTransientTree",
229 XAOD_MESSAGE( "Couldn't get the input file's format "
230 "metadata" ) );
231 return 0;
232 }
233
234 // Remember which directory we are in now:
235 ::TDirectory* dir = gDirectory;
236
237 // Create the transient tree:
238 gROOT->cd();
239 auto eventTree = std::make_unique< xAODTEventTree >( event, treeName );
240
241 // Go back to the original directory:
242 dir->cd();
243
244 // Make sure that the first file/event is loaded at this point.
245 if( event.getEntry( 0 ) < 0 ) {
246 ::Error( "xAOD::MakeTransientTree",
247 XAOD_MESSAGE( "Couldn't load first event" ) );
248 return 0;
249 }
250
251 // Create a branch for each xAOD interface object:
252 EventFormat::const_iterator ef_itr = ef->begin();
253 EventFormat::const_iterator ef_end = ef->end();
254 for( ; ef_itr != ef_end; ++ef_itr ) {
255
256 // Convenience reference:
257 const xAOD::EventFormatElement& efe = ef_itr->second;
258
259 // Just skip all branches ending in "Aux.":
260 if( efe.branchName().rfind( "Aux." ) ==
261 ( efe.branchName().size() - 4 ) ) {
262 continue;
263 }
264 // Also skip dynamic branches:
265 if( efe.parentName() != "" ) {
266 continue;
267 }
268
269 // Don't bother if the branch is not available:
270 if( ! event.m_inTree->GetBranch( efe.branchName().c_str() ) ) {
271 continue;
272 }
273
274 // Check if the class in question is known:
275 ::TClass* cl = ::TClass::GetClass( efe.className().c_str() );
276 if( ! cl ) continue;
277
278 // Don't add auxiliary store objects:
279 if( cl->InheritsFrom( "SG::IConstAuxStore" ) ) {
280 continue;
281 }
282
283 // Check if we have a type-info for this class:
284 const std::type_info* ti = cl->GetTypeInfo();
285 if( ! ti ) {
286 ::Warning( "xAOD::MakeTransientTree",
287 "Couldn't find std::type_info object for type %s "
288 "(key=%s)", cl->GetName(), efe.branchName().c_str() );
289 continue;
290 }
291
292 // Check if the object is actually available on the input:
293 static constexpr bool METADATA = false;
294 if( ! event.contains( efe.branchName(), *ti, METADATA ) ) {
295 continue;
296 }
297
298 // If everything is right, let's make the branch:
299 auto br =
300 std::make_unique< xAODTEventBranch >( *eventTree, event, *ti,
301 efe.branchName().c_str(),
302 efe.className().c_str() );
303 eventTree->AddBranch( std::move( br ) );
304
305 }
306
307 // Grab a simple pointer to the tree:
308 ::TTree* result = eventTree.get();
309 // Now put it into the object store:
310 s_objectHolder.add( std::move( eventTree ) );
311
312 // Return the object that was just created:
313 ::Info( "xAOD::MakeTransientTree",
314 "Created transient tree \"%s\" in ROOT's common memory",
315 treeName );
316 return result;
317 }
318
319 ::TTree* MakeTransientTree ATLAS_NOT_THREAD_SAFE ( ::TFile* ifile, const char* treeName,
320 TEvent::EAuxMode mode ) {
321
322 // Create a TEvent object that will take care of retrieving objects
323 // from the persistent tree:
324 std::unique_ptr< TEvent > event( new TEvent( mode ) );
325 if( ! event->readFrom( ifile, kTRUE, treeName ) ) {
326 ::Error( "xAOD::MakeTransientTree",
327 XAOD_MESSAGE( "Couldn't set up the reading of the input "
328 "file" ) );
329 return 0;
330 }
331
332 // Create the transient tree using this TEvent object:
333 ::TTree* result = MakeTransientTree( *event, treeName );
334
335 // Put the event object into the object store:
336 s_objectHolder.add( std::move( event ) );
337
338 // Return the created tree:
339 return result;
340 }
341
342 ::TTree* MakeTransientTree ATLAS_NOT_THREAD_SAFE ( ::TChain* itree, TEvent::EAuxMode mode ) {
343
344 // Create the objects used by the function:
345 std::unique_ptr< TEvent > event( new TEvent( mode ) );
346 std::unique_ptr< ::TEventNotifier > notifier( new ::TEventNotifier() );
347
348 // Set up the TEvent object that will take care of retrieving objects
349 // from the persistent tree:
350 if( ! event->readFrom( itree ) ) {
351 ::Error( "xAOD::MakeTransientTree",
352 XAOD_MESSAGE( "Couldn't set up the reading of the input "
353 "tree/chain" ) );
354 return 0;
355 }
356
357 // Load the first event, to trigger opening the first input file:
358 if( event->getEntry( 0 ) < 0 ) {
359 ::Error( "xAOD::MakeTransientTree",
360 XAOD_MESSAGE( "Couldn't load event 0 from the chain" ) );
361 return 0;
362 }
363
364 // Set up an object taking care of notifying the TEvent object about
365 // changes in the TChain's status:
366 notifier->Setup( itree, event.get() );
367 itree->SetNotify( notifier.get() );
368
369 // Create the transient tree using this TEvent object:
370 ::TTree* result = MakeTransientTree( *event, itree->GetName() );
371
372 // Put all objects into the object store:
373 s_objectHolder.add( std::move( event ) );
374 s_objectHolder.add( std::move( notifier ) );
375
376 // Return the created tree:
377 return result;
378 }
379
380 ::TTree* MakeTransientMetaTree ATLAS_NOT_THREAD_SAFE ( TEvent& event, ::TTree* persMetaTree ) {
381
382 // Remember which directory we are in now:
383 ::TDirectory* dir = gDirectory;
384
385 // Create the transient metadata tree:
386 gROOT->cd();
387 auto metaTree = std::make_unique< xAODTMetaTree >( event );
388
389 // Go back to the original directory:
390 dir->cd();
391
392 // Loop over the branches of the persistent metadata tree:
393 TObjArray* branches = persMetaTree->GetListOfBranches();
394 for( ::Int_t i = 0; i < branches->GetEntries(); ++i ) {
395
396 // Access the branch object:
397 ::TBranch* br = dynamic_cast< ::TBranch* >( branches->At( i ) );
398 if( ! br ) {
399 ::Error( "xAOD::MakeTransientMetaTree",
400 XAOD_MESSAGE( "Couldn't access branch %i as a TBranch" ),
401 i );
402 continue;
403 }
404
405 // Skip the EventFormat branch. That must not be disturbed by the
406 // generic metadata handling.
407 if( ! strcmp( br->GetName(), "EventFormat" ) ) continue;
408
409 // Check whether we have a dictionary for this type:
410 ::TClass* cl = ::TClass::GetClass( br->GetClassName(), kTRUE, kTRUE );
411 if( ! cl ) continue;
412
413 // Check if we have a type-info for this class:
414 const std::type_info* ti = cl->GetTypeInfo();
415 if( ! ti ) continue;
416
417 // Don't add auxiliary store objects:
418 if( cl->InheritsFrom( "SG::IConstAuxStore" ) ) {
419 continue;
420 }
421
422 // If everything is right, let's make the branch:
423 auto mbr = std::make_unique< xAODTMetaBranch >( *metaTree, event, *ti,
424 br->GetName(),
425 br->GetClassName() );
426 metaTree->AddBranch( std::move( mbr ) );
427 }
428
429 // Grab a simple pointer to the tree:
430 ::TTree* result = metaTree.get();
431 // Now put it into the object store:
432 s_objectHolder.add( std::move( metaTree ) );
433
434 // Return the object that was just created:
435 ::Info( "xAOD::MakeTransientMetaTree",
436 "Created transient metadata tree \"MetaData\" in ROOT's common "
437 "memory");
438 return result;
439 }
440
441 ::TTree* MakeTransientMetaTree ATLAS_NOT_THREAD_SAFE ( ::TFile* ifile,
442 const char* eventTreeName,
443 TEvent::EAuxMode mode ) {
444
445 // Create a TEvent object that will take care of retrieving objects
446 // from the persistent tree:
447 std::unique_ptr< TEvent > event( new TEvent( mode ) );
448 if( ! event->readFrom( ifile, kTRUE, eventTreeName ) ) {
449 ::Error( "xAOD::MakeTransientMetaTree",
450 XAOD_MESSAGE( "Couldn't set up the reading of the input "
451 "file" ) );
452 return 0;
453 }
454
455 // Access the metadata tree directly:
456 ::TTree* metaTree = dynamic_cast< ::TTree* >( ifile->Get( "MetaData" ) );
457 if( ! metaTree ) {
458 ::Error( "xAOD::MakeTransientMetaTree",
459 XAOD_MESSAGE( "Couldn't access metadata tree \"MetaData\" "
460 "in the input file" ) );
461 return 0;
462 }
463
464 // Create the transient tree using this TEvent object:
465 ::TTree* result = MakeTransientMetaTree( *event, metaTree );
466
467 // Put the event object into the object store:
468 s_objectHolder.add( std::move( event ) );
469
470 // Return the created tree:
471 return result;
472 }
473
474 ::TTree* MakeTransientMetaTree ATLAS_NOT_THREAD_SAFE ( ::TChain* ichain,
475 const char* eventTreeName,
476 TEvent::EAuxMode mode ) {
477
478 // Construct a helper TChain object to give to TEvent:
479 std::unique_ptr< ::TChain > helperChain( new ::TChain( eventTreeName ) );
480 ::TObjArray* files = ichain->GetListOfFiles();
481 for( ::Int_t i = 0; i < files->GetEntries(); ++i ) {
482 helperChain->Add( files->At( i )->GetTitle() );
483 }
484
485 // Create a TEvent object that will take care of retrieving objects
486 // from the persistent tree.
487 std::unique_ptr< TEvent > event( new TEvent( mode ) );
488 if( ! event->readFrom( helperChain.get(), kTRUE ) ) {
489 ::Error( "xAOD::MakeTransientMetaTree",
490 XAOD_MESSAGE( "Couldn't set up the reading of the input "
491 "TChain" ) );
492 return 0;
493 }
494
495 // Create the transient tree using this TEvent object:
496 ::TTree* result = MakeTransientMetaTree( *event, ichain );
497
498 // Put the created objects into the object store:
499 s_objectHolder.add( std::move( helperChain ) );
500 s_objectHolder.add( std::move( event ) );
501
502 // Return the created tree:
503 return result;
504 }
505
506} // namespace xAOD
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
#define ATLAS_NOT_THREAD_SAFE
getNoisyStrip() Find noisy strips from hitmaps and write out into xml/db formats
Class describing one branch of the ROOT file.
const std::string & branchName() const
Get the branch/key name.
const std::string & parentName() const
Get the name of the parent auxiliary object.
const std::string & className() const
Get the class name of this branch/key.
KeyedData_t::const_iterator const_iterator
Iterator for looping over the elements of the object.
Tool for accessing xAOD files outside of Athena.
A simple helper class holding both event and metadata transient trees.
Definition TTransTrees.h:29
bool add(const std::string &hname, TKey *tobj)
Definition fastadd.cxx:55
int ev
Definition globals.cxx:25
std::vector< std::string > files
file names and file pointers
Definition hcg.cxx:50
-diff
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
EventFormat_v1 EventFormat
Definition of the current event format version.
Definition EventFormat.h:16
::TTransObjectHolder::Canary s_canary
To flag when we're in global cleanup. Must come after s_objectHolder.
::TTransObjectHolder s_objectHolder
Object managing all the transient objects created on the heap.
void ClearTransientTrees ATLAS_NOT_THREAD_SAFE()
Function cleaning up the managed memory.
TChain * tree