ATLAS Offline Software
Loading...
Searching...
No Matches
xAODEventSelector.cxx
Go to the documentation of this file.
1
2
3/*
4 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
5*/
6
7// xAODEventSelector.cxx
8// Implementation file for class xAODEventSelector
9// Author: Johannes Elmsheuser, Will Buttinger
11
12// STL includes
13#include <sstream>
14#include <string>
15#include <algorithm>
16#include <vector>
17#include <stdint.h>
18
19// ROOT includes
20#include "TROOT.h"
22#include "TClass.h"
23#include "TFile.h"
24#include "TKey.h"
25#include "TLeaf.h"
26
27#include "Gaudi/Property.h"
28
29// Framework includes
30#include "GaudiKernel/FileIncident.h"
31#include "GaudiKernel/IIoComponentMgr.h"
32#include "GaudiKernel/ISvcLocator.h"
33#include "GaudiKernel/ITHistSvc.h"
34#include "GaudiKernel/MsgStream.h"
35#include "GaudiKernel/StatusCode.h"
36#include "GaudiKernel/System.h"
37#include "GaudiKernel/IClassIDSvc.h"
42
43// StoreGate includes
44
45#include "SGTools/BuiltinsClids.h" // to make sure we have their clids
46#include "SGTools/StlMapClids.h" // to make sure we have their clids
47#include "SGTools/StlVectorClids.h" // to make sure we have their clids
50
51// EventInfo includes
52#include "EventInfo/EventInfo.h"
53#include "EventInfo/EventType.h"
54#include "EventInfo/EventID.h"
56
57// Package includes
58#include "xAODEventSelector.h"
59#include "xAODBranchAddress.h"
60#include "RootGlobalsRestore.h"
61
62// xAOD include(s):
63#include "xAODRootAccess/Init.h"
64
65#include "GaudiKernel/ServiceHandle.h"
67#include <map>
68
69
73
74namespace Athena {
75
79class xAODEventContext : public ::IEvtSelector::Context
80{
81public:
85 virtual ~xAODEventContext() {}
87 virtual void* identifier() const override {
88 void* id ATLAS_THREAD_SAFE = const_cast<xAODEventSelector*>(m_evtsel);
89 return id;
90 }
91
92 const std::vector<std::string>& files() const { return m_evtsel->m_inputCollectionsName.value(); }
94 const TFile* file() const { return m_evtsel->m_tfile; }
96 StatusCode setFile ATLAS_NOT_THREAD_SAFE (const std::string& fname) {
97 return const_cast<xAODEventSelector*>(m_evtsel)->setFile(fname);
98 }
99
100 std::size_t fileIndex() const { return m_evtsel->m_collIdx; }
102 int64_t entry() const { return m_evtsel->m_curEvt; }
103
104private:
107};
108
110 ISvcLocator* svcLoc ) :
111 base_class ( name, svcLoc ),
112 m_dataStore( "StoreGateSvc/StoreGateSvc", name ),
113 m_imetaStore( "StoreGateSvc/InputMetaDataStore", name ),
114 m_ometaStore( "StoreGateSvc/MetaDataStore", name ),
115 m_clidsvc ( "ClassIDSvc", name ),
116 m_dictsvc ( "AthDictLoaderSvc", name ),
117 m_incsvc ( "IncidentSvc", name ),
118 m_poolSvc ( "PoolSvc" , name ),
119 m_ppSvc ( "ProxyProviderSvc" , name ),
120 m_nbrEvts ( 0 ),
121 m_curEvt ( 0 ),
122 m_collIdx ( 0 ),
123 m_collEvts ( ),
124 m_needReload (true),
126 m_tevent(NULL),
127 m_tfile(NULL),
129{
130//Properties important to end user:
131 declareProperty( "InputCollections", m_inputCollectionsName,"List of input (ROOT) file names" );
132 declareProperty( "SkipEvents",m_skipEvts = 0,"Number of events to skip at the beginning" );
133 declareProperty( "AccessMode", m_accessMode = -1, "-1 = use TEvent Default; 0 = BranchAccess; 1 = ClassAccess; 2 = AthenaAccess" );
134
135 declareProperty( "FillEventInfo", m_fillEventInfo=false,"If True, will fill old EDM EventInfo with xAOD::EventInfo content, necessary for database reading (IOVDbSvc)");
136
137 declareProperty( "PrintPerfStats", m_printPerfStats=false,"If True, at end of job will print the xAOD perf stats");
138
139//Expert Properties:
140 declareProperty( "EvtStore", m_dataStore, "Store where to publish data");
141 declareProperty( "ProxyProviderSvc" , m_ppSvc , "The ProxyProviderSvc that we should register ourself in and connect the EvtStore to");
142 declareProperty( "InputMetaStore",m_imetaStore, "Store where to publish (input) metadata");
143 declareProperty( "MetaStore",m_ometaStore, "Store where to publish (output) metadata");
144 declareProperty( "TreeName",m_tupleName = "CollectionTree","Name of the TTree to load/read from input file(s)" );
145 declareProperty( "MetaDataTreeName", m_metadataName = "MetaData","Name of the TTree to load/read metadata from input file(s)" );
146
147 declareProperty( "ReadMetaDataWithPool", m_readMetadataWithPool=false, "If true, using POOL to read metadata, will ensure input file is registered with catalog");
148 declareProperty( "printEventProxyWarnings", m_printEventProxyWarnings);
149
150#ifndef XAOD_ANALYSIS
151 declareProperty( "CollectionType", m_collectionType="", "Compability flag for RecExCommon");
152#endif
153
154}
155
156// Destructor
160
162{
163 ATH_MSG_VERBOSE ("Enter xAODEventSelector initialization...");
164
165 CHECK( m_clidsvc.retrieve() );
166 CHECK( m_dictsvc.retrieve() );
167
168 if ( m_tupleName.value().empty() ) {
169 ATH_MSG_ERROR("You have to give a TTree name to read from the ROOT files !");
170 return StatusCode::FAILURE;
171 }
172
173 const std::size_t nbrInputFiles = m_inputCollectionsName.value().size();
174 if ( nbrInputFiles < 1 ) {
175 ATH_MSG_ERROR("You need to give at least 1 input file !!" << endmsg
176 << "(Got [" << nbrInputFiles << "] file instead !)");
177 return StatusCode::FAILURE;
178 } else {
179 ATH_MSG_INFO("Selector configured to read [" << nbrInputFiles << "] file(s)...");
180 }
181
182 ATH_MSG_DEBUG("Calling xAOD::Init...");
183 int old_level = gErrorIgnoreLevel;
184 gErrorIgnoreLevel = kWarning;
185 xAOD::Init().ignore();
186 gErrorIgnoreLevel = old_level;
187 //if using the AthROOTErrorHandlerSvc, need to initialize it once again to give back error handling control to svc
188 if(serviceLocator()->existsService("AthROOTErrorHandlerSvc")) {
189 ServiceHandle<IService> ehSvc("AthROOTErrorHandlerSvc",name());
190 CHECK( ehSvc.retrieve() );
191 CHECK( ehSvc->initialize() ); //gives back control to svc
192 CHECK( ehSvc.release() );
193 }
194 switch(m_accessMode) {
195 case -1: ATH_MSG_INFO("Using DEFAULT xAOD access mode (usually same as CLASS mode)"); break;
196 case 0: ATH_MSG_INFO("Using BRANCH xAOD access mode"); break;
197 case 1: ATH_MSG_INFO("Using CLASS xAOD access mode"); break;
198 case 2: ATH_MSG_INFO("Using ATHENA xAOD access mode"); break;
199 }
200 if(m_accessMode != -1) {
201 m_tevent = new xAOD::xAODTEvent(xAOD::TEvent::EAuxMode(m_accessMode)); //our special class inheriting from xAOD::TEvent
202 } else {
203 m_tevent = new xAOD::xAODTEvent(); //our special class inheriting from xAOD::TEvent
204 }
205 m_tevent->printProxyWarnings(m_printEventProxyWarnings);
206
207 //use the first file to decide if reading metadata with POOL is ok
209 std::unique_ptr<TFile> f( TFile::Open( m_inputCollectionsName.value()[0].c_str() ) );
210 if(!f) {
211 ATH_MSG_ERROR("Failed to open first input file: " << m_inputCollectionsName.value()[0]);
212 return StatusCode::FAILURE;
213 }
214 if(!f->Get("##Shapes")) {
215 ATH_MSG_INFO("First file is not POOL file (e.g. is CxAOD), so reading metadata with xAOD::TEvent instead");
217 }
218 f->Close();
219 }
220
221
222 {
223 // register this service for 'I/O' events
224 ServiceHandle<IIoComponentMgr> iomgr("IoComponentMgr", name());
225 if (!iomgr.retrieve().isSuccess()) {
226 ATH_MSG_FATAL("Could not retrieve IoComponentMgr !");
227 return StatusCode::FAILURE;
228 }
229 if (!iomgr->io_register(this).isSuccess()) {
230 ATH_MSG_FATAL("Could not register myself with the IoComponentMgr !");
231 return StatusCode::FAILURE;
232 }
233 // register input file's names with the I/O manager
234 const std::vector<std::string>& incol = m_inputCollectionsName.value();
235 bool allGood = true;
236 for (std::size_t icol = 0, imax = incol.size(); icol < imax; icol++) {
237 if (!iomgr->io_register(this,
238 IIoComponentMgr::IoMode::READ,
239 incol[icol]).isSuccess()) {
240 ATH_MSG_FATAL("could not register [" << incol[icol] << "] for output !");
241 allGood = false;
242 } else {
243 ATH_MSG_VERBOSE("io_register[" << this->name() << "](" << incol[icol] << ") [ok]");
244 }
245 }
246 if (!allGood) {
247 return StatusCode::FAILURE;
248 }
249 }
250
251 if (!do_init_io().isSuccess()) {
252 return StatusCode::FAILURE;
253 }
254
255 // retrieve event stores
256 // this needs to happen *after* having initialized the i/o
257 // as our branches (which need a valid m_ntuple pointer)
258 // may be asked to be registered as we are a ProxyProvider.
259 // retrieving the event store will poke the ProxyProviderSvc...
260/*
261 if ( !m_dataStore.retrieve().isSuccess() ) {
262 ATH_MSG_ERROR("Could not retrieve [" << m_dataStore.typeAndName() << "] !!");
263 return StatusCode::FAILURE;
264 }
265
266 // ditto for (input) meta data store
267 if (!m_imetaStore.retrieve().isSuccess()) {
268 ATH_MSG_ERROR("Could not retrieve [" << m_imetaStore.typeAndName() << "] !!");
269 return StatusCode::FAILURE;
270 }
271
272 // ditto for (output) meta data store
273 if (!m_ometaStore.retrieve().isSuccess()) {
274 ATH_MSG_ERROR
275 ("Could not retrieve [" << m_ometaStore.typeAndName() << "] !!");
276 return StatusCode::FAILURE;
277 }
278*/
279
280 //ensure the xAODCnvSvc is listed in the EventPersistencySvc
281 ServiceHandle<IProperty> epSvc("EventPersistencySvc",name());
282
283
284 std::vector<std::string> propVal;
285 CHECK( Gaudi::Parsers::parse( propVal , epSvc->getProperty("CnvServices").toString() ) );
286 bool foundSvc(false); bool foundPoolSvc(false);
287 for(const std::string& s : propVal) {
288 if(s=="Athena::xAODCnvSvc") { foundSvc=true; }
289 if(s=="AthenaPoolCnvSvc") { foundPoolSvc=true; } //only need this if in hybrid mode
290 }
291 if(!foundSvc) propVal.push_back("Athena::xAODCnvSvc");
292 if(!foundPoolSvc && m_readMetadataWithPool) propVal.push_back("AthenaPoolCnvSvc");
293
294 if(!foundSvc || (!foundPoolSvc && m_readMetadataWithPool)) {
295 CHECK( epSvc->setProperty("CnvServices", Gaudi::Utils::toString( propVal ) ));
296 }
297
298
299 //we should also add ourself as a proxy provider
300 CHECK( m_ppSvc.retrieve() );
301
302 //ensure the MetaDataSvc is added as a provider first, if we are in hybrid mode
304 std::vector<std::string> propVal;
305 IProperty* prop = dynamic_cast<IProperty*>(&*m_ppSvc);
306 if (!prop) {
307 return StatusCode::FAILURE;
308 }
309 CHECK( Gaudi::Parsers::parse( propVal , prop->getProperty("ProviderNames").toString() ) );
310 bool foundSvc(false);
311 for(const std::string& s : propVal) {
312 if(s=="MetaDataSvc") { foundSvc=true; break; }
313 }
314 if(!foundSvc) {
315 propVal.push_back("MetaDataSvc");
316 IProperty* prop = dynamic_cast<IProperty*>(&*m_ppSvc);
317 if (!prop) {
318 return StatusCode::FAILURE;
319 }
320 CHECK( prop->setProperty("ProviderNames", Gaudi::Utils::toString( propVal ) ));
321 }
322 }
323
324 //now we add ourself as a provider
325 m_ppSvc->addProvider( this );
326 //trigger a reload of proxies in the storegate, which will poke the proxyprovidersvc
327 //not actually needed
328 //CHECK( m_dataStore->loadEventProxies() );
329
330
331 //finally ensure the storegate has our proxy set in it
332 //FIXME: this doesnt seem to allow multi storegates on the fly ???
333 //m_dataStore->setProxyProviderSvc( &*m_ppSvc );
334
335 CHECK( m_ppSvc.release() );
336
337
338 //load the first file .. this is so metadata can be read even if no events present
339 //checked above that there's at least one file
340 CHECK( setFile(m_inputCollectionsName.value()[0]) );
341
342 //first FirstInputFile incident so that input metadata store is populated by MetaDataSvc
343 m_incsvc->fireIncident(FileIncident(name(), "FirstInputFile", m_inputCollectionsName.value()[0]));
344
346
347
348 return StatusCode::SUCCESS;
349}
350
352{
353 // Fire EndInputFile for any file still open (the event loop may end
354 // before the file is fully read).
355 m_inputFileGuard.reset();
356 return StatusCode::SUCCESS;
357}
358
360{
361 ATH_MSG_VERBOSE ("Finalize...");
362 // FIXME: this should be tweaked/updated if/when a selection function
363 // or filtering predicate is applied (one day?)
364 ATH_MSG_INFO ("Total events read: " << (m_nbrEvts - m_skipEvts));
365
366 if(m_printPerfStats) {
369 }
370
371
372 return StatusCode::SUCCESS;
373}
374
376// Const methods:
378
379StatusCode
380xAODEventSelector::next( IEvtSelector::Context& ctx ) const
381{
382 // std::cout << "::next(fidx=" << m_collIdx << ", eidx=" << m_curEvt << ")"
383 // << std::endl;
384 ATH_MSG_DEBUG ("next() : iEvt " << m_curEvt);
385
386 // get evt context
387 xAODEventContext* rctx = dynamic_cast<xAODEventContext*>(&ctx);
388 if ( 0 == rctx ) {
389 ATH_MSG_ERROR ("Could not dyn-cast to xAODEventContext !!");
390 throw GaudiException("xAODEventSelector::next() - Unable to get xAODEventContext","xAODEventSelector",StatusCode::FAILURE);
391 }
392
393
394 const TFile *file = rctx->file();
395 if(file && m_nbrEvts==0) {
396 //fire the BeginInputFile incident for the first file
398 file->GetName(), {},
399 /*endFileName=*/file->GetName());
400 }
401
402 if (!file) { //must be starting another file ...
403 auto& fnames = rctx->files();
404 //std::size_t fidx = rctx->fileIndex();
405 if( rctx->setFile("").isFailure() ) {
406 throw GaudiException("xAODEventSelector::next() - Fatal error when trying to setFile('')","xAODEventSelector",StatusCode::FAILURE);
407 }
408
409 while( m_tevent_entries == 0 ) { //iterate through files until we have one with entries
410 if (m_collIdx < int(rctx->files().size())) {
411 const std::string& fname = fnames[m_collIdx];
412 if( rctx->setFile( fname ).isFailure() ) {
413 throw GaudiException("xAODEventSelector::next() - Fatal error when trying to setFile('" + fname + "')","xAODEventSelector",StatusCode::FAILURE);
414 }
415 ATH_MSG_DEBUG("TEvent entries = " << m_tevent_entries);
416 //fire incident for this file ..
418 rctx->file()->GetName(), {},
419 /*endFileName=*/rctx->file()->GetName());
420 } else {
421 // end of collections
422 return StatusCode::FAILURE; //this is a valid failure ... athena will interpret as 'finished looping'
423 }
424 if( m_tevent_entries==0) m_collIdx++;
425
426
427 } //end of while loop
428
429 }
430
431
432 ATH_MSG_DEBUG("m_curEvt=" << m_curEvt);
433
434 //Infer the local entry (entry of current file) from the global entry
435
436 int64_t global_entry = rctx->entry(); //the actual event counter
437 int64_t entry = global_entry;
438 if (m_collEvts[m_collIdx].min_entries < 0) {
439 // need to trigger collmetadata...
440 const_cast<xAODEventSelector*>(this)->find_coll_idx(entry);
441 }
442 // rctx::entry is the *global* entry number.
443 // we need the local one...
444 entry = global_entry - m_collEvts[m_collIdx].min_entries; //actual entry in the current file
445
446
447
448 if ( m_tevent_entries > entry ) {
449
450 // Load the event:
451 if( m_tevent->getEntry( entry ) < 0 ) {
452 ATH_MSG_ERROR( "Failed to load entry " << static_cast< int >( entry ) );
453 throw GaudiException("xAODEventSelector::next() - xAOD::TEvent::getEntry returned less than 0 bytes","xAODEventSelector",StatusCode::FAILURE);
454 }
455
456 ++m_nbrEvts;
457 m_curEvt = global_entry + 1;
458
459 // std::cout << "--event-info--" << std::endl;
460 // event info
461
462 // EventInfo is required, otherwise Athena will crash
463 const xAOD::EventInfo* xaodEventInfo = 0;
464 if(m_fillEventInfo) {
465 if(m_tevent->retrieve( xaodEventInfo , "EventInfo").isFailure()) {
466 ATH_MSG_ERROR("Could not find xAOD::EventInfo");
467 throw GaudiException("xAODEventSelector::next() - Could not find xAOD::EventInfo","xAODEventSelector",StatusCode::FAILURE);
468 }
469 }
470 EventType* evtType = new EventType;
471 //const std::size_t runNbr = (xaodEventInfo) ? xaodEventInfo->runNumber() : 0;
472 EventInfo* evtInfo = new EventInfo(
473 (xaodEventInfo) ? new EventID(xaodEventInfo->runNumber(), xaodEventInfo->eventNumber(), xaodEventInfo->timeStamp(), xaodEventInfo->timeStampNSOffset(), xaodEventInfo->lumiBlock(), xaodEventInfo->bcid()) : new EventID(0, m_curEvt-1,0 ), evtType);
474 if ( !m_dataStore->record( evtInfo, "EventInfo" ).isSuccess() ) {
475 ATH_MSG_ERROR ("Could not record EventInfo !");
476 delete evtInfo; evtInfo = 0;
477 throw GaudiException("xAODEventSelector::next() - Could not record EventInfo","xAODEventSelector",StatusCode::FAILURE);
478 }
479
480 return StatusCode::SUCCESS;
481
482 } else {
483 // file is depleted — fire EndInputFile
484 m_inputFileGuard.reset();
485
486 // prepare for next file, if any...
487 // std::cout << "=========================================================="
488 // << std::endl;
489 // std::cerr << "::switch to next file...\n";
490
491 // iterate over our "cached" transient addresses,
492 // marking them as garbage and dropping the RootBranchAddress (as a side effect of
493 // ::setAddress(NULL).
494 // this way, the next time we hit ::createRootBranchAddress or ::updateAddress
495 // all internal states are kosher.
496
497 /*
498 * Problem for rel22 --
499 * The proxyProviderSvc 'moves' the transient addresses created in this class
500 * and thus invalidates them.
501 * The sequence is proxyProviderSvc will call "loadAddresses" method below but
502 * when it puts them into a DataProxy it will move the addresses so they are now invalid
503 *
504 * Shortest route to fixing this is just to clear the addresses and not touch them again
505 */
506 self()->m_rootAddresses.clear();
507
508 for (auto& iaddr : self()->m_rootAddresses) {
509 iaddr.second = false; // mark as invalid
510 SG::TransientAddress* taddr = iaddr.first;
511 taddr->setAddress(NULL);
512 }
513 const bool forceRemove = false;
514 CHECK( m_dataStore->clearStore(forceRemove) ); //must clear the storegate so that any tampering user did in EndInputFile incident is cleared
515 m_needReload = true;
516
517 m_collIdx += 1;
518 CHECK( rctx->setFile("") );
519 return next(*rctx);
520 }
521
522 // NOT REACHED
523 // std::cout << "***end of collections***" << std::endl;
524 // end of collections
525 //return StatusCode::FAILURE;
526}
527
528StatusCode xAODEventSelector::next( Context& ctx, int jump ) const
529{
530 ATH_MSG_DEBUG ("next(" << jump << ") : iEvt " << m_curEvt);
531
532 if (self()->seek(ctx, m_curEvt + jump).isSuccess()) {
533 return StatusCode::FAILURE;
534 }
535 return next(ctx);
536}
537
538StatusCode
539xAODEventSelector::previous( IEvtSelector::Context& ctx ) const
540{
541 return next( ctx, -1 );
542}
543
544StatusCode
545xAODEventSelector::previous( Context& ctx, int jump ) const
546{
547 return next( ctx, -jump );
548}
549
550StatusCode
551xAODEventSelector::last( Context& /*ctxt*/ ) const
552{
553 ATH_MSG_ERROR ("............. Last Event Not Implemented .............");
554 return StatusCode::FAILURE;
555}
556
557
558StatusCode
559xAODEventSelector::rewind( Context& ctxt ) const
560{
561 return self()->seek(ctxt, 0);
562}
563
564StatusCode
565xAODEventSelector::createContext( Context*& refCtx ) const
566{
567 xAODEventContext *ctx = new xAODEventContext(this);
568 refCtx = ctx;
569 return StatusCode::SUCCESS;
570}
571
572StatusCode
573xAODEventSelector::createAddress( const Context& /*refCtx*/,
574 IOpaqueAddress*& /*addr*/ ) const
575{
576 //std::cerr << "::TTES::createAddress()...\n";
577 return StatusCode::SUCCESS;
578}
579
580StatusCode
581xAODEventSelector::releaseContext( Context*& refCtxt ) const
582{
583 if(refCtxt==0) return StatusCode::SUCCESS; //added to avoid warning from MetaDataSvc, which passes an empty context
584 xAODEventContext *ctx = dynamic_cast<xAODEventContext*>(refCtxt);
585 if ( ctx ) {
586 delete ctx; ctx = 0;
587 return StatusCode::SUCCESS;
588 }
589
590 return StatusCode::FAILURE;
591}
592
593StatusCode
594xAODEventSelector::resetCriteria( const std::string&, Context& ) const
595{
596 ATH_MSG_ERROR ("............. resetCriteria Not Implemented .............");
597 return StatusCode::FAILURE;
598}
599
601// Non-const methods:
603
608StatusCode
609xAODEventSelector::seek (Context& refCtxt, int evtnum) const
610{
611 // std::cout << "::seek - evtnum=" << evtnum
612 // << " curevt=" << m_curEvt
613 // << " curcol=" << m_collIdx
614 // << std::endl;
615 long coll_idx = find_coll_idx(evtnum);
616 // std::cout << "::seek - evtnum=" << evtnum
617 // << " curevt=" << m_curEvt
618 // << " curcol=" << m_collIdx
619 // << " colidx=" << coll_idx
620 // << std::endl;
621 if (coll_idx == -1 && evtnum < m_curEvt) {
622 coll_idx = m_collIdx;
623 }
624
625 if (coll_idx == -1) {
626 ATH_MSG_INFO("seek: reached end of input.");
627 return StatusCode::RECOVERABLE;
628 }
629
630 if (coll_idx != m_collIdx) {
631 // tell everyone we switched files...
632 xAODEventContext* rctx = dynamic_cast<xAODEventContext*>(&refCtxt);
633 if (!rctx) {
634 return StatusCode::FAILURE;
635 }
636 ATH_CHECK(rctx->setFile(""));
637 }
638
639 m_collIdx = coll_idx;
640 m_curEvt = evtnum;
641
642 return StatusCode::SUCCESS;
643}
644
649int
650xAODEventSelector::curEvent (const Context& /*refCtxt*/) const
651{
652 return m_curEvt;
653}
654
657StatusCode
659{
660 ATH_MSG_VERBOSE("I/O reinitialization...");
661
662 ServiceHandle<IIoComponentMgr> iomgr("IoComponentMgr", name());
663 if (!iomgr.retrieve().isSuccess()) {
664 ATH_MSG_FATAL("Could not retrieve IoComponentMgr !");
665 return StatusCode::FAILURE;
666 }
667 if (!iomgr->io_hasitem(this)) {
668 ATH_MSG_FATAL("IoComponentMgr does not know about myself !");
669 return StatusCode::FAILURE;
670 }
671 std::vector<std::string> inputCollections = m_inputCollectionsName.value();
672
673 for (std::size_t
674 i = 0,
675 imax = m_inputCollectionsName.value().size();
676 i < imax;
677 ++i) {
678 std::string &fname = inputCollections[i];
679 // std::cout << "--retrieve new name for [" << fname << "]...\n";
680 if (!iomgr->io_contains(this, fname)) {
681 ATH_MSG_ERROR("IoComponentMgr does not know about [" << fname << "] !");
682 return StatusCode::FAILURE;
683 }
684 if (!iomgr->io_retrieve(this, fname).isSuccess()) {
685 ATH_MSG_FATAL("Could not retrieve new value for [" << fname << "] !");
686 return StatusCode::FAILURE;
687 }
688 // std::cout << "--> [" << fname << "]\n" << std::flush;
689 }
690 // all good... copy over.
691 m_inputCollectionsName = inputCollections;
692
693 // remove our EventInfo if any...
694 // {
695 // const bool force_remove = true;
696 // if (!m_dataStore->clearStore(force_remove).isSuccess()) {
697 // ATH_MSG_ERROR("could not clear event store!");
698 // return StatusCode::FAILURE;
699 // } else {
700 // ATH_MSG_INFO("sgdump: \n" << m_dataStore->dump());
701 // }
702 // }
703
704 // std::cout << "--> do_init_io...\n" << std::flush;
705 if (!do_init_io().isSuccess()) {
706 return StatusCode::FAILURE;
707 }
708
709 ATH_MSG_INFO("I/O reinitialization... [done]");
710 return StatusCode::SUCCESS;
711}
712
713
717StatusCode
719 tadList& /*tads*/)
720{
721 // std::cerr << "TTES::preLoadAddresses(" << int(storeID)
722 // << "," << tads.size()
723 // << ")...\n";
724 return StatusCode::SUCCESS;
725}
726
728StatusCode
730{
731 if (m_needReload || m_rootAddresses.empty()) {
732 //CHECK(createMetaDataRootBranchAddresses());
733 return createRootBranchAddresses(storeID, tads);
734 }
735
736 return StatusCode::SUCCESS;
737}
738
740StatusCode
742 const EventContext& /*ctx*/)
743{
744 // check if this tad is known to us.
745 if (tad) {
746 auto itr = m_rootAddresses.find(tad);
747 if ( itr != m_rootAddresses.end() && itr->second ) {
748 return StatusCode::SUCCESS;
749 }
750 ATH_MSG_DEBUG("updateAddress: address [" << tad->clID() << "#"
751 << tad->name() << ") NOT known to us.");
752 return StatusCode::FAILURE;
753 }
754
755 // do nothing.
756 return StatusCode::SUCCESS;
757}
758
759
761// Protected methods:
763
764
765
766
767StatusCode
769 tadList &tads)
770{
771 if (storeID != StoreID::EVENT_STORE) {
772 ATH_MSG_INFO("-- not the event-store --");
773 return(StatusCode::SUCCESS);
774 }
775
776 if (0 == m_tfile) {
777 ATH_MSG_ERROR("null pointer to n-tuple !");
778 return StatusCode::FAILURE;
779 }
780
781 TTree* inputTree = dynamic_cast<TTree*>(m_tfile->Get(m_tupleName.value().c_str()));
782
783 if(inputTree!=0) {
784
785
786 ATH_MSG_DEBUG("Reading xAOD::EventFormat");
787
788 // m_tevent->dump();
789
790 const void* value_ptr = m_tevent; //passed as 'parameter' to the address object
791
792 std::set<std::string> missingAux;
793
794 for( auto itr = m_tevent->inputEventFormat()->begin(); itr!=m_tevent->inputEventFormat()->end();++itr) {
795 if(inputTree->GetBranch(itr->second.branchName().c_str())==0) continue; //skip branches that are not available in the input collection
796 ATH_MSG_VERBOSE("EFE:" << itr->first << " branchName = " << itr->second.branchName() << " className=" << itr->second.className());
797 CLID id = 0;
798 if( m_clidsvc->getIDOfTypeInfoName(itr->second.className(), id).isFailure() &&
799 m_clidsvc->getIDOfTypeName(itr->second.className(), id).isFailure()) {
800 //if this is an AuxStore (infer if key ends in Aux.), its possible we schema-evolved away from the version in the input file, but that this evolution is actually 'ok' in some cases. So don't print an error if the CLID is missing for an Aux, but we will print a warning at the end for these aux stores
801 if(itr->second.branchName().compare(itr->second.branchName().length()-4,4,"Aux.")==0) {
802 missingAux.insert( itr->second.className() );continue;
803 } else {
804 //vectors can be missing their std:: prefix, so add that and retry before failing
805 TString className = itr->second.className();
807 //ALT solution to this is do what RootNtupleEventSelector does: uses TClass:GetClass
808 //and GetTypeInfo() method to get the proper type info
809 TClass *cls = TClass::GetClass(className);
810 if(cls) {
811 const std::type_info *ti = cls->GetTypeInfo();
812 if(ti) className = System::typeinfoName(*ti);
813 }
814
815 if( m_clidsvc->getIDOfTypeInfoName(className.Data(), id).isFailure() &&
816 m_clidsvc->getIDOfTypeName(className.Data(), id).isFailure()) {
817 ATH_MSG_WARNING("No CLID for class " << itr->second.className() << " , cannot read " << itr->second.branchName());
818 continue;
819 }
820 }
821 }
822
823 const std::string br_name = itr->second.branchName();
824
826 (POOL_ROOTTREE_StorageType, id,
827 m_tupleName.value(),
828 br_name,
829 (unsigned long)(value_ptr),
830 (unsigned long)(0)); //IMPORTANT THIS IS 0: signals to xAODBranchAddress to read event-level info (see setTEventAddress)
831 // recycle old rootaddress, if any.
832 SG::TransientAddress* taddr = NULL;
833 // FIXME: should we only iterate over m_rootAddresses which have been marked
834 // as invalid ? (ie: iaddr->second == false)
835 // probably not worth it... (but depends on the "occupancy")
836 for (auto
837 iaddr = m_rootAddresses.begin(),
838 iaddre= m_rootAddresses.end();
839 iaddr != iaddre;
840 ++iaddr) {
841 SG::TransientAddress *old = iaddr->first;
842 if (old->clID() == id &&
843 old->name() == br_name) {
844 // found a "cached" transient address which corresponds to this clid+key
845 // bind it to our new RootBranchAddress...
846 old->setAddress(addr);
847 taddr = old;
848 iaddr->second = true; // mark as valid
849 break;
850 }
851 }
852 if (taddr == NULL) {
853 taddr = new SG::TransientAddress(id, br_name, addr);
854 taddr->setProvider(this, storeID);
855 taddr->clearAddress(false);
856 // only add the *new* TransientAddress to the input list as the *old* ones
857 // are already tracked by the datastore (via the sticky proxies)
858 tads.push_back(taddr);
859 // note: we can store this taddr *b/c* we don't clearAddress it
860 // ie: b/c we just called clearAddress(false) so it will be recycled
861 // over the events.
862 m_rootAddresses.insert(std::make_pair(taddr, true));
863 }
864 // }
865 }
866
867
868 if(missingAux.size()) {
869 std::string allAux; for(auto& s : missingAux) allAux += s + ", ";
870 ATH_MSG_WARNING("The following AuxStore types are not directly accessible (missing CLID, possibly from schema evolution): " << allAux);
871 }
872 } //end if block of requiring input tree to exist
873 else {
874 ATH_MSG_DEBUG("No input collection " << m_tupleName.value() << " found in input file " << m_tfile->GetTitle() );
875 }
876
877 m_needReload = false;
878
879 ATH_MSG_DEBUG("In xAODEventSelector::createRootBranchAddresses end ...");
880
881 return StatusCode::SUCCESS;
882}
883
884StatusCode
886{
887
888 ATH_MSG_DEBUG("In xAODEventSelector::createMetaDataRootBranchAddresses start ...");
889
890 if ( 0 == m_tfile ) {
891 ATH_MSG_ERROR ("Could not get m_tfile !!");
892 throw "xAODEventSelector: Unable to get m_tfile";
893 }
894
895 //FIXME JE
896 ATH_MSG_DEBUG("m_metadataName.value().c_str() = " << m_metadataName.value().c_str() );
897 TTree* tree = dynamic_cast<TTree*>(m_tfile->Get(m_metadataName.value().c_str()));
898 ATH_MSG_DEBUG("m_tfile = " << m_tfile );
899 ATH_MSG_DEBUG("tree = " << tree );
900 if (!tree) std::abort();
901 TObjArray *leaves = tree->GetListOfLeaves();
902 if (!leaves) {
903 ATH_MSG_INFO("no leaves!!");
904 return StatusCode::SUCCESS;
905 }
906
907 // loop over leaves
908 for (Int_t i = 0; i < leaves->GetEntries(); ++i) {
909 TLeaf *leaf = (TLeaf *)leaves->At(i);
910 TBranch *branch = leaf->GetBranch();
911 if (branch) {
912
913 CLID id = 0;
914 const void* value_ptr = m_tevent;
915 const std::string type_name = leaf->GetTypeName();
916 const std::string br_name = branch->GetName();
917 // Skip if type_name does contain xAOD, ie. is not an xAOD container
918 const std::string toCheck = "xAOD::";
919 if (type_name.find(toCheck) == std::string::npos) {
920 ATH_MSG_DEBUG("** Skip type-name = " << type_name << ", br_name = " << br_name );
921 continue;
922 }
923 const std::string sg_key = br_name;//m_tupleName.value()+"/"+br_name;
924 TClass *cls = TClass::GetClass(type_name.c_str());
925 const std::type_info *ti = 0;
926
927 // Skip the EventFormat branch. That must not be disturbed by the
928 // generic metadata handling.
929 if( br_name == "EventFormat" ) continue;
930
931 if (cls) {
932 ti = cls->GetTypeInfo();
933 // first, try to load a dict for that class...
934 if (ti) {
935 m_dictsvc->load_type(*ti);
936 }
937 if (!ti) {
938 ATH_MSG_DEBUG("could not find a type-info for [" <<
939 type_name << "]");
940 continue;
941 }
942
943 // Find the clid for the typeInfo
945
946 if (id == 0) {
947 ATH_MSG_DEBUG("** could not find a CLID for type-name ["
948 << type_name << "]");
949 continue;
950 }
951
952
953
954 ATH_MSG_DEBUG("id = " << id << ", m_metadataName.value() = " << m_metadataName.value() << ", br_name = " << br_name << ", value_ptr = " << value_ptr);
957 (POOL_ROOTTREE_StorageType, id,
958 m_metadataName.value(),
959 br_name,
960 (unsigned long)(value_ptr),
961 (unsigned long)(1))); //IMPORTANT THIS IS 1: signals to BranchAddress to read metadata
962 if (!m_imetaStore->recordAddress(br_name, std::move(addr), true).isSuccess()) {
963 ATH_MSG_ERROR("could not record address at [" << br_name << "] in store ["
964 << m_imetaStore->name() << "]");
965 }
966 // SG::TransientAddress* taddr = new SG::TransientAddress
967 // (id, sg_key, addr);
968 // taddr->setProvider(this);
969 // taddr->clearAddress(true);
970 // tads.push_back(taddr);
971 }
972 }
973 }
974
975 ATH_MSG_DEBUG("In xAODEventSelector::createMetaDataRootBranchAddresses end ...");
976
977 return StatusCode::SUCCESS;
978}
979
980
981TFile*
982xAODEventSelector::fetchNtupleFile(const std::string& fname) const
983{
984 TFile* file = NULL;
985 if(fname.empty()) return file; //if blank, return 0
987 //see if file already open
988 file = (TFile*)gROOT->GetListOfFiles()->FindObject(fname.c_str());
989 if (!file) {
990 //open the file
991 file = TFile::Open(fname.c_str(), "READ");
992 if (file) file->SetName(fname.c_str());
993 }
994 //check file is ok before returning
995 if (!file || file->IsZombie()) {
996 ATH_MSG_ERROR("could not open next file in input collection ["
997 << fname << "]");
998 if (file) {
999 file->Close();
1000 }
1001 return 0;
1002 }
1003 return file;
1004}
1005
1006//move onto given file
1007StatusCode xAODEventSelector::setFile(const std::string& fname) {
1008
1009 TFile* newFile = fetchNtupleFile(fname);
1010 if(!newFile && !fname.empty()) {
1011 ATH_MSG_FATAL( "xAODEventSelector: Unable to fetch Ntuple: " << fname);
1012 return StatusCode::FAILURE; //failed to load file
1013 }
1014
1015 if(m_tfile && m_tfile != newFile) {
1016 const std::string currFile = m_tfile->GetName();
1017 //disconnect pool if necessary ... always fire this, hopefully it is safe even if not needed
1018 m_poolSvc->disconnectDb("PFN:"+currFile).ignore();
1019 //close existing file
1020 m_tfile->Close();
1021 //we should also cleanup after pool, in case it has left open files dangling
1022 }
1023 m_tfile = newFile;
1024 m_tevent_entries = 0; //will set in a moment
1025
1026 if(!m_tfile) return StatusCode::SUCCESS; //must have been setting to blank file
1027
1028 if(m_tevent->readFrom( m_tfile ).isFailure()) {
1029 ATH_MSG_FATAL( "xAODEventSelector: TEvent cannot read " << fname);
1030 return StatusCode::FAILURE;
1031 }
1032
1033 m_tevent_entries = m_tevent->getEntries();
1034
1035 //need to load metadata for file
1036 if (!m_imetaStore->clearStore().isSuccess()) {
1037 ATH_MSG_INFO("could not clear store [" << m_imetaStore.typeAndName() << "]");
1038 return StatusCode::FAILURE;
1039 }
1040
1041
1043 //ensure input file collection created
1044 ATH_MSG_DEBUG("Creating poolsvc collection for " << fname);
1045 m_poolSvc->createCollection( "PFN:"+fname , fname ); //FIXME: this throws exceptions which get in the way of debugging with gdb :-(
1046
1047 //metadata will be read by MetaDataSvc, triggered by the BeginInputFile call
1048 } else {
1049 if (!createMetaDataRootBranchAddresses().isSuccess()) {
1050 ATH_MSG_ERROR("Could not load metadata");
1051 }
1052 }
1053
1054
1055
1056 return StatusCode::SUCCESS;
1057
1058}
1059
1060
1061StatusCode
1063{
1064 // std::cout << "::fetchNtuple..." << std::endl;
1065
1066 // initialize some helper structures and data
1067 {
1069 zero.min_entries = -1;
1070 zero.max_entries = -1;
1071 m_collEvts.resize(m_inputCollectionsName.value().size(), zero);
1072 m_collIdx = 0;
1073 }
1074
1075
1076
1077 //CHECK( setFile( m_inputCollectionsName.value()[m_collIdx] ) );
1078
1079
1080 // std::cout << "::clear-root-addresses..." << std::endl;
1081 // reset the list of branches
1082 //m_rootAddresses.clear();
1083 m_needReload = true;
1084
1085 // skip events we are asked to skip
1087 m_nbrEvts = 0;
1088
1089 // std::cout << "::fetchNtuple...[done]" << std::endl;
1090 return StatusCode::SUCCESS;
1091}
1092
1096int
1098{
1099 // std::cout << "--find_coll_idx(" << evtidx << ")..." << std::endl
1100 // << "--collsize: " << m_collEvts.size() << std::endl;
1101 for (std::size_t i = 0, imax = m_collEvts.size();
1102 i < imax;
1103 ++i) {
1104 // std::cout << "--[" << i << "]...\n";
1105 CollMetaData &itr = m_collEvts[i];
1106 if (itr.min_entries == -1) {
1107 TFile *file = fetchNtupleFile(m_inputCollectionsName.value()[i]);
1108 if (file) {
1109 long offset = 0;
1110 if (i > 0) {
1111 CollMetaData &jtr = m_collEvts[i-1];
1112 offset += jtr.max_entries;
1113 }
1114 itr.min_entries = offset;
1115 TTree* tree = dynamic_cast<TTree*>(file->Get(m_tupleName.value().c_str()));
1116 itr.max_entries = offset + ( (tree) ? tree->GetEntriesFast() : 0);
1117 } else {
1118 throw "xAODEventSelector: Unable to fetch ntuple";
1119 }
1120 }
1121 // std::cout << "--[" << i << "] => [" << itr.min_entries << ", "
1122 // << itr.max_entries << ") evtidx=[" << evtidx << "]"
1123 // << std::endl;
1124 if (itr.min_entries <= evtidx && evtidx < itr.max_entries) {
1125 return i;
1126 }
1127 }
1128 return -1;
1129}
1130
1131
1132int xAODEventSelector::size (Context& /*refCtxt*/) const {
1133 //use find_coll_idx to trigger a population of the m_collEvts ... dummy call with -1 to trigger all colls loaded
1134 find_coll_idx(-1);
1135 return m_collEvts.back().max_entries;
1136}
1137
1138//not used for anything
1139void xAODEventSelector::handle(const Incident& /*incident*/) {
1140
1141}
1142
1143} //> namespace Athena
#define endmsg
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
a static registry of CLID->typeName entries.
macros to associate a CLID to a type
#define CHECK(...)
Evaluate an expression and check for errors.
This class provides a unique identification for each event, in terms of run/event number and/or a tim...
This class provides general information about an event.
uint32_t CLID
The Class ID type.
Include TBranchElement.h, suppressing clang warnings.
int imax(int i, int j)
Define macros for attributes used to control the static checker.
#define ATLAS_THREAD_SAFE
state of a few global resources from ROOT and restores their initial value upon d-tor call.
A simple class to do the retrieve from TEvent.
event selector context ... just holds reference back to the selector
int64_t entry() const
access to the current event entry number
StatusCode setFile ATLAS_NOT_THREAD_SAFE(const std::string &fname)
call to setFile on evtSel
std::size_t fileIndex() const
access to the file iterator
virtual void * identifier() const override
identifier method required by IEvtSelector::Context
const std::vector< std::string > & files() const
access to the container of files
xAODEventContext(const xAODEventSelector *sel)
standard c-tor with initialization
const xAODEventSelector * m_evtsel
reference to the hosting event selector instance
const TFile * file() const
access to the current file
virtual ~xAODEventContext()
standard d-tor
Class implementing the GAUDI IEvtSelector interface using ROOT TTree as a backend.
ServiceHandle< StoreGateSvc > m_ometaStore
Pointer to the StoreGateSvc output metadata store.
std::optional< InputFileIncidentGuard > m_inputFileGuard
RAII guard: guarantees a matching EndInputFile for every BeginInputFile.
virtual StatusCode updateAddress(StoreID::type storeID, SG::TransientAddress *tad, const EventContext &ctx) override
update a transient Address
virtual int size(Context &refCtxt) const override
ICollectionSize interface
StringProperty m_tupleName
Name of TTree to load from collection of input files.
virtual StatusCode next(Context &refCtxt) const override
xAODEventSelector(const std::string &name, ISvcLocator *svcLoc)
Constructor with parameters:
long m_nbrEvts
Number of Events read so far.
ServiceHandle< IDictLoaderSvc > m_dictsvc
Pointer to the IDictLoaderSvc.
TFile * m_tfile
current TFile being read
virtual StatusCode resetCriteria(const std::string &cr, Context &ctx) const override
StringArrayProperty m_inputCollectionsName
List of input files containing TTree.
StatusCode createRootBranchAddresses(StoreID::type storeID, tadList &tads)
helper method to create proxies
int find_coll_idx(int evtidx) const
helper method to get the collection index (into m_inputCollectionsName) for a given event index evtid...
StatusCode createMetaDataRootBranchAddresses() const
helper method to create proxies for the metadata store
virtual StatusCode releaseContext(Context *&refCtxt) const override
friend class Athena::xAODEventContext
StringProperty m_metadataName
Name of TTree to load from metadata of input files.
xAOD::xAODTEvent * m_tevent
current TEvent being read
xAODEventSelector * self() const
non-const access to self (b/c next() is const)
std::vector< CollMetaData > m_collEvts
cache of the number of entries for each collection
StatusCode do_init_io()
helper method to init the i/o components
virtual StatusCode initialize() override
virtual StatusCode io_reinit() override
Callback method to reinitialize the internal state of the component for I/O purposes (e....
ServiceHandle< IProxyProviderSvc > m_ppSvc
Handle to the proxy provider svc.
virtual StatusCode loadAddresses(StoreID::type storeID, tadList &list) override
get all new addresses from Provider for this Event.
ServiceHandle< StoreGateSvc > m_dataStore
Pointer to the StoreGateSvc event store.
StatusCode setFile(const std::string &fname)
switch to given file, loading metadata and triggering a beginInputFile incident
virtual StatusCode previous(Context &refCtxt) const override
std::unordered_map< SG::TransientAddress *, bool > m_rootAddresses
virtual int curEvent(const Context &refCtxt) const override
return the current event number.
ServiceHandle< IIncidentSvc > m_incsvc
Handle to the incident service.
virtual StatusCode createAddress(const Context &refCtxt, IOpaqueAddress *&) const override
virtual StatusCode finalize() override
ServiceHandle< IClassIDSvc > m_clidsvc
Pointer to the IClassIDSvc.
virtual StatusCode last(Context &refContext) const override
virtual StatusCode seek(Context &refCtxt, int evtnum) const override
Seek to a given event number.
TFile * fetchNtupleFile(const std::string &fname) const
helper method to retrieve the correct tuple
long m_curEvt
current event index
ServiceHandle< IPoolSvc > m_poolSvc
Handle to the PoolSvc (used in Hybrid mode when user is reading metadata with pool).
virtual StatusCode createContext(Context *&refpCtxt) const override
virtual ~xAODEventSelector()
Destructor:
long m_skipEvts
Number of events to skip at the beginning.
virtual StatusCode rewind(Context &refCtxt) const override
long m_collIdx
current collection index (into m_inputCollectionsName)
virtual void handle(const Incident &incident) override
virtual StatusCode stop() override
virtual StatusCode preLoadAddresses(StoreID::type storeID, tadList &list) override
ServiceHandle< StoreGateSvc > m_imetaStore
Pointer to the StoreGateSvc input metadata store.
static CLID typeinfoToCLID(const std::type_info &ti)
Return the CLID corresponding to a type_info.
Simple smart pointer for Gaudi-style refcounted objects.
static InputFileIncidentGuard begin(IIncidentSvc &incSvc, std::string_view source, std::string_view beginFileName, std::string_view guid, std::string_view endFileName={}, std::string_view beginType=IncidentType::BeginInputFile, std::string_view endType=IncidentType::EndInputFile)
Factory: fire the begin incident and return a guard whose destructor fires the matching end incident.
static void transition(std::optional< InputFileIncidentGuard > &guard, IIncidentSvc &incSvc, std::string_view source, std::string_view beginFileName, std::string_view guid, std::string_view endFileName={}, std::string_view beginType=IncidentType::BeginInputFile, std::string_view endType=IncidentType::EndInputFile)
Replace the guard in an optional, with strict End-before-Begin ordering.
CLID clID() const
Retrieve string key:
void clearAddress(const bool &flag)
Return the clearAddress flag.
const std::string & name() const
Get the primary (hashed) SG key.
void setAddress(CxxUtils::RefCountedPtr< IOpaqueAddress > pAddress)
Retrieve primary clid.
void setProvider(IAddressProvider *provider, StoreID::type storeID)
@ EVENT_STORE
Definition StoreID.h:26
uint32_t lumiBlock() const
The current event's luminosity block number.
uint32_t bcid() const
The bunch crossing ID of the event.
uint32_t timeStamp() const
POSIX time in seconds from 1970. January 1st.
uint32_t runNumber() const
The current event's run number.
uint32_t timeStampNSOffset() const
Nanosecond time offset wrt. the time stamp.
uint64_t eventNumber() const
The current event's event number.
ReadStats & stats()
Access the object belonging to the current thread.
Definition IOStats.cxx:17
static IOStats & instance()
Singleton object accessor.
Definition IOStats.cxx:11
void stop()
Stop the statistics collection.
void start(bool clear=true)
Start the statistics collection.
static PerfStats & instance()
Function accessing the singleton instance.
void Print(::Option_t *option="") const
Print information about the collected statistics.
void zero(TH2 *h)
zero the contents of a 2d histogram
Some weak symbol referencing magic... These are declared in AthenaKernel/getMessageSvc....
StatusCode parse(std::tuple< Tup... > &tup, const Gaudi::Parsers::InputData &input)
StatusCode Init(const char *appname)
Function initialising ROOT/PyROOT for using the ATLAS EDM.
Definition Init.cxx:31
EventInfo_v1 EventInfo
Definition of the latest event info version.
long max_entries
number of entries after this collection
long min_entries
number of entries up to this collection
TChain * tree
TFile * file