ATLAS Offline Software
Loading...
Searching...
No Matches
RootNtupleEventSelector.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// RootNtupleEventSelector.cxx
8// Implementation file for class RootNtupleEventSelector
9// Author: S.Binet<binet@cern.ch>
11
12// STL includes
13#include <sstream>
14#include <string>
15#include <vector>
16#include <stdint.h>
17#include <unordered_map>
18#include <unordered_set>
19
20// ROOT includes
21#include "TROOT.h"
23#include "TClass.h"
24#include "TClassEdit.h"
25#include "TFile.h"
26#include "TKey.h"
27#include "TLeaf.h"
28
29// Framework includes
30//#include "GaudiKernel/GenericAddress.h"
31#include "GaudiKernel/FileIncident.h"
32#include "GaudiKernel/IIoComponentMgr.h"
33#include "GaudiKernel/ISvcLocator.h"
34#include "GaudiKernel/ITHistSvc.h"
35#include "GaudiKernel/MsgStream.h"
36#include "GaudiKernel/StatusCode.h"
37#include "GaudiKernel/System.h"
40
41// StoreGate includes
42
43#include "SGTools/BuiltinsClids.h" // to make sure we have their clids
44#include "SGTools/StlMapClids.h" // to make sure we have their clids
45#include "SGTools/StlVectorClids.h" // to make sure we have their clids
48
49#include "TObject.h"
50#include "TTree.h"
51CLASS_DEF( TObject, 74939790 , 1 )
52#include "AthenaRootComps/TransferTree.h"
53
54// EventInfo includes
55#include "EventInfo/EventInfo.h"
56#include "EventInfo/EventType.h"
57#include "EventInfo/EventID.h"
60
61
62// Package includes
64#include "RootBranchAddress.h"
65#include "RootGlobalsRestore.h"
66
67#include "boost/tokenizer.hpp"
68
69namespace {
70 std::string
71 root_typename(const std::string& root_type_name)
72 {
73 static const std::unordered_map<std::string,std::string> s = {
74 {"Int_t", System::typeinfoName(typeid(Int_t))},
75 {"UInt_t", System::typeinfoName(typeid(UInt_t))},
76
77 {"Long_t", System::typeinfoName(typeid(Long_t))},
78 {"ULong_t", System::typeinfoName(typeid(ULong_t))},
79
80 {"Long64_t", System::typeinfoName(typeid(Long64_t))},
81 {"ULong64_t", System::typeinfoName(typeid(ULong64_t))},
82
83 {"Float_t", System::typeinfoName(typeid(Float_t))},
84 {"Float16_t", System::typeinfoName(typeid(Float16_t))},
85 {"Double_t", System::typeinfoName(typeid(Double_t))},
86 {"Double32_t", System::typeinfoName(typeid(Double32_t))},
87
88 {"Bool_t", System::typeinfoName(typeid(Bool_t))},
89 {"Char_t", System::typeinfoName(typeid(Char_t))},
90 {"UChar_t", System::typeinfoName(typeid(UChar_t))},
91
92 {"Short_t", System::typeinfoName(typeid(Short_t))},
93 {"UShort_t", System::typeinfoName(typeid(UShort_t))}
94 };
95
96 return s.at(root_type_name);
97 }
98
99#if 0
100 std::vector<std::string>
101 get_active_leaves(TTree *tuple)
102 {
103 std::vector<std::string> active;
104 TObjArray *leaves = tuple->GetListOfLeaves();
105 if (leaves) {
106 // loop over leaves
107 for (Int_t i = 0; i < leaves->GetEntries(); ++i) {
108 TLeaf *leaf = (TLeaf *)leaves->At(i);
109 TBranch *branch = leaf->GetBranch();
110 if (branch) {
111 const char *brname = branch->GetName();
112 if (tuple->GetBranchStatus(brname)) {
113 active.push_back(std::string(brname));
114 }
115 }
116 }
117 }
118 return active;
119 }
120#endif
121
122}
123
124namespace Athena {
125
130 public ::IEvtSelector::Context
131{
132public:
134 typedef std::vector<std::string> FileNames_t;
135
136private:
139
142
145
147 std::string m_fid;
148
149public:
150
158
161
162 // access to the container of files
163 const FileNames_t& files() const
164 { return m_evtsel->m_inputCollectionsName.value(); }
165
167 virtual void* identifier() const
168 { return (void*)(m_evtsel); }
169
171 std::size_t fileIndex() const
172 { return m_collIdx; }
173
175 void setFileIndex(std::size_t idx)
176 { m_collIdx = idx; }
177
178 std::size_t tupleIndex() const
179 { return m_tupleIdx; }
180
181 void setTupleIndex(std::size_t idx)
182 { m_tupleIdx = idx; }
183
185 int64_t entry() const { return m_evtsel->m_curEvt; }
186
188 void setFID(const std::string& fid) { m_fid = fid; }
189
191 const std::string& fid() const { return m_fid; }
192
194 TTree* tree() const { return m_evtsel->m_tuple; }
195
197 void setTree(TTree* tree) {
198 // make sure we clean-up and close the file holding
199 // the previous tree, if any.
200 // dont close if it is the same tree though!
201 TTree *cur = m_evtsel->m_tuple;
202 if (cur && tree != cur) {
203 TFile *old_file = cur->GetCurrentFile();
204 if (old_file) {
205 old_file->Close();
206 }
207 }
208
209 m_evtsel->m_tuple = tree;
210 }
211};
212
214
216// Public methods:
218
219// Constructors
221
223 ISvcLocator* svcLoc ) :
224 extends ( name, svcLoc ),
225 m_dataStore( "StoreGateSvc/StoreGateSvc", name ),
226 m_imetaStore( "StoreGateSvc/InputMetaDataStore", name ),
227 m_ometaStore( "StoreGateSvc/MetaDataStore", name ),
228 m_clidsvc ( "ClassIDSvc", name ),
229 m_dictsvc ( "AthDictLoaderSvc", name ),
230 m_incsvc ( "IncidentSvc", name ),
231 m_nbrEvts ( 0 ),
232 m_curEvt ( 0 ),
233 m_collEvts ( ),
234 m_tuple (NULL),
235 m_needReload (true)
236{
237 declareProperty( "DataStore",
238 m_dataStore,
239 "Store where to publish data");
240
241 declareProperty( "InputMetaStore",
242 m_imetaStore,
243 "Store where to publish (input) metadata");
244
245 declareProperty( "MetaStore",
246 m_ometaStore,
247 "Store where to publish (output) metadata");
248
249 declareProperty( "InputCollections",
250 m_inputCollectionsName,
251 "List of input (ROOT) file names" );
252 m_inputCollectionsName.declareUpdateHandler
254
255 declareProperty( "TupleName",
256 m_tupleName = "CollectionTree",
257 "Name of the TTree to load/read from input file(s). "
258 "May be a semicolon-separated string to read multiple TTrees.");
259
260 declareProperty( "SkipEvents",
261 m_skipEvts = 0,
262 "Number of events to skip at the beginning" );
263
264 declareProperty( "ActiveBranches",
265 m_activeBranchNames,
266 "List of branch names to activate" );
267}
268
269// Destructor
273
275{
276 ATH_MSG_INFO ("Enter RootNtupleEventSelector initialization...");
277
278 // retrieve clidsvc
279 if ( !m_clidsvc.retrieve().isSuccess() ) {
281 ("Could not retrieve [" << m_clidsvc.typeAndName() << "]");
282 return StatusCode::FAILURE;
283 }
284
285 // retrieve dictsvc
286 if ( !m_dictsvc.retrieve().isSuccess() ) {
288 ("Could not retrieve [" << m_dictsvc.typeAndName() << "]");
289 return StatusCode::FAILURE;
290 }
291
292 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
293 boost::char_separator<char> sep (" ;");
294 tokenizer tokens (m_tupleName.value(), sep);
295 m_tupleNames.assign (tokens.begin(), tokens.end());
296
297 if ( m_tupleNames.empty() ) {
299 ("You have to give a TTree name to read from the ROOT files !");
300 return StatusCode::FAILURE;
301 }
302
303 CHECK( m_incsvc.retrieve() );
304 m_incsvc->addListener(this,IncidentType::BeginEvent,99); //used to trigger BeginInputFile on start of first event of file - 99 priority so AFTER storegatesvc done
305
306
307 setupInputCollection( m_inputCollectionsName );
308 const std::size_t nbrInputFiles = m_inputCollectionsName.value().size();
309 if ( nbrInputFiles < 1 ) {
311 ("You need to give at least 1 input file !!" << endmsg
312 << "(Got [" << nbrInputFiles << "] file instead !)");
313 return StatusCode::FAILURE;
314 } else {
316 ("Selector configured to read [" << nbrInputFiles << "] file(s)..."
317 << endmsg
318 << " TTree [" << m_tupleName.value() << "]");
319 }
320
321 {
322 // register this service for 'I/O' events
323 ServiceHandle<IIoComponentMgr> iomgr("IoComponentMgr", name());
324 if (!iomgr.retrieve().isSuccess()) {
325 ATH_MSG_FATAL("Could not retrieve IoComponentMgr !");
326 return StatusCode::FAILURE;
327 }
328 if (!iomgr->io_register(this).isSuccess()) {
329 ATH_MSG_FATAL("Could not register myself with the IoComponentMgr !");
330 return StatusCode::FAILURE;
331 }
332 // register input file's names with the I/O manager
333 const std::vector<std::string>& incol = m_inputCollectionsName.value();
334 bool allGood = true;
335 for (std::size_t icol = 0, imax = incol.size(); icol < imax; icol++) {
336 if (!iomgr->io_register(this,
337 IIoComponentMgr::IoMode::READ,
338 incol[icol]).isSuccess()) {
339 ATH_MSG_FATAL("could not register [" << incol[icol] << "] for output !");
340 allGood = false;
341 } else {
342 ATH_MSG_VERBOSE("io_register[" << this->name() << "](" << incol[icol] << ") [ok]");
343 }
344 }
345 if (!allGood) {
346 return StatusCode::FAILURE;
347 }
348 }
349
350 if (!do_init_io().isSuccess()) {
351 return StatusCode::FAILURE;
352 }
353 // retrieve event store
354 // this needs to happen *after* having initialized the i/o
355 // as our branches (which need a valid m_ntuple pointer)
356 // may be asked to be registered as we are a ProxyProvider.
357 // retrieving the event store will poke the ProxyProviderSvc...
358 /*
359 if ( !m_dataStore.retrieve().isSuccess() ) {
360 ATH_MSG_ERROR
361 ("Could not retrieve [" << m_dataStore.typeAndName() << "] !!");
362 return StatusCode::FAILURE;
363 }
364
365 // ditto for (input) meta data store
366 if (!m_imetaStore.retrieve().isSuccess()) {
367 ATH_MSG_ERROR
368 ("Could not retrieve [" << m_imetaStore.typeAndName() << "] !!");
369 return StatusCode::FAILURE;
370 }
371
372 // ditto for (output) meta data store
373 if (!m_ometaStore.retrieve().isSuccess()) {
374 ATH_MSG_ERROR
375 ("Could not retrieve [" << m_ometaStore.typeAndName() << "] !!");
376 return StatusCode::FAILURE;
377 }
378 */
379
380 //ensure the Athena::NtupleCnvSvc is in the EventPersistencySvc
381 ServiceHandle<IProperty> epSvc("EventPersistencySvc",name());
382 std::vector<std::string> propVal;
383 CHECK( Gaudi::Parsers::parse( propVal , epSvc->getProperty("CnvServices").toString() ) );
384 bool foundSvc(false);
385 for(const std::string& s : propVal) {
386 if(s=="Athena::xAODCnvSvc") { foundSvc=true; break; }
387 }
388 if(!foundSvc) {
389 propVal.push_back("Athena::NtupleCnvSvc");
390 CHECK( epSvc->setProperty("CnvServices", Gaudi::Utils::toString( propVal ) ));
391 }
392
393 //we should also add ourself as a proxy provider
394 ServiceHandle<IProxyProviderSvc> ppSvc("ProxyProviderSvc",name());
395 CHECK( ppSvc.retrieve() );
396 ppSvc->addProvider( this );
397
398
399
400 return StatusCode::SUCCESS;
401}
402
404{
405 // Fire EndInputFile for any file still open (the event loop may end
406 // before the file is fully read).
407 m_inputFileGuard.reset();
408 m_fireBIF = false;
409 return StatusCode::SUCCESS;
410}
411
413{
414 ATH_MSG_INFO ("Finalize...");
415 // FIXME: this should be tweaked/updated if/when a selection function
416 // or filtering predicate is applied (one day?)
417 ATH_MSG_INFO ("Total events read: " << (m_nbrEvts - m_skipEvts));
418
419 // Explicitly delete all the files we created.
420 // If we leave it up to root, then xrootd can get cleaned up before
421 // the root destructors run, leading to a crash.
422 for (TFile* f : m_files)
423 delete f;
424 m_files.clear();
425
426 return StatusCode::SUCCESS;
427}
428
430// Const methods:
432
434{
435 // Fire EndInputFile via guard reset
436 m_inputFileGuard.reset();
437
438 // prepare for next file, if any...
439 // std::cout << "=========================================================="
440 // << std::endl;
441 // std::cerr << "::switch to next file...\n";
442
443 // iterate over proxies and
444 // mark as garbage and drop the RootBranchAddress (as a side effect of
445 // ::setAddress(NULL).
446 // this way, the next time we hit ::createRootBranchAddress or ::updateAddress
447 // all internal states are kosher.
448 for (const SG::DataProxy* cdp : m_dataStore->proxies()) {
449 if (dynamic_cast<Athena::RootBranchAddress*> (cdp->address()) != nullptr) {
450 if (SG::DataProxy* dp = m_dataStore->proxy_exact (cdp->sgkey())) {
451 dp->setAddress (nullptr);
452 }
453 }
454 }
455
456 const bool forceRemove = false;
457 CHECK( m_dataStore->clearStore(forceRemove) ); //must clear the storegate so that any tampering user did in EndInputFile incident is cleared
458 m_needReload = true;
459 // Defer BeginInputFile for the next file to the next BeginEvent.
460 // The actual file name is resolved in handle() from m_tuple.
461 m_fireBIF = true;
462
463 return StatusCode::SUCCESS;
464}
465
466StatusCode
467RootNtupleEventSelector::next( IEvtSelector::Context& ctx ) const
468{
469 // std::cout << "::next(fidx=" << ctx->fileIndex() << ", eidx=" << m_curEvt << ")"
470 // << std::endl;
471 ATH_MSG_DEBUG ("next() : iEvt " << m_curEvt);
472
473 // get evt context
474 RootNtupleEventContext* rctx = dynamic_cast<RootNtupleEventContext*>(&ctx);
475 if ( 0 == rctx ) {
476 ATH_MSG_ERROR ("Could not dyn-cast to RootNtupleEventContext !!");
477 throw "RootNtupleEventSelector: Unable to get RootNtupleEventContext";
478 }
479
480 TTree *tree = rctx->tree();
481 if (!tree) {
482 const FileNames_t& fnames = rctx->files();
483 std::size_t fidx = rctx->fileIndex();
484 rctx->setTree(NULL);
485 //rctx->setEntry(-1);
486
487 while (!tree && rctx->tupleIndex() < m_tupleNames.size()) {
488 if (fidx < rctx->files().size()) {
489 const std::string& fname = fnames[fidx];
490 tree = fetchNtuple(fname, m_tupleNames[rctx->tupleIndex()]);
491 if (!tree) {
492 throw "RootNtupleEventSelector: Unable to get tree";
493 }
494 rctx->setTree(tree);
495
496 }
497 else {
498 // end of collections; go to next tuple.
499 rctx->setTupleIndex (rctx->tupleIndex()+1);
500 rctx->setFileIndex (0);
501 fidx = 0;
502 }
503 }
504
505 if (!tree) {
506 return StatusCode::FAILURE;
507 }
508 }
509 int64_t global_entry = rctx->entry();
510 size_t collIdx = rctx->fileIndex();
511 size_t tupleIdx = rctx->tupleIndex();
512 int64_t entry = global_entry;
513 if (m_collEvts[tupleIdx][collIdx].min_entries < 0) {
514 // need to trigger collmetadata...
515 long coll_idx, tuple_idx;
516 const_cast<RootNtupleEventSelector*>(this)->find_coll_idx(entry,
517 coll_idx,
518 tuple_idx);
519 }
520 // rctx::entry is the *global* entry number.
521 // we need the local one...
522 entry = global_entry - m_collEvts[tupleIdx][collIdx].min_entries;
523
524 Long64_t nentries = tree->GetEntriesFast();
525 // std::cout << "::entry=" << global_entry
526 // << ", nentries=" << nentries
527 // << ", local=" << entry
528 // << " (min=" << m_collEvts[collIdx].min_entries
529 // << ", max=" << m_collEvts[collIdx].max_entries << ")"
530 // << " (tree=" << tree << ")"
531 // << std::endl;
532 if ( nentries > entry ) {
533
534 // load data from tuple
535 //std::cout << "--load-data--" << " " << tree->GetReadEntry() << std::endl;
536 if (tree->LoadTree(entry) < 0) {
538 ("Problem loading tree for event [" << m_curEvt << "] !!");
539 throw "RootNtupleEventSelector: Problem loading input tree";
540 } else {
541 ATH_MSG_DEBUG("==> loaded-tree(" << m_curEvt << ")");
542 }
543
544 ++m_nbrEvts;
545 m_curEvt = global_entry + 1;
546
547 // std::cout << "--event-info--" << std::endl;
548 // event info
549 EventType* evtType = new EventType;
550 const std::size_t runNbr = 0;
551 EventInfo* evtInfo = new EventInfo(new EventID(runNbr, m_curEvt-1, 0), evtType);
552 if ( !m_dataStore->record( evtInfo, "TTreeEventInfo" ).isSuccess() ) {
553 ATH_MSG_ERROR ("Could not record TTreeEventInfo !");
554 delete evtInfo; evtInfo = 0;
555 return StatusCode::FAILURE;
556 }
557
558 {
559 auto ei = std::make_unique<xAOD::EventInfo>();
560 auto ei_store = std::make_unique<xAOD::EventAuxInfo>();
561 ei->setStore (ei_store.get());
562 ei->setRunNumber (runNbr);
563 ei->setEventNumber (global_entry);
564
565 static const SG::AuxElement::Accessor<std::string> tupleName ("tupleName");
566 static const SG::AuxElement::Accessor<std::string> collName ("collectionName");
567 tupleName(*ei) = m_tupleNames[tupleIdx];
568 collName(*ei) = m_inputCollectionsName[collIdx];
569
570 CHECK( m_dataStore->record (std::move(ei), "EventInfo") );
571 CHECK( m_dataStore->record (std::move(ei_store), "EventInfoAux.") );
572 }
573
574 // BeginInputFile is deferred to handle() on BeginEvent — data must
575 // be loaded in the store before listeners' handle() is called.
576 return StatusCode::SUCCESS;
577
578 } else {
579 // file is depleted
580 CHECK( endInputFile (rctx) );
581 rctx->setFileIndex (rctx->fileIndex() + 1);
582 rctx->setTree(NULL);
583 return next(*rctx);
584 }
585
586 // NOT REACHED
587 // std::cout << "***end of collections***" << std::endl;
588 // end of collections
589 //return StatusCode::FAILURE;
590}
591
592StatusCode RootNtupleEventSelector::next( Context& ctx, int jump ) const
593{
594 ATH_MSG_DEBUG ("next(" << jump << ") : iEvt " << m_curEvt);
595
596 if (self()->seek(ctx, m_curEvt + jump).isSuccess()) {
597 return StatusCode::FAILURE;
598 }
599 return next(ctx);
600}
601
602StatusCode
603RootNtupleEventSelector::previous( IEvtSelector::Context& ctx ) const
604{
605 return next( ctx, -1 );
606}
607
608StatusCode
609RootNtupleEventSelector::previous( Context& ctx, int jump ) const
610{
611 return next( ctx, -jump );
612}
613
614StatusCode
615RootNtupleEventSelector::last( Context& /*ctxt*/ ) const
616{
617 ATH_MSG_ERROR ("............. Last Event Not Implemented .............");
618 return StatusCode::FAILURE;
619}
620
621
622StatusCode
623RootNtupleEventSelector::rewind( Context& ctxt ) const
624{
625 return self()->seek(ctxt, 0);
626}
627
628StatusCode
630{
632 refCtx = ctx;
633 return StatusCode::SUCCESS;
634}
635
636StatusCode
637RootNtupleEventSelector::createAddress( const Context& /*refCtx*/,
638 IOpaqueAddress*& /*addr*/ ) const
639{
640 //std::cerr << "::TTES::createAddress()...\n";
641 return StatusCode::SUCCESS;
642}
643
644StatusCode
646{
647 RootNtupleEventContext *ctx = dynamic_cast<RootNtupleEventContext*>(refCtxt);
648 if ( ctx ) {
649 delete ctx; ctx = 0;
650 return StatusCode::SUCCESS;
651 }
652
653 return StatusCode::FAILURE;
654}
655
656StatusCode
657RootNtupleEventSelector::resetCriteria( const std::string&, Context& ) const
658{
659 ATH_MSG_ERROR ("............. resetCriteria Not Implemented .............");
660 return StatusCode::FAILURE;
661}
662
664// Non-const methods:
666
671StatusCode
672RootNtupleEventSelector::seek (Context& ctx, int evtnum) const
673{
674 RootNtupleEventContext* rctx = dynamic_cast<RootNtupleEventContext*>(&ctx);
675 if (!rctx) {
676 return StatusCode::FAILURE;
677 }
678
679 // std::cout << "::seek - evtnum=" << evtnum
680 // << " curevt=" << m_curEvt
681 // << " curcol=" << rctx->fileIndex()
682 // << std::endl;
683 long coll_idx, tuple_idx;
684 find_coll_idx(evtnum, coll_idx, tuple_idx);
685 // std::cout << "::seek - evtnum=" << evtnum
686 // << " curevt=" << m_curEvt
687 // << " curcol=" << rctx->fileIndex()
688 // << " colidx=" << coll_idx
689 // << std::endl;
690 if ((coll_idx == -1 || tuple_idx == -1) && evtnum < m_curEvt) {
691 coll_idx = rctx->fileIndex();
692 tuple_idx = rctx->tupleIndex();
693 }
694
695 if (coll_idx == -1 || tuple_idx == -1) {
696 ATH_MSG_INFO("seek: reached end of input.");
697 return StatusCode::RECOVERABLE;
698 }
699
700 if (coll_idx != static_cast<int>(rctx->fileIndex()) ||
701 tuple_idx != static_cast<int>(rctx->tupleIndex()))
702 {
703 // tell everyone we switched files...
704 m_tuple = NULL;
705 CHECK( endInputFile (rctx) );
706 }
707
708 rctx->setFileIndex (coll_idx);
709 rctx->setTupleIndex (tuple_idx);
710 m_curEvt = evtnum;
711
712 return StatusCode::SUCCESS;
713}
714
719int
720RootNtupleEventSelector::curEvent (const Context& /*refCtxt*/) const
721{
722 return m_curEvt;
723}
724
727StatusCode
729{
730 ATH_MSG_INFO("I/O reinitialization...");
731
732 ServiceHandle<IIoComponentMgr> iomgr("IoComponentMgr", name());
733 if (!iomgr.retrieve().isSuccess()) {
734 ATH_MSG_FATAL("Could not retrieve IoComponentMgr !");
735 return StatusCode::FAILURE;
736 }
737 if (!iomgr->io_hasitem(this)) {
738 ATH_MSG_FATAL("IoComponentMgr does not know about myself !");
739 return StatusCode::FAILURE;
740 }
741 std::vector<std::string> inputCollections = m_inputCollectionsName.value();
742
743 for (std::size_t
744 i = 0,
745 imax = m_inputCollectionsName.value().size();
746 i < imax;
747 ++i) {
748 std::string &fname = inputCollections[i];
749 // std::cout << "--retrieve new name for [" << fname << "]...\n";
750 if (!iomgr->io_contains(this, fname)) {
751 ATH_MSG_ERROR("IoComponentMgr does not know about [" << fname << "] !");
752 return StatusCode::FAILURE;
753 }
754 if (!iomgr->io_retrieve(this, fname).isSuccess()) {
755 ATH_MSG_FATAL("Could not retrieve new value for [" << fname << "] !");
756 return StatusCode::FAILURE;
757 }
758 // std::cout << "--> [" << fname << "]\n" << std::flush;
759 }
760 // all good... copy over.
761 m_inputCollectionsName = inputCollections;
762
763 // remove our EventInfo if any...
764 // {
765 // const bool force_remove = true;
766 // if (!m_dataStore->clearStore(force_remove).isSuccess()) {
767 // ATH_MSG_ERROR("could not clear event store!");
768 // return StatusCode::FAILURE;
769 // } else {
770 // ATH_MSG_INFO("sgdump: \n" << m_dataStore->dump());
771 // }
772 // }
773
774 // std::cout << "--> do_init_io...\n" << std::flush;
775 if (!do_init_io().isSuccess()) {
776 return StatusCode::FAILURE;
777 }
778
779 ATH_MSG_INFO("I/O reinitialization... [done]");
780 return StatusCode::SUCCESS;
781}
782
783
787StatusCode
789 tadList& /*tads*/)
790{
791 // std::cerr << "TTES::preLoadAddresses(" << int(storeID)
792 // << "," << tads.size()
793 // << ")...\n";
794 return StatusCode::SUCCESS;
795}
796
798StatusCode
800{
801 if (m_needReload) {
802 return createRootBranchAddresses(storeID, tads);
803 }
804
805 return StatusCode::SUCCESS;
806}
807
809StatusCode
811 const EventContext& /*ctx*/)
812{
813 if (tad) {
814 if (m_dataStore->proxy_exact (tad->sgkey())) {
815 return StatusCode::SUCCESS;
816 }
817 return StatusCode::FAILURE;
818 }
819 // do nothing.
820 return StatusCode::SUCCESS;
821}
822
823
825// Protected methods:
827
829void
830RootNtupleEventSelector::setupInputCollection( Gaudi::Details::PropertyBase& /*inputCollectionsName*/ )
831{
832 // nothing ?
833 return;
834}
835
836StatusCode
838 tadList &tads)
839{
840 if (storeID != StoreID::EVENT_STORE) {
841 ATH_MSG_INFO("-- not the event-store --");
842 return(StatusCode::SUCCESS);
843 }
844
845 if (0 == m_tuple) {
846 ATH_MSG_ERROR("null pointer to n-tuple !");
847 return StatusCode::FAILURE;
848 }
849
850 TObjArray *leaves = m_tuple->GetListOfLeaves();
851 if (!leaves) {
852 ATH_MSG_INFO("no leaves!!");
853 return StatusCode::SUCCESS;
854 }
855
856 // loop over leaves
857 for (Int_t i = 0; i < leaves->GetEntries(); ++i) {
858 TLeaf *leaf = (TLeaf *)leaves->At(i);
859 TBranch *branch = leaf->GetBranch();
860 if (branch) {
861
862 CLID id = 0;
863 const void* value_ptr = m_tuple;
864 const std::string type_name = leaf->GetTypeName();
865 const std::string br_name = branch->GetName();
866 const std::string sg_key = br_name;//m_tupleName.value()+"/"+br_name;
867 TClass *cls = TClass::GetClass(type_name.c_str());
868 const std::type_info *ti = 0;
869
870 if (cls) {
871 ti = cls->GetTypeInfo();
872 // first, try to load a dict for that class...
873 if (ti) {
874 m_dictsvc->load_type(*ti);
875 }
876 if (!ti) {
877 ATH_MSG_WARNING("could not find a type-info for [" <<
878 type_name << "]");
879 continue;
880 }
881 std::string ti_typename = System::typeinfoName(*ti);
882 if (!m_clidsvc->getIDOfTypeInfoName(ti_typename, id)
883 .isSuccess()) {
884 // try another one...
885 {
886 // Protect against data race inside TClassEdit.
887 // https://github.com/root-project/root/issues/10353
888 // Should be fixed in root 6.26.02.
889 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
890 ti_typename = TClassEdit::ShortType(ti_typename.c_str(),
891 TClassEdit::kDropAllDefault);
892 }
893 if (!m_clidsvc->getIDOfTypeInfoName(ti_typename, id)
894 .isSuccess()) {
895 ATH_MSG_DEBUG("** could not find a CLID from type-info ["
896 << System::typeinfoName(*ti) << "]");
897 ATH_MSG_DEBUG("** could not find a CLID from type-info-alias ["
898 << ti_typename << "]");
899 continue;
900 }
901 }
902 } else {
903 // probably a built-in type...
904 if (!m_clidsvc->getIDOfTypeName(::root_typename(type_name), id)
905 .isSuccess()) {
906 ATH_MSG_DEBUG("** could not find a CLID for type-name ["
907 << type_name << "]");
908 continue;
909 }
910 }
911 if (id == 0) {
912 ATH_MSG_DEBUG("** could not find a CLID for type-name ["
913 << type_name << "]");
914 continue;
915 }
917 (ROOT_StorageType, id,
918 m_tuple->GetName(),
919 br_name,
920 (unsigned long)(value_ptr),
921 (unsigned long)(m_curEvt-1));
922
923 // recycle old rootaddress, if any.
924 SG::DataProxy* proxy = m_dataStore->proxy (id, sg_key);
925 if (proxy) {
926 proxy->setAddress (addr);
927 }
928 else {
929 auto taddr = new SG::TransientAddress(id, sg_key, addr, false);
930 taddr->setProvider(this, storeID);
931 // only add the *new* TransientAddress to the input list as the *old* ones
932 // are already tracked by the datastore (via the sticky proxies)
933 tads.push_back(taddr);
934 }
935 }
936 }
937 m_needReload = false;
938 // BeginInputFile is deferred to handle() on BeginEvent — see comment there.
939
940 return StatusCode::SUCCESS;
941}
942
943StatusCode
945 TTree *tree,
946 const std::string& prefix) const
947{
948 if (0 == store) {
949 ATH_MSG_ERROR("null pointer to store !");
950 return StatusCode::FAILURE;
951 }
952
953 if (0 == tree) {
954 ATH_MSG_ERROR("null pointer to n-tuple !");
955 return StatusCode::FAILURE;
956 }
957
958 // Record tree in Storegate for later writing
959 TransferTree* temp = new TransferTree(tree);
960 if (store->record(temp,prefix).isFailure()) ATH_MSG_ERROR("Unable to record metadata tree " << tree->GetName());
961
962 const std::string tree_name = tree->GetName();
963 TObjArray *branches = tree->GetListOfBranches();
964 if (!branches) {
965 ATH_MSG_INFO("no branches!!");
966 return StatusCode::SUCCESS;
967 }
968
969 // loop over branches
970 for (Int_t i = 0; i < branches->GetEntries(); ++i) {
971 TBranch *branch = (TBranch *)branches->At(i);
972 if (branch) {
973
974 CLID id = 0;
975 const void* value_ptr = tree;
976 const std::string type_name = branch->GetClassName();
977 const std::string br_name = branch->GetName();
978 const std::string sg_key = prefix.empty()
979 ? br_name
980 : prefix + "/" + br_name;
981 TClass *cls = NULL;
982 if (!type_name.empty()) {
983 cls = TClass::GetClass(type_name.c_str());
984 }
985 const std::type_info *ti = 0;
986
987 if (cls) {
988 ti = cls->GetTypeInfo();
989 // first, try to load a dict for that class...
990 if (ti) {
991 m_dictsvc->load_type(*ti);
992 }
993 if (!ti) {
994 ATH_MSG_WARNING("could not find a type-info for [" <<
995 type_name << "]");
996 continue;
997 }
998 std::string ti_typename = System::typeinfoName(*ti);
999 if (!m_clidsvc->getIDOfTypeInfoName(ti_typename, id)
1000 .isSuccess()) {
1001 // try another one...
1002 {
1003 // Protect against data race inside TClassEdit.
1004 // https://github.com/root-project/root/issues/10353
1005 // Should be fixed in root 6.26.02.
1006 R__WRITE_LOCKGUARD(ROOT::gCoreMutex);
1007 ti_typename = TClassEdit::ShortType(ti_typename.c_str(),
1008 TClassEdit::kDropAllDefault);
1009 }
1010 if (!m_clidsvc->getIDOfTypeInfoName(ti_typename, id)
1011 .isSuccess()) {
1012 ATH_MSG_INFO("** could not find a CLID from type-info ["
1013 << System::typeinfoName(*ti) << "]");
1014 ATH_MSG_INFO("** could not find a CLID from type-info-alias ["
1015 << ti_typename << "]");
1016 continue;
1017 }
1018 }
1019 } else {
1020 // probably a built-in type...
1021 TObjArray *leaves = branch->GetListOfLeaves();
1022 if (leaves &&
1023 leaves->GetEntries() == 1) {
1024 const std::string type_name = ((TLeaf*)leaves->At(0))->GetTypeName();
1025 if (!m_clidsvc->getIDOfTypeName(::root_typename(type_name), id)
1026 .isSuccess()) {
1027 ATH_MSG_INFO("** could not find a CLID for type-name ["
1028 << type_name << "]");
1029 continue;
1030 }
1031 }
1032 }
1033 if (id == 0) {
1034 ATH_MSG_INFO("** could not find a CLID for type-name ["
1035 << type_name << "]");
1036 continue;
1037 }
1040 (ROOT_StorageType, id,
1041 tree_name,
1042 br_name,
1043 (unsigned long)(value_ptr),
1044 (unsigned long)(0)));
1045 if (!store->recordAddress(sg_key, std::move(addr), true).isSuccess()) {
1046 ATH_MSG_ERROR("could not record address at [" << sg_key << "] in store ["
1047 << store->name() << "]");
1048 }
1049 // SG::TransientAddress* taddr = new SG::TransientAddress
1050 // (id, sg_key, addr);
1051 // taddr->setProvider(this);
1052 // taddr->clearAddress(true);
1053 // tads.push_back(taddr);
1054 }
1055 }
1056 return StatusCode::SUCCESS;
1057}
1058
1059TTree*
1061 const std::string& tupleName) const
1062{
1063 // std::cout << "::fetchNtuple(" << fname << ")..." << std::endl;
1064 TTree* tree = NULL;
1066 // std::cout << "::TFile::Open()..." << std::endl;
1067 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(fname.c_str());
1068 TFile* fnew = nullptr;
1069 if (!f) {
1070 f = TFile::Open(fname.c_str(), "READ");
1071 fnew = f;
1072 if (f) {
1073 f->SetName(fname.c_str());
1074 }
1075 }
1076 if (!f || f->IsZombie()) {
1077 ATH_MSG_ERROR("could not open next file in input collection ["
1078 << fname << "]");
1079 if (f) {
1080 f->Close();
1081 }
1082 return tree;
1083 }
1084 // std::cout << "::TFile::GetTree(" << m_tupleName << ")..." << std::endl;
1085 tree = (TTree*)f->Get(tupleName.c_str());
1086 if (!tree) {
1087 ATH_MSG_ERROR("could not retrieve tree [" << tupleName << "]"
1088 << " from file [" << fname << "]");
1089 f->Close();
1090 return tree;
1091 }
1092
1093 if (fnew)
1094 m_files.push_back(fnew);
1095
1096 // std::cout << "::TTree::SetBranchStatus()..." << std::endl;
1097 // disable all branches
1098 tree->SetBranchStatus("*", 0);
1099
1100 if (!m_imetaStore->clearStore().isSuccess()) {
1101 ATH_MSG_INFO("could not clear store [" << m_imetaStore.typeAndName() << "]");
1102 return tree;
1103 }
1104
1105 addMetadataFromDirectoryName(tupleName+"Meta", f);
1106 addMetadataFromDirectoryName("Lumi", f, "Lumi");
1107 return tree;
1108}
1109
1110void RootNtupleEventSelector::addMetadataFromDirectoryName(const std::string &metadirname, TFile *fileObj, const std::string &prefix) const
1111{
1112 TDirectoryFile *metadir = (TDirectoryFile*)fileObj->Get(metadirname.c_str());
1113 if (!metadir) return;
1114 addMetadataFromDirectory(metadir, prefix);
1115}
1116
1117void RootNtupleEventSelector::addMetadataFromDirectory(TDirectoryFile *metadir, const std::string &prefix) const
1118{
1119 std::unordered_set<std::string> meta_keys;
1120 const TList *keys = metadir->GetListOfKeys();
1121 for (Int_t i=0; i < keys->GetSize(); ++i) {
1122 TKey* key = dynamic_cast<TKey*>(keys->At(i));
1123 if (!key) {
1124 continue;
1125 }
1126
1127 const std::string meta_key = key->GetName();
1128 if (!meta_keys.emplace(key->GetName()).second) {
1129 // key was already in the set:
1130 // meta_key is another cycle from a previous key entry.
1131 // *ASSUME* the highest cycle is the one we are interested in
1132 // *AND* that it was the previous one...
1133 continue;
1134 }
1135
1136 std::string fullPrefix(prefix);
1137 if (prefix != "") fullPrefix += "/";
1138 const std::string path = fullPrefix + key->GetName();
1139
1140 TString fullKeyName(TString::Format("%s;%hi", key->GetName(), key->GetCycle()));
1141 TObject *objRef = metadir->Get(fullKeyName);
1142
1143 TTree *metatree = dynamic_cast<TTree*>(objRef);
1144 if (metatree) {
1145 addMetadata(metatree, path);
1146 continue;
1147 }
1148
1149 TObjString *metaObjString = dynamic_cast<TObjString*>(objRef);
1150 if (metaObjString) {
1151 addMetadata(metaObjString, path);
1152 continue;
1153 }
1154
1155 ATH_MSG_WARNING("Unsupported metadata type: " << objRef->ClassName());
1156 }
1157}
1158
1159void RootNtupleEventSelector::addMetadata(TTree *metatree, const std::string &path) const
1160{
1161 if (metatree->GetEntry(0) < 0) {
1162 ATH_MSG_INFO("Problem retrieving data from metadata-tree [" << path << "] !!");
1163 return;
1164 }
1165
1166 if (!createMetaDataRootBranchAddresses(m_imetaStore.get(), metatree, path).isSuccess()) {
1167 ATH_MSG_INFO("Could not create metadata for tree [" << path << "]");
1168 }
1169}
1170
1171void RootNtupleEventSelector::addMetadata(TObjString *metastring, const std::string &path) const
1172{
1173 std::string *converted = new std::string(metastring->String());
1174 if (!m_imetaStore->record(converted, path).isSuccess()) {
1175 ATH_MSG_INFO("Could not create metadata for string [" << path << "]");
1176 }
1177}
1178
1179StatusCode
1181{
1182 // std::cout << "::fetchNtuple..." << std::endl;
1183
1184 // initialize some helper structures and data
1185 {
1186 CollMetaData zero;
1187 zero.min_entries = -1;
1188 zero.max_entries = -1;
1189 zero.entries = -1;
1190 m_collEvts.resize (m_tupleNames.size());
1191 for (size_t i = 0; i < m_collEvts.size(); i++) {
1192 m_collEvts[i].resize(m_inputCollectionsName.value().size(), zero);
1193 }
1194 }
1195
1196 m_tuple = fetchNtuple(m_inputCollectionsName.value()[0],
1197 m_tupleNames[0]);
1198 if (!m_tuple) {
1199 throw "RootNtupleEventSelector: Unable to fetch Ntuple";
1200 }
1201
1202 // std::cout << "::clear-root-addresses..." << std::endl;
1203 // reset the list of branches
1204 m_needReload = true;
1205
1206 // skip events we are asked to skip
1207 m_curEvt = m_skipEvts;
1208 m_nbrEvts = 0;
1209
1210 // std::cout << "::fetchNtuple...[done]" << std::endl;
1211 return StatusCode::SUCCESS;
1212}
1213
1218void
1219RootNtupleEventSelector::find_coll_idx (int evtidx,
1220 long& coll_idx,
1221 long& tuple_idx) const
1222{
1223 coll_idx = -1;
1224 tuple_idx = -1;
1225
1226 // std::cout << "--find_coll_idx(" << evtidx << ")..." << std::endl
1227 // << "--collsize: " << m_collEvts.size() << std::endl;
1228 for (size_t ituple = 0; ituple < m_collEvts.size(); ++ituple) {
1229 for (size_t icoll = 0; icoll < m_collEvts[ituple].size(); ++icoll) {
1230 CollMetaData &itr = m_collEvts[ituple][icoll];
1231 if (itr.min_entries == -1) {
1232 TTree *tree = fetchNtuple(m_inputCollectionsName.value()[icoll],
1233 m_tupleNames[ituple]);
1234 if (tree) {
1235 long offset = 0;
1236 if (icoll > 0) {
1237 offset = m_collEvts[ituple][icoll-1].max_entries;
1238 }
1239 else if (ituple > 0) {
1240 offset = m_collEvts[ituple-1].back().max_entries;
1241 }
1242 itr.entries = tree->GetEntriesFast();
1243 itr.min_entries = offset;
1244 itr.max_entries = offset + itr.entries;
1245 } else {
1246 throw "RootNtupleEventSelector: Unable to fetch ntuple";
1247 }
1248 }
1249 // std::cout << "--[" << i << "] => [" << itr.min_entries << ", "
1250 // << itr.max_entries << ") evtidx=[" << evtidx << "]"
1251 // << std::endl;
1252 if (itr.min_entries <= evtidx && evtidx < itr.max_entries) {
1253 coll_idx = icoll;
1254 tuple_idx = ituple;
1255 return;
1256 }
1257 }
1258 }
1259}
1260
1262int RootNtupleEventSelector::size (Context& /*refCtxt*/) const {
1263 //use find_coll_idx to trigger a population of the m_collEvts
1264 long coll_idx, tuple_idx;
1265 find_coll_idx(-1, coll_idx, tuple_idx);
1266 return m_collEvts.back().back().max_entries;
1267}
1268
1269
1270void RootNtupleEventSelector::handle(const Incident& incident) {
1271 if (m_fireBIF && incident.type() == IncidentType::BeginEvent) {
1272 std::string fname = m_tuple->GetCurrentFile()->GetName();
1274 fname, {},
1275 /*endFileName=*/fname);
1276 m_fireBIF = false;
1277 }
1278}
1279
1280} //> namespace Athena
#define endmsg
#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)
macros to associate a CLID to a type
#define CLASS_DEF(NAME, CID, VERSION)
associate a clid and a version to a type eg
#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.
size_t size() const
Number of registered mappings.
Include TBranchElement.h, suppressing clang warnings.
int imax(int i, int j)
A simple class to hold the buffer of a TBranch from a TTree.
state of a few global resources from ROOT and restores their initial value upon d-tor call.
ROOT specific event selector context.
virtual void * identifier() const
context identifier
long m_tupleIdx
current tuple index (into `m_tupleNames')
void setTree(TTree *tree)
set the tree used to iterate
std::size_t fileIndex() const
access to the file iterator
std::vector< std::string > FileNames_t
definition of the file container
const std::string & fid() const
access to the connection FID
virtual ~RootNtupleEventContext()
standard d-tor
void setFileIndex(std::size_t idx)
set file iterator
long m_collIdx
current collection index (into m_inputCollectionsName)
int64_t entry() const
access to the current event entry number
const RootNtupleEventSelector * m_evtsel
reference to the hosting event selector instance
TTree * tree() const
access to the tree used to iterate
void setFID(const std::string &fid)
set connection FID
RootNtupleEventContext(const RootNtupleEventSelector *sel)
standard c-tor with initialization
Class implementing the GAUDI IEvtSelector interface using ROOT TTree as a backend.
virtual StatusCode seek(Context &refCtxt, int evtnum) const override
Seek to a given event number.
virtual StatusCode finalize() override
virtual int size(Context &refCtxt) const override
ICollectionSize interface
RootNtupleEventSelector(const std::string &name, ISvcLocator *svcLoc)
Constructor with parameters:
virtual StatusCode releaseContext(Context *&refCtxt) const override
virtual int curEvent(const Context &refCtxt) const override
return the current event number.
void setupInputCollection(Gaudi::Details::PropertyBase &inputCollectionsName)
callback to synchronize the list of input files
virtual StatusCode loadAddresses(StoreID::type storeID, tadList &list) override
get all new addresses from Provider for this Event.
virtual StatusCode last(Context &refContext) const override
virtual StatusCode resetCriteria(const std::string &cr, Context &ctx) const override
virtual StatusCode preLoadAddresses(StoreID::type storeID, tadList &list) override
TTree * m_tuple
current tree being read
std::vector< std::vector< CollMetaData > > m_collEvts
helper method to get the collection index (into m_inputCollectionsName) and tuple index (into m_tuple...
bool m_needReload
The (python) selection function to apply on the TChain we are reading.
virtual StatusCode updateAddress(StoreID::type storeID, SG::TransientAddress *tad, const EventContext &ctx) override
update a transient Address
virtual StatusCode next(Context &refCtxt) const override
StatusCode endInputFile(RootNtupleEventContext *rctx) const
StatusCode do_init_io()
helper method to init the i/o components
StatusCode createMetaDataRootBranchAddresses(StoreGateSvc *store, TTree *tree, const std::string &prefix) const
helper method to create proxies for the metadata store
bool m_fireBIF
Flag to fire BeginInputFile on the next BeginEvent incident.
void addMetadataFromDirectoryName(const std::string &metadirname, TFile *fileObj, const std::string &prefix="") const
virtual StatusCode createContext(Context *&refpCtxt) const override
std::optional< InputFileIncidentGuard > m_inputFileGuard
RAII guard: guarantees a matching EndInputFile for every BeginInputFile.
void addMetadataFromDirectory(TDirectoryFile *metadir, const std::string &prefix="") const
void addMetadata(TTree *metatree, const std::string &path="") const
TTree * fetchNtuple(const std::string &fname, const std::string &tupleName) const
helper method to retrieve the correct tuple
virtual void handle(const Incident &incident) override
StatusCode createRootBranchAddresses(StoreID::type storeID, tadList &tads)
helper method to create proxies
virtual StatusCode initialize() override
virtual StatusCode previous(Context &refCtxt) const override
virtual StatusCode io_reinit() override
Callback method to reinitialize the internal state of the component for I/O purposes (e....
virtual StatusCode rewind(Context &refCtxt) const override
virtual StatusCode createAddress(const Context &refCtxt, IOpaqueAddress *&) const override
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.
void record(const T *p, const std::string &key)
Definition TestStore.h:81
virtual const std::string & name() const override
Definition TestStore.cxx:97
sgkey_t sgkey() const
Set the primary (hashed) SG key.
The Athena Transient Store API.
@ EVENT_STORE
Definition StoreID.h:26
void zero(TH2 *h)
zero the contents of a 2d histogram
std::vector< std::string > files
file names and file pointers
Definition hcg.cxx:50
Some weak symbol referencing magic... These are declared in AthenaKernel/getMessageSvc....
RootNtupleEventContext::FileNames_t FileNames_t
find_coll_idx(-1, coll_idx, tuple_idx)
StatusCode ROOTMessageFilterSvc::initialize ATLAS_NOT_THREAD_SAFE()
Return the file descriptor fataldump() uses for output.
StatusCode parse(std::tuple< Tup... > &tup, const Gaudi::Parsers::InputData &input)
@ active
Definition Layer.h:47
EventInfo_v1 EventInfo
Definition of the latest event info version.
TChain * tree