ATLAS Offline Software
Loading...
Searching...
No Matches
REvent.cxx
Go to the documentation of this file.
1// Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
2
3// Local include(s).
5
6#include "IOUtils.h"
20
21// Framework include(s).
31#ifndef XAOD_STANDALONE
33#endif
34
35// ROOT include(s).
36#include <TFile.h>
37#include <TKey.h>
38#include <TMethodCall.h>
39
40#include <ROOT/RNTuple.hxx>
41
42// System include(s).
43#include <regex>
44#include <stdexcept>
45#include <typeinfo>
46#include <utility>
47
48namespace {
49
59std::string getFirstFieldMatch(ROOT::RNTupleReader& reader,
60 const std::string& pre) {
61
62 const std::regex pattern(".*" + pre + ".*");
63 for (const auto& field : reader.GetDescriptor().GetTopLevelFields()) {
64
65 if (std::regex_match(field.GetFieldName(), pattern)) {
66 return field.GetFieldName();
67 }
68 }
69
70 return pre;
71}
72
73std::string getFieldNameFromKey( const std::string& key ) {
74
75 // build RNTuple field name from the key of the output object
76 // RNTuple field names require replacing '.' with ':' for <cont>Aux. or <cont>AuxDyn.<var>
77 std::string fieldName = key;
78 if (fieldName.rfind("Aux.") != std::string::npos || fieldName.rfind("AuxDyn.") != std::string::npos) {
79 std::replace(fieldName.begin(), fieldName.end(), '.', ':');
80 }
81 return fieldName;
82}
83
84
85StatusCode getInfoForFieldCreation( const std::string& key, const xAOD::TVirtualManager& mgr,
86 std::string& fieldName, std::string& className ) {
87
88 // Get field name from the key
89 fieldName = getFieldNameFromKey(key);
90
91 // Get class name from holder
92 // There are two managers to consider:
93 // ROutObjManager - standard objects
94 // RAuxFieldManager - aux either simple type (isPrimitive) or - aux non-simple type
95 // Check for ROutObjManager
96 const xAOD::Experimental::ROutObjManager* omgr = dynamic_cast< const xAOD::Experimental::ROutObjManager* >( &mgr );
97
98
99 // ATH_MSG_DEBUG("REvent::getInfoForFieldCreation - found outObjMgr for key " << key << ", " << omgr);
100
101
102 if( omgr ) {
103
104 // ATH_MSG_DEBUG("REvent::getInfoForFieldCreation - get className ");
105
106 className = omgr->holder()->getClass()->GetName();
107
108 // ATH_MSG_DEBUG("REvent::getInfoForFieldCreation - get className " << className);
109
110 }
111 else {
112 // Check for RAuxFieldManager
113
114 // ATH_MSG_DEBUG("REvent::getInfoForFieldCreation - is rauxFieldMgr for key " << key);
115
116 const xAOD::Experimental::RAuxFieldManager* auxmgr = dynamic_cast< const xAOD::Experimental::RAuxFieldManager* >( &mgr );
117
118 // ATH_MSG_DEBUG("REvent::getInfoForFieldCreation - found rauxFieldMgr for key " << key << ", " << auxmgr);
119
120
121 if( auxmgr ) {
122 if ( auxmgr->isPrimitive() ) {
123
124 // ATH_MSG_DEBUG("REvent::getInfoForFieldCreation - get className for primative ");
125
126 className = xAOD::Utils::getTypeName( *auxmgr->holder()->getTypeInfo() );
127 }
128 else {
129
130 // ATH_MSG_DEBUG("REvent::getInfoForFieldCreation - get className for non-primative ");
131
132 className = auxmgr->holder()->getClass()->GetName();
133 }
134 }
135 }
136
137 // ATH_MSG_DEBUG("REvent::getInfoForFieldCreation - fieldName " << fieldName << " className " << className);
138
139 return StatusCode::SUCCESS;
140}
141
142
143} // namespace
144
145namespace xAOD::Experimental {
146
147REvent::REvent(const EventContext* ctx /* = nullptr*/)
148 : Event("xAOD::Experimental::REvent", ctx)
149{}
150
152
153 // Clear the input and output (meta-)objects before the input/output files
154 // would be closed. Otherwise we can be left with RNTuple view objects
155 // pointing nowhere. This has to be done here, as the containers are members
156 // of the base class, which are only destroyed after the readers of this
157 // class.
158 m_inputObjects.clear();
159 m_outputObjects.clear();
160 m_inputMetaObjects.clear();
161 m_outputMetaObjects.clear();
162}
163
165StatusCode REvent::readFrom(TFile& inFile) {
166 ATH_CHECK(readFrom(inFile.GetName()));
167 return StatusCode::SUCCESS;
168}
169
176StatusCode REvent::readFrom(std::string_view fileName) {
177
178 ATH_MSG_INFO("REvent::readFrom: fileName " << fileName);
179
180 // Set up the file access tracer.
182
183 // Clear the cached input objects.
184 m_inputObjects.clear();
185 m_inputMissingObjects.clear();
186 m_inputMetaObjects.clear();
187 {
189 lock.upgrade();
190 m_branches.clear();
191 }
192 m_eventReader.reset();
193
194 // Reset the internal flags.
195 m_entry = -1;
197
198 // Clear out the current object.
200
201
202 ATH_MSG_DEBUG("Create RNTupleReader for \"" << METADATA_OBJECT_NAME
203 << "\" in file: " << fileName);
204
205 // Set up a reader for the metadata ntuple.
206 // Since some types are non-xAOD types and so not 'visible' when running in AnalysisBase
207 // we need to protect for unknown types with SetEmulateUnknownTypes(true)
208 ROOT::RNTupleDescriptor::RCreateModelOptions opts;
209 opts.SetEmulateUnknownTypes(true);
210 m_metaReader = ROOT::RNTupleReader::Open(opts, METADATA_OBJECT_NAME, fileName);
211 if (!m_metaReader) {
212 ATH_MSG_ERROR("Couldn't find \"" << METADATA_OBJECT_NAME
213 << "\" tree in input file: " << fileName);
214 return StatusCode::FAILURE;
215 }
216 ATH_MSG_DEBUG("Created RNTupleReader for \"" << METADATA_OBJECT_NAME
217 << "\" in file: " << fileName);
218
219 // Make sure that the xAOD::EventFormat dictonary is loaded.
220 // This may not be the case if streamer information reading is turned
221 // off.
222 static const std::string eventFormatTypeName =
224 if (::TClass::GetClass(eventFormatTypeName.c_str()) == nullptr) {
225 ATH_MSG_WARNING("Couldn't load the EventFormat dictionary");
226 }
227 ATH_MSG_VERBOSE("Loaded the xAOD::EventFormat dictionary");
228
229 // Helper lambda for collecting the event format metadata from an RNTuple
230 // with a given name.
231 auto readEventFormatMetadata = [&](std::string_view tupleName) -> StatusCode {
232 // Set up a reader. This may technically be the same as m_metaReader, but
233 // it's easier to write the code this way.
234 auto metaReader = ROOT::RNTupleReader::Open(tupleName, fileName);
235 if (!metaReader) {
236 ATH_MSG_ERROR("Couldn't find \""
237 << tupleName << "\" ntuple in input file: " << fileName);
238 return StatusCode::FAILURE;
239 }
240 ATH_MSG_VERBOSE("Created temporary RNTupleReader for \""
241 << tupleName << "\" in file: " << fileName);
242
243 // Try to read in the event format metadata.
244 const std::string eventFormatFieldName =
245 getFirstFieldMatch(*m_metaReader, "EventFormat");
246 try {
247 // Add its elements to m_inputEventFormat.
248 auto ef = m_metaReader->GetView<xAOD::EventFormat>(eventFormatFieldName);
249 for (const auto& [key, element] : ef(0u)) {
250 m_inputEventFormat.add(element);
251 }
252 } catch (const ROOT::RException&) {
253 ATH_MSG_WARNING("Input file provides no event or metadata");
254 return StatusCode::RECOVERABLE;
255 }
256 ATH_MSG_VERBOSE("Merged event format metadata from \"" << tupleName
257 << "\" ntuple");
258
259 // Return gracefully.
260 return StatusCode::SUCCESS;
261 };
262
263 // Read in the metadata from the "main" metadata ntuple.
264 const StatusCode sc = readEventFormatMetadata(METADATA_OBJECT_NAME);
265 if (sc.isRecoverable()) {
267 return StatusCode::SUCCESS;
268 }
269 ATH_CHECK(sc);
270
271 // List all the other Metadata RNTuples in the input file.
272 // Having several metadata tuples can happen for augmented files
273 // as one metadata tree per stream is produced.
274 std::set<std::string> lOtherMetaTupleNames;
275 {
276 std::unique_ptr<TFile> inFile(TFile::Open(fileName.data(), "READ"));
277 TList* lKeys = inFile->GetListOfKeys();
278 if (lKeys == nullptr) {
279 ATH_MSG_ERROR("Could not get list of keys for input file: " << fileName);
280 return StatusCode::FAILURE;
281 }
282 for (const TObject* obj : *lKeys) {
283 const std::string keyName = obj->GetName();
284 // Make sure the key corresponds to a metadata ntuple but
285 // do not add the current metadata tree in the list of other trees
286 // and do not add the metadata tree handlers to the list
287 if ((keyName != METADATA_OBJECT_NAME) &&
288 (keyName.find("MetaData") != std::string::npos) &&
289 (keyName.find("MetaDataHdr") == std::string::npos)) {
290 // Make sure key corresponds to an RNTuple
291 const TKey* key = dynamic_cast<const TKey*>(obj);
292 if (key == nullptr) {
293 ATH_MSG_ERROR("Object describing \"" << keyName << "\" in file \""
294 << fileName
295 << "\" is not a TKey?");
296 return StatusCode::FAILURE;
297 }
298 const char* className = key->GetClassName();
299 static constexpr bool LOAD = kFALSE;
300 static constexpr bool SILENT = kTRUE;
301 ::TClass* cl = ::TClass::GetClass(className, LOAD, SILENT);
302 if ((cl != nullptr) && cl->InheritsFrom(ROOT::RNTuple::Class())) {
303 lOtherMetaTupleNames.insert(std::move(keyName));
304 }
305 }
306 }
307 }
308
309 // Read in the metadata from any additonal NTuples found (if any).
310 for (const std::string& tupleName : lOtherMetaTupleNames) {
311 ATH_CHECK(readEventFormatMetadata(tupleName));
312 }
313
314 // Set up the main ntuple reader.
315 // Files written by Athena also store non-xAOD types (e.g. DataHeader_p6) in the
316 // event ntuple, so protect for unknown types the same way as for the metadata
317 m_eventReader = ROOT::RNTupleReader::Open(opts, EVENT_RNTUPLE_NAME, fileName);
318 if (!m_eventReader) {
319 ATH_MSG_ERROR("Couldn't access RNTuple \"" << EVENT_RNTUPLE_NAME
320 << "\" in file: " << fileName);
321 return StatusCode::FAILURE;
322 }
323 ATH_MSG_DEBUG("Created RNTupleReader for \"" << EVENT_RNTUPLE_NAME
324 << "\" in file: " << fileName);
325
326 // Init the statistics collection.
328 // Update the event counter in the statistics object:
330 stats.setNEvents(stats.nEvents() + m_eventReader->GetNEntries());
331
332 // Notify the listeners that a new file was opened:
333 const TIncident beginIncident(IncidentType::BeginInputFile);
334 for (TVirtualIncidentListener* listener : m_listeners) {
335 listener->handle(beginIncident);
336 }
337 // For now implement a very simple scheme in which we claim already
338 // at the start that the entire file was processed. Since we have no way
339 // of ensuring that the user indeed does this. And we can't delay calling
340 // this function, as the user may likely close his/her output file before
341 // closing the last opened input file.
342 const TIncident endIncident(IncidentType::EndInputFile);
343 for (TVirtualIncidentListener* listener : m_listeners) {
344 listener->handle(endIncident);
345 }
346
347 // The initialisation was successful:
348 return StatusCode::SUCCESS;
349}
350
351
352
358StatusCode REvent::writeTo(TFile& file) {
359
360 // Save filefor writing
362
363 ATH_MSG_DEBUG("REvent::writeTo - opened output file " << m_outputFile->GetName());
364
365 // Access the EventFormat object associated with this file:
368
369 ATH_MSG_DEBUG("REvent::writeTo - creating RNTupleModel ");
370
371 // Create new model for this file
372 m_model = ROOT::RNTupleModel::Create();
373
374 // Set output RNTuple name as model description
375 const char* rnTupleName = EVENT_RNTUPLE_NAME;
376 m_model->SetDescription(rnTupleName);
377
378 // Return gracefully:
379 return StatusCode::SUCCESS;
380}
381
388StatusCode REvent::finishWritingTo(TFile& file) {
389
390 // A small sanity check for meta data writing - need output file as long as MetaData is in a rntuple:
391 if( m_outputFile != &file ) {
392 ATH_MSG_FATAL("File given to finishWritingTo does not match the file given in writeTo file!");
393 return StatusCode::FAILURE;
394 }
395
396 // Notify the listeners that they should write out their metadata, if they
397 // have any.
398 const TIncident incident( IncidentType::MetaDataStop );
399 for (auto& listener : m_listeners) {
400 listener->handle(incident);
401 }
402
403 // Now go to the output file:
404 m_outputFile->cd();
405
406 const char* outRNTupleName = METADATA_OBJECT_NAME;
407
408 // Check if there's already a metadata tree in the output, if so we can return:
409 if( m_outputFile->Get( outRNTupleName ) ) {
410
411 // Let's assume that the metadata is complete in the file already.
412 ATH_MSG_INFO( "Metadata tree already exists, returning" );
413
414 return StatusCode::SUCCESS;
415 }
416
417 // Write out meta data
418
419 // Create new model for this file
420 auto model = ROOT::RNTupleModel::Create();
421
422 // Set output RNTuple name as model description
423 model->SetDescription(outRNTupleName);
424
425
426 // Create field explicitly for EventFormat
427
428 // Check if we have a dictionary: for this object:
429 std::string typeName = SG::normalizedTypeinfoName( typeid( xAOD::EventFormat ) );
430 TClass* cl = TClass::GetClass( typeName.c_str() );
431 if( ! cl ) {
432 ATH_MSG_ERROR( "Didn't find dictionary for type: " << typeName );
433 return StatusCode::FAILURE;
434 }
435 std::string efName = cl->GetName();
436
437 ATH_MSG_DEBUG("finishWriting");
438
439 model->AddField( ROOT::RFieldBase::Create( "EventFormat", efName ).Unwrap());
440
441 // Loop over output meta data object managers and create the corresponding fields for the output model
442
443 // Make sure that any dynamic auxiliary variables that
444 // were added to the object after it was put into the event,
445 // get added to the output
446
447 // Must copy m_outputMetaObjects because it may be augmented in putAux
448 std::vector<std::pair<std::string, TVirtualManager*>> outputMetaObjects;
449 outputMetaObjects.reserve(m_outputMetaObjects.size());
450 for (const auto& [key, mgr] : m_outputMetaObjects) {
451 TVirtualManager* objMgr = dynamic_cast<TVirtualManager*>(mgr.get());
452 if (objMgr == nullptr) {
453 ATH_MSG_FATAL("Internal logic error detected");
454 return StatusCode::FAILURE;
455 }
456
457 ATH_MSG_DEBUG("finishWriting: save metadata key " << key);
458
459 outputMetaObjects.emplace_back(key, objMgr);
460 }
461
462 // Set up the saving of all the dynamic auxiliary properties
463 // of the object if it has any:
464 for( auto& itr : outputMetaObjects ) {
465 static constexpr bool IS_METADATA = true;
466 ATH_CHECK( putAux( *(itr.second), IS_METADATA ) );
467 }
468
469 // Now create fields for each output metadata object
470 for (auto &[key, mgr] : m_outputMetaObjects) {
471
472 // Get field name and class name to create a RFieldBase
473 std::string fieldName;
474 std::string className;
475 if (getInfoForFieldCreation( key, *mgr, fieldName, className ).isFailure()) return StatusCode::FAILURE;
476
477 // should have found class name
478 if ( className.empty() ) {
479 ATH_MSG_ERROR( "could not find className!" );
480 return StatusCode::FAILURE;
481 }
482
483 // Add RFieldBase to model
484 model->AddField( ROOT::RFieldBase::Create( fieldName, className ).Unwrap());
485
486 }
487
488 // Create RNTuple write for meta data with model
489 auto metaDataWriter = ROOT::RNTupleWriter::Append(std::move(model), outRNTupleName, *m_outputFile);
490
491
492 // Get entry for writing
493 auto rnEntry = metaDataWriter->GetModel().CreateBareEntry();
494
495 // Now loop over all object managers and bind the output object pointers
496 // to the those in the output metadata RNTuple
497 for (auto &[key, mgr] : m_outputMetaObjects) {
498
499 // Get field name from the key
500 auto fieldName = getFieldNameFromKey(key);
501
502 // Save value, if exist, otherwise save default value
503 if (mgr.get()) {
504 rnEntry->BindRawPtr(fieldName, mgr->object());
505 } else {
506 rnEntry->EmplaceNewValue(fieldName);
507 }
508 }
509
510 // Add EventFormat to the RNEntry
511 rnEntry->BindRawPtr( "EventFormat", m_outputEventFormat );
512
513 // Write the entry, and check the return value:
514 const ::Int_t ret = metaDataWriter->Fill(*rnEntry);
515 if( ret <= 0 ) {
516 ATH_MSG_FATAL( "Output rntuple filling failed with return value: " << ret );
517 }
518 else {
519 ATH_MSG_INFO( "Output meta data rntuple filled. nbytes = " << ret );
520 }
521
522 // Now clean up:
523
524 // reset output EventFormat
526 m_outputObjects.clear();
527 m_outputMetaObjects.clear();
528
529 rnEntry.reset();
530
532 m_eventWriter.reset();
533
534 metaDataWriter.reset();
535
536 // Return gracefully:
537 return StatusCode::SUCCESS;
538} // finishWriting
539
540
543::Long64_t REvent::getEntries() const {
544
545 if (m_eventReader) {
546 return m_eventReader->GetNEntries();
547 } else if (m_inputNTupleIsMissing) {
548 return 0u;
549 } else {
550 ATH_MSG_ERROR("Function called on an uninitialised object");
551 return 0u;
552 }
553}
554
569::Int_t REvent::getEntry(::Long64_t entry, ::Int_t getall) {
570
571 // A little sanity check:
572 if (!m_eventReader) {
573 ATH_MSG_ERROR("Function called on an uninitialised object");
574 return -1;
575 }
576
577 // Check if anything needs to be done.
578 if (entry == m_entry) {
579 ATH_MSG_DEBUG("Entry " << entry << " is already the active one");
580 return 0;
581 }
582
583 // Set entry value
584 m_entry = entry;
585
586 // Stats counter needs to know it's the next event.
588
589 // Loop over all input object managers, and force them to load their
590 // content. But only if getall was used.
591 ::Int_t result = 0;
592 if (getall) {
593 for (auto& [key, inObj] : m_inputObjects) {
594 result += inObj->getEntry(getall);
595 }
596 }
597
598 // Notify the listeners that a new event was loaded.
599 const TIncident incident(IncidentType::BeginEvent);
600 for (TVirtualIncidentListener* listener : m_listeners) {
601 listener->handle(incident);
602 }
603
604 // Return the number of bytes read.
605 return result;
606}
607
608bool REvent::hasInput() const {
609
611}
612
613bool REvent::hasOutput() const {
614 return (m_outputFile != nullptr);
615}
616
623::Int_t REvent::fill() {
624
625 // Make sure that all objects have been read in. The 99 as the value
626 // has a special meaning for RAuxStore. With this value it doesn't
627 // delete its transient (decoration) variables. Otherwise it does.
628 // (As it's supposed to, when moving to a new event.)
629 if( m_eventReader ) {
630 if (getEntry( m_entry, 99 ) < 0) {
631 ATH_MSG_ERROR( "getEntry failed!" );
632 return 0;
633 }
634 }
635
636 // Prepare the objects for writing. Note that we need to iterate over a
637 // copy of the m_outputObjects container. Since the putAux(...) function
638 // called inside the loop may itself add elements to the m_outputObject
639 // container.
640 std::string unsetObjects;
641 std::vector<std::pair<std::string, TVirtualManager*>> outputObjectsCopy;
642 outputObjectsCopy.reserve(m_outputObjects.size());
643 for (const auto& [key, mgr] : m_outputObjects) {
644 TVirtualManager* objMgr = dynamic_cast<TVirtualManager*>(mgr.get());
645 if (objMgr == nullptr) {
646 ATH_MSG_ERROR("Internal logic error detected");
647 return 0;
648 }
649 outputObjectsCopy.emplace_back(key, objMgr);
650 }
651 for (auto &[key, mgr] : outputObjectsCopy) {
652
653 ATH_MSG_DEBUG("REvent::fill - checking and adding aux for " << key << ", " << mgr << " isSet " << mgr->isSet());
654
655 // Check that a new object was provided in the event - skip dynamic variables:
656 if ((key.find("AuxDyn") == std::string::npos) && !mgr->isSet()) {
657
658 ATH_MSG_DEBUG("REvent::fill - not set " << key);
659
660 // We are now going to fail. But let's collect the names of
661 // all the unset objects:
662 if (unsetObjects.size()) {
663 unsetObjects += ", ";
664 }
665 unsetObjects.append("\"" + key + "\"");
666 continue;
667 }
668
669 // Make sure that any dynamic auxiliary variables that
670 // were added to the object after it was put into the event
671 // are also added to the output.
672 if( putAux( *mgr ).isFailure() ) {
673 ATH_MSG_ERROR( "Failed to put dynamic auxiliary variables in the output for object \"" << key << "\"" );
674 return 0;
675 }
676 }
677
678 // Check if there were any unset objects:
679 if (unsetObjects.size()) {
680 ATH_MSG_ERROR("The following objects were not set in the current event: "
681 << unsetObjects);
682 return 0;
683 }
684
685 // For the first call to fill, we create an RNTupleWriter with the RNTuple model already accumulated
686 // - there may be extensions for Aux containers which are empty for the first few events
687 ATH_MSG_DEBUG( "REvent::fill - has event writer " << (m_eventWriter.get() != nullptr) );
688
689 if( m_eventWriter.get() == nullptr ) {
690
691 // Set output RNTuple name as model description
692 const char* rnTupleName = EVENT_RNTUPLE_NAME;
693
694 // Create RNTuple write with model
695 m_eventWriter = ROOT::RNTupleWriter::Append(std::move(m_model), rnTupleName, *m_outputFile);
696
697 // Reset the RNTupleModel so that subsequent additions of new fields will be done with model extensions
698 m_model.reset();
699
700 ATH_MSG_DEBUG( "REvent::fill - created writer and reset model " );
701
702 }
703
704 // Get entry for writing
705 auto rnEntry = m_eventWriter->GetModel().CreateBareEntry();
706
707 // Now loop over all object managers and bind the output object pointers
708 // to the those in the output RNTuple
709 ::Int_t nbytes = 0;
710 for (auto &[key, mgr] : m_outputObjects) {
711
712 // Get field name from the key
713 auto fieldName = getFieldNameFromKey(key);
714
715 // Check if this is a container, top-level or aux, rather than a aux variable (AuxDyn):
716 ROutObjManager* omgr = dynamic_cast< ROutObjManager* >( mgr.get() );
717 bool isContainer = (omgr != nullptr);
718
719 ATH_MSG_DEBUG("REvent::fill - bind ptr " << key << " mgr " << mgr << " is set " << mgr->isSet()
720 << ", is container " << isContainer);
721
722 // Save value, if an object has been set, otherwise save default value
723 // Dynamic attributes don't exist for empty containers, e.g. no electrons in an event
724 if (mgr->isSet()) {
725 rnEntry->BindRawPtr(fieldName, mgr->object());
726 } else {
727
728 ATH_MSG_DEBUG("REvent::fill - bind unSet ptr " << key << " mgr " << mgr << " is set " << mgr->isSet()
729 << ", is container " << isContainer);
730
731 rnEntry->EmplaceNewValue(fieldName);
732 }
733 }
734
735 ATH_MSG_DEBUG("REvent::fill - writer fill ");
736
737 // Write the entry, and check the return value:
738 const ::Int_t ret = m_eventWriter->Fill(*rnEntry);
739 if( ret <= 0 ) {
740 ATH_MSG_ERROR( "Output RNTuple filling failed with return value: " << ret );
741 }
742 nbytes += ret;
743
744 ATH_MSG_DEBUG("REvent::fill - writer filled ");
745
746 // Reset the object managers:
747 for (auto &[key, mgr] : m_outputObjects) {
748 mgr->reset();
749
750 ATH_MSG_DEBUG("REvent::fill - after reset " << key << " is set " << mgr->isSet());
751
752 }
753
754 // Return the number of bytes written:
755 return nbytes;
756}
757
758
759StatusCode REvent::getNames(const std::string& targetClassName,
760 std::vector<std::string>& vkeys,
761 bool metadata) const {
762
763 // The results go in here
764 std::set<std::string> keys;
765
766 // Get list of fields from
767 // the input metadata tree or input tree
768
769 ROOT::RNTupleReader* reader = (metadata) ? m_metaReader.get() : m_eventReader.get();
770 if (reader == nullptr) {
771 ATH_MSG_ERROR("No input file is connected");
772 return StatusCode::FAILURE;
773 }
774 if (metadata) ATH_MSG_DEBUG("scanning input objects for metadata for type name " << targetClassName);
775 else ATH_MSG_DEBUG("scanning input objects for event data for type name " << targetClassName);
776
777 // add in names for all top level fields
778 for (const auto &topLevelField : reader->GetDescriptor().GetTopLevelFields()) {
779 std::string objClassName = topLevelField.GetTypeName();
780 std::string key = topLevelField.GetFieldName();
781 if (objClassName == targetClassName) {
782 ATH_MSG_VERBOSE("Matched " << targetClassName << " to key " << key);
783 keys.insert(std::move(key));
784 }
785 }
786
787 // check output objects
788 if (m_eventWriter && !metadata){
789 ATH_MSG_DEBUG("scanning output objects for type name " << targetClassName);
790 // add in names for all top level fields
791 for (const auto& topLevelFieldName : m_eventWriter->GetModel().GetRegisteredSubfieldNames()) {
792 auto& topLevelField = m_eventWriter->GetModel().GetConstField(topLevelFieldName);
793 std::string objClassName = topLevelField.GetTypeName();
794 std::string key = topLevelField.GetFieldName();
795 ATH_MSG_VERBOSE("Inspecting " << objClassName << "/" << key);
796 if (objClassName == targetClassName) {
797 ATH_MSG_VERBOSE("Matched " << targetClassName << " to key " << key);
798 keys.insert(std::move(key));
799 }
800 }
801 }
802
803 const Object_t& outAux = ( metadata ?
805
806 // Search though EventFormat for entries where class matches the provided
807 // typeName
808
809 ATH_MSG_DEBUG("scanning output Aux objects for type name " << targetClassName);
810
811 for( const auto& object : outAux ) {
812 // All metadata objects should be held by ROutObjManager objects.
813 // Anything else is an error.
814 std::string objClassName;
815 if ( metadata ) {
816 ROutObjManager* mgr = dynamic_cast< ROutObjManager* >( object.second.get() );
817 if ( ! mgr ) continue;
818 objClassName = mgr->holder()->getClass()->GetName();
819 }
820 const std::string& key = object.first;
821 ATH_MSG_VERBOSE("Inspecting " << objClassName << "/" << key);
822 if (objClassName == targetClassName) {
823 ATH_MSG_VERBOSE("Matched " << targetClassName << " to key " << key);
824 keys.insert(std::move(key));
825 }
826 }
827
828 vkeys.insert(vkeys.end(), keys.begin(), keys.end());
829
830 return StatusCode::SUCCESS;
831}
832
850StatusCode REvent::connectObject(const std::string& key, ::Bool_t silent) {
851
852 // A little sanity check.
853 if (!m_eventReader) {
854 ATH_MSG_ERROR("Function called on un-initialised object");
855 return StatusCode::FAILURE;
856 }
857
858 // Increment the access counter on this container.
860
861 // Check if the branch is already connected.
862 if (m_inputObjects.contains(key)) {
863 return StatusCode::SUCCESS;
864 }
865 // Check if it was already found to be missing.
866 if (m_inputMissingObjects.contains(key)) {
867 if (!silent) {
868 ATH_MSG_WARNING("Field \"" << key << "\" not available on input");
869 }
870 return StatusCode::RECOVERABLE;
871 }
872
873 // Tell the user what's happening.
874 ATH_MSG_DEBUG("Connecting to field \"" << key << "\"");
875
876 // Check if we have metadata about this branch.
877 const xAOD::EventFormatElement* ef = nullptr;
878
879 // Find the name of the field that stores the object.
880 const std::string fieldName =
881 Utils::getFieldName(m_eventReader->GetDescriptor(), key);
882
883 if (m_inputEventFormat.exists(key) == false) {
884 if (!silent) {
885 ATH_MSG_WARNING("No metadata available for object: " << key);
886 }
887 } else {
888 ef = m_inputEventFormat.get(key);
889 }
890
891 // Check if the field exists in our input RNTuple.
892 if (m_eventReader->GetDescriptor().FindFieldId(fieldName.c_str()) ==
893 ROOT::kInvalidDescriptorId) {
894 // Field doesn't exist
895 if (!silent) {
896 ATH_MSG_WARNING("Field \"" << fieldName << "\" not available on input");
897 }
898 m_inputMissingObjects.insert(key);
899 return StatusCode::RECOVERABLE;
900 }
901
902 // RDS: may need some logic here to get type from inputEventFormat rather than
903 // the view to read in with automatic schema evolution
904
905 // Get class name from the field
906 ROOT::RNTupleView<void> view =
907 m_eventReader->GetView<void>(fieldName.c_str(), nullptr);
908 std::string className = view.GetField().GetTypeName();
909 if (className == "") {
910 if (ef) {
911 // This is a fairly weird situation, but let's fall back to taking
912 // the class name from the metadata object in this case.
913 className = ef->className();
914 } else {
916 "Couldn't find an appropriate type with a dictionary for field \""
917 << fieldName << "\"");
918 return StatusCode::FAILURE;
919 }
920 }
921 ::TClass* realClass = ::TClass::GetClass(className.c_str());
922 if (((!realClass) || (!realClass->IsLoaded())) && ef) {
923 // We may need to do an actual schema evolution here, in which
924 // case let's fall back on the class name coming from the metadata
925 // object.
926 className = ef->className();
927 realClass = ::TClass::GetClass(className.c_str());
928 }
929 if ((!realClass) || (!realClass->IsLoaded())) {
930 // Now we're in trouble...
932 "Couldn't find an appropriate type with a dictionary for field \""
933 << fieldName << "\"");
934 return StatusCode::FAILURE;
935 }
936
937 // Make sure that the current object is the "active event":
938#ifndef XAOD_STANDALONE
939 SG::CurrentEventStore::Push save (SG::CurrentEventStore::store());
940#endif
941 setActive();
942
943 // Check if the output already has this object. If it does, let's
944 // assume that we have been copying the object to the output. Which
945 // means that we need to resume filling the same memory address that
946 // the output holder points to.
947 void* ptr = nullptr;
948
949 // Handle the case where an output object with this key already exists.
950 Object_t::const_iterator out_itr = m_outputObjects.find( key );
951 if( out_itr != m_outputObjects.end() ) {
952 // It needs to be an object manager...
953 RObjectManager* mgr =
954 dynamic_cast< RObjectManager* >( out_itr->second.get() );
955 if( ! mgr ) {
956 ATH_MSG_ERROR("Couldn't access output manager for: " << key );
957 return StatusCode::FAILURE;
958 }
959 // Get the pointer out of it:
960 ptr = mgr->holder()->get();
961 }
962
963 // If there is no output object, then let's create one ourselves.
964 // This is the only way in which we can have the memory management of
965 // THolder do the right thing with this object.
966 if (ptr == nullptr) {
967 ptr = realClass->New();
968 }
969
970 // Create the new manager object that will hold this EDM object.
971 auto mgr = std::make_unique<RObjectManager>(
972 m_eventReader->GetView(fieldName, ptr, className), m_entry,
973 std::make_unique<THolder>(ptr, realClass));
974 RObjectManager* mgrPtr = mgr.get();
975 m_inputObjects[key] = std::move(mgr);
976
977 // If it's an auxiliary store object, set it up correctly.
978 if (Details::isAuxStore(*(mgrPtr->holder()->getClass()))) {
980 }
981
982 // If it (probably) has an associated auxiliary store, set it up as well.
983 if (Details::hasAuxStore(*(mgrPtr->holder()->getClass()))) {
985 key + "Aux.", Details::isStandalone(*(mgrPtr->holder()->getClass()))));
986 }
987
988 // Return gracefully.
989 return StatusCode::SUCCESS;
990} // connectObject
991
1000StatusCode REvent::connectMetaObject(const std::string& key, bool silent) {
1001
1002 // A little sanity check.
1003 if (!m_metaReader) {
1004 ATH_MSG_ERROR("Function called on un-initialised object");
1005 return StatusCode::FAILURE;
1006 }
1007
1008 // Check if the branch is already connected.
1009 if (m_inputMetaObjects.contains(key)) {
1010 return StatusCode::SUCCESS;
1011 }
1012
1013 // Find the name of the field that stores the object.
1014 const std::string fieldName =
1015 Utils::getFieldName(m_metaReader->GetDescriptor(), key);
1016
1017 // Check if the field exists in our input RNTuple.
1018 if (m_metaReader->GetDescriptor().FindFieldId(fieldName.c_str()) ==
1019 ROOT::kInvalidDescriptorId) {
1020 // Field doesn't exist
1021 if (!silent) {
1022 ATH_MSG_WARNING("Field \"" << fieldName << "\" not available on input");
1023 }
1024 return StatusCode::RECOVERABLE;
1025 }
1026
1027 // RDS: may need some logic here to get type from inputEventFormat rather than
1028 // the view to read in with automatic schema evolution
1029
1030 // Get class name from the field
1031 ROOT::RNTupleView<void> view =
1032 m_metaReader->GetView<void>(fieldName.c_str(), nullptr);
1033 std::string className = view.GetField().GetTypeName();
1034 if (className == "") {
1036 "Couldn't find an appropriate type with a dictionary for field \""
1037 << fieldName << "\"");
1038 return StatusCode::FAILURE;
1039 }
1040 ::TClass* realClass = ::TClass::GetClass(className.c_str());
1041 if ((!realClass) || (!realClass->IsLoaded())) {
1042 // Now we're in trouble...
1044 "Couldn't find an appropriate type with a dictionary for field \""
1045 << fieldName << "\"");
1046 return StatusCode::FAILURE;
1047 }
1048
1049 // Create the object and the manager(s) around it.
1050 void* ptr = realClass->New();
1051 static const ::Long64_t FIRST_ENTRY = 0;
1052 auto mgr = std::make_unique<RObjectManager>(
1053 m_metaReader->GetView(fieldName, ptr, className), FIRST_ENTRY,
1054 std::make_unique<THolder>(ptr, realClass));
1055 // For metadata, we must read in the first entry - entry number already set by FIRST_ENTRY in constructor
1056 mgr->getEntry();
1057 RObjectManager* mgrPtr = mgr.get();
1058 m_inputMetaObjects[key] = std::move(mgr);
1059
1060 // If it's an auxiliary store object, set it up correctly.
1061 if (Details::isAuxStore(*(mgrPtr->holder()->getClass()))) {
1062 // For reading in of the dynamic variables for metadata
1064 }
1065
1066 // If it (probably) has an associated auxiliary store, set it up as well.
1067 if (Details::hasAuxStore(*(mgrPtr->holder()->getClass()))) {
1069 key + "Aux.", Details::isStandalone(*(mgrPtr->holder()->getClass()))));
1070 static constexpr bool METADATA = true;
1071 ATH_CHECK(setAuxStore(key, *mgrPtr, METADATA));
1072 }
1073
1074 // Return gracefully.
1075 return StatusCode::SUCCESS;
1076} // connectMetaObject
1077
1087StatusCode REvent::connectAux(const std::string& prefix, ::Bool_t standalone) {
1088
1089 // A little sanity check.
1090 if (!m_eventReader) {
1091 ATH_MSG_ERROR("Function called on un-initialised object");
1092 return StatusCode::FAILURE;
1093 }
1094
1095 // Check if the field is already connected.
1096 if (m_inputObjects.contains(prefix)) {
1097 return StatusCode::SUCCESS;
1098 }
1099
1100 // Connect to the field as we would for any other.
1101 static constexpr bool SILENT = false;
1102 ATH_CHECK(connectObject(prefix, SILENT));
1103
1104 // Access the object's manager.
1105 Object_t::const_iterator mgr_itr = m_inputObjects.find(prefix);
1106 if (mgr_itr == m_inputObjects.end()) {
1107 ATH_MSG_FATAL("There's a logic error in the code");
1108 return StatusCode::FAILURE;
1109 }
1110 const Details::IObjectManager* omgr =
1111 dynamic_cast<const RObjectManager*>(mgr_itr->second.get());
1112 if (omgr == nullptr) {
1113 ATH_MSG_FATAL("There's a logic error in the code");
1114 return StatusCode::FAILURE;
1115 }
1116
1117 // Check if we can switch out the internal store of this object.
1118 static const TClass* const holderClass = TClass::GetClass(typeid(SG::IAuxStoreHolder));
1119 if (omgr->holder()->getClass()->InheritsFrom(holderClass) == false) {
1120 // Nope... So let's just end the journey here.
1121 return StatusCode::SUCCESS;
1122 }
1123
1124 // Try to get the object as an IAuxStoreHolder.
1125 SG::IAuxStoreHolder* storeHolder = reinterpret_cast<SG::IAuxStoreHolder*>(
1126 omgr->holder()->getAs(typeid(SG::IAuxStoreHolder)));
1127 if (!storeHolder) {
1128 ATH_MSG_FATAL("There's a logic error in the code");
1129 return StatusCode::FAILURE;
1130 }
1131
1132 // A sanity check to see whether the store's type is in sync with the
1133 // object's type that it will be connected to:
1134 if ((standalone &&
1136 ((!standalone) && (storeHolder->getStoreType() !=
1138 ATH_MSG_ERROR("Requested store types inconsistent for: " << prefix);
1139 ATH_MSG_ERROR("standalone = "
1140 << standalone << ", getStoreType() = "
1141 << static_cast<int>(storeHolder->getStoreType()));
1142 return StatusCode::FAILURE;
1143 }
1144
1145 // Return gracefully.
1146 return StatusCode::SUCCESS;
1147}
1148
1157StatusCode REvent::connectMetaAux(const std::string& prefix,
1158 ::Bool_t standalone) {
1159
1160 // A little sanity check.
1161 if (!m_metaReader) {
1162 ATH_MSG_ERROR("Function called on un-initialised object");
1163 return StatusCode::FAILURE;
1164 }
1165
1166 // Check if the field is already connected.
1167 if (m_inputMetaObjects.contains(prefix)) {
1168 return StatusCode::SUCCESS;
1169 }
1170
1171 // Connect to the field as we would for any other.
1172 static constexpr bool SILENT = false;
1173 ATH_CHECK(connectMetaObject(prefix, SILENT));
1174
1175 // Access the object's manager.
1176 Object_t::const_iterator mgr_itr = m_inputMetaObjects.find(prefix);
1177 if (mgr_itr == m_inputMetaObjects.end()) {
1178 ATH_MSG_FATAL("There's a logic error in the code");
1179 return StatusCode::FAILURE;
1180 }
1181 const Details::IObjectManager* omgr =
1182 dynamic_cast<const RObjectManager*>(mgr_itr->second.get());
1183 if (omgr == nullptr) {
1184 ATH_MSG_FATAL("There's a logic error in the code");
1185 return StatusCode::FAILURE;
1186 }
1187
1188 // Check if we can switch out the internal store of this object.
1189 static const TClass* const holderClass =
1190 TClass::GetClass(typeid(SG::IAuxStoreHolder));
1191 if (omgr->holder()->getClass()->InheritsFrom(holderClass) == false) {
1192 // Nope... So let's just end the journey here.
1193 return StatusCode::SUCCESS;
1194 }
1195
1196 // Try to get the object as an IAuxStoreHolder.
1197 SG::IAuxStoreHolder* storeHolder = reinterpret_cast<SG::IAuxStoreHolder*>(
1198 omgr->holder()->getAs(typeid(SG::IAuxStoreHolder)));
1199 if (!storeHolder) {
1200 ATH_MSG_FATAL("There's a logic error in the code");
1201 return StatusCode::FAILURE;
1202 }
1203
1204 // A sanity check to see whether the store's type is in sync with the
1205 // object's type that it will be connected to:
1206 if ((standalone &&
1208 ((!standalone) && (storeHolder->getStoreType() !=
1210 ATH_MSG_ERROR("Requested store types inconsistent for: " << prefix);
1211 ATH_MSG_ERROR("standalone = "
1212 << standalone << ", getStoreType() = "
1213 << static_cast<int>(storeHolder->getStoreType()));
1214 return StatusCode::FAILURE;
1215 }
1216
1217 // Return gracefully.
1218 return StatusCode::SUCCESS;
1219}
1220
1232StatusCode REvent::setAuxStore(const std::string& key,
1233 Details::IObjectManager& mgr, bool metadata) {
1234
1235 // Check if we need to do anything:
1236 if ((Details::hasAuxStore(*(mgr.holder()->getClass())) == false) &&
1237 (Details::isAuxStore(*(mgr.holder()->getClass())) == false)) {
1238 return StatusCode::SUCCESS;
1239 }
1240
1241 // Select which object container to use:
1242 Object_t& objects = (metadata ? m_inputMetaObjects : m_inputObjects);
1243
1244 // Look up the auxiliary object's manager:
1245 TVirtualManager* auxMgr = nullptr;
1246 std::string auxKey;
1247 if (Details::isAuxStore(*(mgr.holder()->getClass()))) {
1248 auxMgr = &mgr;
1249 auxKey = key;
1250 } else {
1251 auto itr = objects.find(key + "Aux.");
1252 if (itr == objects.end()) {
1253 // Apparently there's no auxiliary object for this DV, so let's
1254 // give up.
1255 return StatusCode::SUCCESS;
1256 }
1257 auxMgr = itr->second.get();
1258 auxKey = key + "Aux:";
1259 }
1260
1261 // Get the aux store object.
1262 RObjectManager* omgr = dynamic_cast<RObjectManager*>(auxMgr);
1263 if (!omgr) {
1264 ATH_MSG_FATAL("Auxiliary manager for \"" << auxKey
1265 << "\" is not of the right type");
1266 return StatusCode::FAILURE;
1267 }
1268 void* p = omgr->holder()->getAs(typeid(SG::IAuxStore));
1269 SG::IAuxStore* store = reinterpret_cast<SG::IAuxStore*>(p);
1270 if (store == nullptr) {
1271 ATH_MSG_FATAL("There's a logic error in the code");
1272 return StatusCode::FAILURE;
1273 }
1274
1275 if (!metadata) {
1276 // Make sure the auxiliary object is up to date.
1277 ::Int_t readBytes = auxMgr->getEntry();
1278
1279 // Check if there is a separate auxiliary object for the dynamic
1280 // variables, which would need to be updated.
1281 const std::string dynAuxKey = auxKey + "Dynamic";
1282 auto dynAuxMgr = objects.find(dynAuxKey);
1283 if ((dynAuxMgr != objects.end()) && (readBytes || (auxMgr == &mgr))) {
1284
1285 // Tell the dynamic store object to switch to a new entry.
1286 dynAuxMgr->second->getEntry();
1287 }
1288
1289#ifndef XAOD_STANDALONE
1290 // Call toTransient on the aux store.
1291 store->toTransient (this->currentContext());
1292#endif
1293 }
1294
1295 // Stop here if we've set up an auxiliary store.
1296 if (auxMgr == &mgr) {
1297 return StatusCode::SUCCESS;
1298 }
1299
1300 // Access the auxiliary base class of the object/vector:
1302 SG::AuxElement* aux = 0;
1303 switch (mgr.holder()->typeKind()) {
1304 case THolder::DATAVECTOR: {
1305 void* vvec = mgr.holder()->getAs(typeid(SG::AuxVectorBase));
1306 vec = reinterpret_cast<SG::AuxVectorBase*>(vvec);
1307 } break;
1308 case THolder::AUXELEMENT: {
1309 void* vaux = mgr.holder()->getAs(typeid(SG::AuxElement));
1310 aux = reinterpret_cast<SG::AuxElement*>(vaux);
1311 } break;
1312 default:
1313 break;
1314 }
1315
1316 // Check whether index tracking is enabled for the type. If not, then
1317 // we need to fix it...
1318 if (vec && (!vec->trackIndices())) {
1319 Details::forceTrackIndices(*vec);
1320 }
1321
1322 // Check if we were successful:
1323 if ((!vec) && (!aux)) {
1324 ATH_MSG_FATAL("Couldn't access class \""
1325 << mgr.holder()->getClass()->GetName()
1326 << "\" as SG::AuxVectorBase or SG::AuxElement");
1327 return StatusCode::FAILURE;
1328 }
1329
1330 // Connect with the aux store.
1331 if (vec) {
1332 vec->setStore(store);
1333 } else if (aux) {
1334 aux->setStore(store);
1335 } else {
1336 ATH_MSG_FATAL("There's a logic error in the code");
1337 return StatusCode::FAILURE;
1338 }
1339
1340 // We succeeded:
1341 return StatusCode::SUCCESS;
1342}
1343
1344
1361StatusCode REvent::record( void* obj,
1362 const std::string& typeName,
1363 const std::string& key,
1364 bool overwrite,
1365 bool metadata,
1366 bool isOwner ) {
1367
1368
1369 // Check if we have an output file when writing an event:
1370 if ( !hasOutput() ) {
1371 ATH_MSG_FATAL("No output output file defined. Did you forget to call writeTo(...)?" );
1372 return StatusCode::FAILURE;
1373 }
1374 assert( m_outputEventFormat != 0 );
1375
1376 ATH_MSG_DEBUG("REvent::record - key, type " << key << ", " << typeName);
1377
1378
1379 // If this is metadata, just take ownership of it. The object will only
1380 // be recorded into the output file when calling finishWriting(...).
1381 if( metadata ) {
1382 // Check whether we already have such an object:
1383 if( ( ! overwrite ) &&
1384 ( m_outputMetaObjects.find( key ) !=
1385 m_outputMetaObjects.end() ) ) {
1386 ATH_MSG_FATAL("Meta-object " << typeName << "/" << key << " already recorded" );
1387 return StatusCode::FAILURE;
1388 }
1389 // Check if we have a dictionary for this object:
1390 TClass* cl = TClass::GetClass( typeName.c_str() );
1391 if( ! cl ) {
1392 ATH_MSG_ERROR( "Didn't find dictionary for type: " << typeName );
1393 return StatusCode::FAILURE;
1394 }
1395 // Create output object manager with a holder for the object:
1396 auto outmgr = std::make_unique<ROutObjManager>( key, std::make_unique<THolder>(obj, cl, isOwner));
1397 m_outputMetaObjects[key] = std::move(outmgr);
1398 // We're done. The rest will be done later on.
1399 return StatusCode::SUCCESS;
1400 }
1401
1402 // Check if we accessed this object on the input. If yes, then this
1403 // key may not be used for recording.
1404 if( ( ! overwrite ) &&
1405 ( m_inputObjects.find( key ) != m_inputObjects.end() ) ) {
1406 ATH_MSG_FATAL( "Object " << typeName << "/" << key <<
1407 " already accessed from the input, can't be overwritten in memory" );
1408 return StatusCode::FAILURE;
1409 }
1410
1411 // Check if we need to add it to the event record:
1412 Object_t::iterator vitr = m_outputObjects.find( key );
1413 if( vitr == m_outputObjects.end() ) {
1414
1415 // Check if we have a dictionary for this object:
1416 TClass* cl = TClass::GetClass( typeName.c_str() );
1417 if( ! cl ) {
1418 ATH_MSG_ERROR( "Didn't find dictionary for type: " << typeName );
1419 return StatusCode::FAILURE;
1420 }
1421 // Check if this is a new object "type" or not:
1422 if( ! m_outputEventFormat->exists( key ) ) {
1423 m_outputEventFormat->add( EventFormatElement( key, cl->GetName(),
1424 "", getHash( key ) ) );
1425 }
1426 // Create output object manager with a holder for the object:
1427 auto outmgr = std::make_unique<ROutObjManager>( key, std::make_unique<THolder>(obj, cl, isOwner));
1428 ROutObjManager* outmgrPtr = outmgr.get();
1429 m_outputObjects[ key ] = std::move(outmgr);
1430
1431 ATH_MSG_DEBUG("REvent::record - save outObjMgr for key, type " << key << ", " << typeName);
1432
1433 // Set up the saving of all the dynamic auxiliary properties
1434 // of the object if it has any:
1435 ATH_CHECK( putAux( *outmgrPtr ) );
1436
1438 ATH_CHECK( addField(key, *outmgrPtr) );
1439
1440 // Return at this point, as we don't want to run the rest of
1441 // the function's code:
1442 return StatusCode::SUCCESS;
1443 }
1444
1445 // Access the object manager:
1446 ROutObjManager* omgr = dynamic_cast< ROutObjManager* >( vitr->second.get() );
1447 if( ! omgr ) {
1448 ATH_MSG_FATAL( "Manager object of the wrong type encountered" );
1449 return StatusCode::FAILURE;
1450 }
1451
1452 // RDS: Is the following still needed?
1453 // // Check that the type of the object matches that of the previous
1454 // // object:
1455 // if( typeName != omgr->holder()->getClass()->GetName() ) {
1456 // // This may still be, when the ROOT dictionary name differs from the
1457 // // "simple type name" known to C++. So let's get the ROOT name of the
1458 // // new type:
1459 // TClass* cl = TClass::GetClass( typeName.c_str() );
1460 // if( ( ! cl ) || ::strcmp( cl->GetName(),
1461 // omgr->holder()->getClass()->GetName() ) ) {
1462 // ATH_MSG_FATAL(
1463 // XAOD_MESSAGE( "For output key \"%s\" the previous type "
1464 // "was \"%s\", the newly requested type is "
1465 // "\"%s\"" ),
1466 // key.c_str(), omgr->holder()->getClass()->GetName(),
1467 // typeName.c_str() );
1468 // return StatusCode::FAILURE;
1469 // }
1470 // }
1471
1472 // Replace the managed object:
1473 omgr->setObject( obj );
1474
1475 // Replace the auxiliary objects:
1476 return putAux( *omgr );
1477} // record
1478
1479StatusCode REvent::recordAux(TVirtualManager& mgr, const std::string& key,
1480 bool metadata) {
1481
1482 // Check if the auxiliary store is a generic object.
1483 Details::IObjectManager* iomgr = dynamic_cast<Details::IObjectManager*>(&mgr);
1484 if (iomgr != nullptr) {
1485 // Record the auxiliary object using the main record function.
1486 static const bool OVERWRITE = true;
1487 static const bool IS_OWNER = true;
1488 ATH_CHECK(record(iomgr->object(), iomgr->holder()->getClass()->GetName(),
1489 key, OVERWRITE, metadata, IS_OWNER));
1490 return StatusCode::SUCCESS;
1491 }
1492
1493 // Apparently we didn't recorgnize the auxiliary store type.
1494 ATH_MSG_ERROR("Unknown auxiliary store manager type encountered");
1495 return StatusCode::FAILURE;
1496}
1497
1498
1516StatusCode REvent::putAux( TVirtualManager& vmgr, ::Bool_t metadata ) {
1517
1518 // A little sanity check:
1519 assert( m_outputEventFormat != 0 );
1520
1521 // Do the conversion:
1522 ROutObjManager* mgr = dynamic_cast< ROutObjManager* >( &vmgr );
1523
1524 ATH_MSG_DEBUG("REvent::putAux - vmgr " << mgr);
1525
1526 if( ! mgr ) {
1527 // It's not an error any more when we don't get a ROutObjManager.
1528 return StatusCode::SUCCESS;
1529 }
1530
1531 // Check if this class has an auxiliary store, if not nothing needs to be done:
1532 if( ! mgr->holder()->getClass()->InheritsFrom( "SG::IAuxStoreIO" ) ) {
1533
1534 ATH_MSG_DEBUG("REvent::putAux - no Aux store ");
1535
1536 return StatusCode::SUCCESS;
1537 }
1538
1539 // Get a pointer to the auxiliary store I/O interface:
1540 SG::IAuxStoreIO* aux = reinterpret_cast< SG::IAuxStoreIO* >(mgr->holder()->getAs( typeid( SG::IAuxStoreIO ) ) );
1541 if( ! aux ) {
1542 ATH_MSG_FATAL( "There is a logic error in the code!" );
1543 }
1544
1545 // Check if we have rules defined for which auxiliary properties
1546 // to write out:
1548 if( ! metadata ) {
1549 auto item_itr = m_auxItemList.find( mgr->key() );
1550 if( item_itr != m_auxItemList.end() ) {
1551 sel.selectAux( item_itr->second );
1552 }
1553 }
1554
1555 // Get the dynamic auxiliary variables held by this object, which
1556 // were selected to be written:
1557 const SG::auxid_set_t auxids = sel.getSelectedAuxIDs (aux->getSelectedAuxIDs());
1558
1559 // Decide what should be the prefix of all the dynamic branches:
1560 const std::string dynNamePrefix = Utils::dynBranchPrefix( mgr->key() );
1561
1562 ATH_MSG_DEBUG("REvent::putAux - dynNamePrefix " << dynNamePrefix);
1563
1564
1565 // Select which container to add the variables to:
1566 Object_t& objects = ( metadata ? m_outputMetaObjects : m_outputObjects );
1567
1568 // RDS: is the following needed in an RNTuple?
1569 // This iteration will determine the ordering of branches within
1570 // the tree, so sort auxids by name.
1572 typedef std::pair< std::string, SG::auxid_t > AuxVarSort_t;
1573 std::vector< AuxVarSort_t > varsort;
1574 varsort.reserve( auxids.size() );
1575 for( SG::auxid_t id : auxids ) {
1576 varsort.emplace_back( r.getName( id ), id );
1577 }
1578 std::sort( varsort.begin(), varsort.end() );
1579
1580 // Extract all the dynamic variables from the object:
1581 for( const auto& p : varsort ) {
1582
1583 // The auxiliary ID:
1584 const SG::auxid_t id = p.second;
1585
1586 // Construct a dynamic key name for the field that we will write:
1587 const std::string dynKey = dynNamePrefix + p.first;
1588
1589 ATH_MSG_DEBUG("REvent::putAux - id, dynKey " << id << ", " << dynKey);
1590
1591
1592 // Try to find the object manager:
1593 Object_t::iterator bmgr = objects.find( dynKey );
1594
1595 // Check if we already know about this variable:
1596 if( bmgr == objects.end() ) {
1597 // Construct the full type name of the variable:
1598 const std::type_info* brType = aux->getIOType( id );
1599 if( ! brType ) {
1600 ATH_MSG_FATAL( "No I/O type found for variable " << dynKey );
1601 return StatusCode::FAILURE;
1602 }
1603 const std::string brTypeName = Utils::getTypeName( *brType );
1604 std::string brProperTypeName = "<unknown>";
1605
1606 // Check if it's a primitive type or not:
1607 bool isPrimitive = false;
1608 TVirtualManager* outmgrPtr = nullptr;
1609
1610 if( strlen( brType->name() ) == 1 ) {
1611 isPrimitive = true;
1612
1613 ATH_MSG_DEBUG("REvent::putAux - primitive " << id << ", " << brTypeName << " brType name " << brType->name());
1614
1615
1616 // Making the "proper" type name is simple in this case:
1617 brProperTypeName = std::move(brTypeName);
1618
1619 // Let's create an RAuxFieldManager for this property:
1620 static constexpr bool IS_OWNER = false;
1621 auto auxmgr = std::make_unique<RAuxFieldManager>(
1622 std::make_unique<THolder>(aux->getIOData( id ), *brType, IS_OWNER), isPrimitive );
1623 outmgrPtr = auxmgr.get();
1624
1625 objects[ dynKey ] = std::move(auxmgr);
1626
1627 } else {
1628
1629 ATH_MSG_DEBUG("REvent::putAux - not primitive " << id << ", " << brTypeName);
1630
1631 // Check if we have a dictionary for this type:
1632 TClass* cl = TClass::GetClass( *brType, kTRUE, kTRUE );
1633 if( ! cl ) {
1634 // The dictionary needs to be loaded now. This could be an
1635 // issue. But let's hope for the best...
1636 cl = TClass::GetClass( brTypeName.c_str() );
1637 // If still not found...
1638 if( ! cl ) {
1639 ATH_MSG_FATAL( "Dictionary not available for variable \"" << dynKey
1640 << "\" of type \"" << brTypeName << "\"" );
1641 return StatusCode::FAILURE;
1642 }
1643 }
1644
1645 // The proper type name comes from the dictionary in this case:
1646 brProperTypeName = cl->GetName();
1647
1648 // Let's create an RAuxFieldManager for this property - not a primitive:
1649 static constexpr bool IS_OWNER = false;
1650 auto auxmgr = std::make_unique<RAuxFieldManager>(
1651 std::make_unique<THolder>(aux->getIOData( id ), cl, IS_OWNER), isPrimitive );
1652 outmgrPtr = auxmgr.get();
1653 objects[ dynKey ] = std::move(auxmgr);
1654 }
1655
1656 // For event data, add in the the new fields to the RNTuple model and event format metadata
1657 if (!metadata) {
1658
1660 ATH_CHECK( addField(dynKey, *outmgrPtr) );
1661
1662 // If all went fine, let's add this branch to the event format
1663 // metadata (but not for regular metadata):
1664 if( ! m_outputEventFormat->exists( dynKey ) ) {
1666 EventFormatElement( dynKey,
1667 brProperTypeName,
1668 mgr->key(),
1669 getHash( dynKey ) ) );
1670 }
1671 }
1672
1673 // We don't need to do the rest:
1674 continue;
1675 }
1676
1677 ATH_MSG_DEBUG("REvent::putAux - setObj " << dynKey);
1678
1679 // Access the object manager:
1680 bmgr = objects.find( dynKey );
1681 if( bmgr == objects.end() ) {
1682 ATH_MSG_FATAL( "There is an internal logic error in the code..." );
1683 }
1684 // Replace the managed object:
1685 void* nc_data ATLAS_THREAD_SAFE = // we hold non-const pointers but check on retrieve
1686 const_cast< void* >( static_cast< const void* >( aux->getIOData( id ) ) );
1687 bmgr->second->setObject( nc_data );
1688 }
1689
1690 // Return gracefully:
1691 return StatusCode::SUCCESS;
1692}
1693
1694
1696StatusCode REvent::addField(const std::string& key, const TVirtualManager& mgr) {
1697
1698 // Add to the RNTuple model -
1699 // This is done by either adding the field to the initial model before the first event is written, or
1700 // after the first event has been written a new field is added via an extension of the output RNTuple model.
1701 // This can occurs when an AuxStore is empty for the initial events
1702
1703 // Get field name and class name to create a RFieldBase
1704 std::string fieldName;
1705 std::string className;
1706 if (getInfoForFieldCreation( key, mgr, fieldName, className ).isFailure()) return StatusCode::FAILURE;
1707 // should have found class name
1708 if ( className.empty() ) {
1709 ATH_MSG_ERROR( "could not find className!" );
1710 return StatusCode::FAILURE;
1711 }
1712
1713 if (m_model) {
1714 // Continue to add to the initial RNTuple model
1715 m_model->AddField( ROOT::RFieldBase::Create( fieldName, className ).Unwrap());
1716 }
1717 else {
1718 if (m_eventWriter.get() == nullptr) {
1719 ATH_MSG_ERROR("Internal logic error detected - no output found");
1720 return StatusCode::FAILURE;
1721 }
1722 // After the first event, one needs to extend the output RNTuple model
1723 auto field = ROOT::RFieldBase::Create(fieldName, className).Unwrap();
1724 auto updater = m_eventWriter->CreateModelUpdater();
1725 updater->BeginUpdate();
1726 updater->AddField(std::move(field));
1727 updater->CommitUpdate();
1728 }
1729
1730 // Return gracefully:
1731 return StatusCode::SUCCESS;
1732
1733}
1734
1735
1742StatusCode REvent::initStats() {
1743
1744 // A little sanity check.
1745 if (!m_eventReader) {
1746 ATH_MSG_ERROR("Function called on an uninitialised object");
1747 return StatusCode::FAILURE;
1748 }
1749
1750 // Reset the number of input branches information.
1752
1753 // Loop over the EventFormat information.
1754 for (const auto& [key, format] : m_inputEventFormat) {
1755
1756 ATH_MSG_DEBUG("Investigating object \"" << key << "\" of class \""
1757 << format.className() << "\"");
1758
1759 // If it's an auxiliary container, scan it using RAuxStore.
1760 if (key.ends_with("Aux.")) {
1761
1762 // But first decide whether it describes a container, or just
1763 // a single object. For that, first get the class that it was
1764 // written with.
1765 TClass* cl = TClass::GetClass(format.className().c_str());
1766 if ((cl == nullptr) || (cl->IsLoaded() == false)) {
1768 "Couldn't find the dictionary for type: " << format.className());
1769 continue;
1770 }
1771
1772 // And then check if it inherits from xAOD::AuxInfoBase.
1773 // If so, consider this standalone, otherwise a container.
1774 static TClass* const auxInfoCl = TClass::GetClass(
1776 if (auxInfoCl == nullptr) {
1777 ATH_MSG_ERROR("Couldn't get dictionary for xAOD::AuxInfoBase");
1778 return StatusCode::FAILURE;
1779 }
1780 const bool isInfo = cl->InheritsFrom(auxInfoCl);
1781 ATH_MSG_VERBOSE("isInfo = {}", isInfo);
1782
1783 // Scan the branches using a temporary RAuxStore instance.
1784 const std::string fieldName =
1785 Utils::getFieldName(m_eventReader->GetDescriptor(), key);
1786 const RAuxStore::EStructMode mode =
1789 static constexpr bool TOP_STORE = true;
1790 RAuxStore temp(this->currentContext(), fieldName, TOP_STORE, mode);
1792
1793 // Add all the auxids to the statistics object:
1794 ReadStats& stats = IOStats::instance().stats();
1795 for (SG::auxid_t id : temp.getAuxIDs()) {
1796 stats.branch(fieldName, id);
1797 }
1798
1799 // Increment the number of known branches.
1800 stats.setBranchNum(stats.branchNum() + temp.getAuxIDs().size());
1801 }
1802 // If it's an interface container.
1803 else {
1804 // Check if it's part of the input ntuple.
1805 const ROOT::RNTupleDescriptor& descriptor =
1806 m_eventReader->GetDescriptor();
1807 if (descriptor.FindFieldId(Utils::getFieldName(descriptor, key)) !=
1808 ROOT::kInvalidDescriptorId) {
1810 }
1811 }
1812 }
1813
1814 // Return gracefully:
1815 return StatusCode::SUCCESS;
1816}
1817
1827 ROOT::RNTupleReader& reader) {
1828
1829 // The name of the field that the object is connected to.
1830 const std::string fieldName = mgr.field().GetField().GetFieldName();
1831
1832 // Check if we can call setName(...) on the object.
1833 ::TMethodCall setNameCall;
1834 setNameCall.InitWithPrototype(mgr.holder()->getClass(), "setName",
1835 "const char*");
1836 if (setNameCall.IsValid()) {
1837 // Yes, there is such a function. Let's call it with the field
1838 // name.
1839 const ::TString params = ::TString::Format("\"%s\"", fieldName.c_str());
1840 const char* charParams = params.Data();
1841 setNameCall.Execute(mgr.holder()->get(), charParams);
1842 } else {
1843 // This is weird. What sort of auxiliary container is this? :-/
1844 ATH_MSG_WARNING("Couldn't find setName(...) function for container \""
1845 << fieldName << "\" (type: "
1846 << mgr.holder()->getClass()->GetName() << ")");
1847 }
1848
1849 // Check if we can switch out the internal store of this object:
1850 static const TClass* const holderClass =
1851 TClass::GetClass(typeid(SG::IAuxStoreHolder));
1852 if (!mgr.holder()->getClass()->InheritsFrom(holderClass)) {
1853 // Nope... So let's just end the journey here.
1854 return StatusCode::SUCCESS;
1855 }
1856
1857 // Try to get the object as an IAuxStoreHolder:
1858 SG::IAuxStoreHolder* storeHolder = reinterpret_cast<SG::IAuxStoreHolder*>(
1859 mgr.holder()->getAs(typeid(SG::IAuxStoreHolder)));
1860 if (!storeHolder) {
1861 ATH_MSG_FATAL("There's a logic error in the code");
1862 return StatusCode::FAILURE;
1863 }
1864
1865 // Create an RAuxStore instance that will read the dynamic variables
1866 // of this container. Notice that the RAuxManager doesn't own the
1867 // RAuxStore object. It will be owned by the SG::IAuxStoreHolder
1868 // object.
1869 static constexpr bool TOP_STORE = false;
1870 const EventContext& ctx = this->currentContext();
1871 auto store = std::make_unique<RAuxStore>(
1872 ctx,
1873 fieldName, TOP_STORE,
1877 // This object is used to read data from the input, it needs to be
1878 // locked:
1879 store->lock();
1880
1881 // Set it up to read from the input RNTuple.
1882 ATH_CHECK(store->readFrom(reader));
1883 // Tell the auxiliary store which entry to use. This is essential for
1884 // metadata objects, and non-important for event data objects, which will
1885 // get a possibly different entry loaded in setAuxStore(...).
1886 ATH_CHECK(store->getEntry(0));
1887
1888 // Set up a manager for it.
1889 static constexpr bool SHARED_OWNER = false;
1890 m_inputObjects[fieldName + "Dynamic"] =
1891 std::make_unique<RAuxManager>(store.get(), m_entry, SHARED_OWNER);
1892
1893 // Give this object to the store holder.
1894 storeHolder->setStore(store.release());
1895
1896 // Return gracefully:
1897 return StatusCode::SUCCESS;
1898}
1899
1900} // namespace xAOD::Experimental
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_INFO(x,...)
#define ATH_MSG_FATAL(x,...)
Base class for elements of a container that can have aux data.
Manage index tracking and synchronization of auxiliary data.
std::vector< size_t > vec
Hold a pointer to the current event store.
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
static Double_t sc
Handle mappings between names and auxid_t.
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Manage index tracking and synchronization of auxiliary data.
Interface for objects taking part in direct ROOT I/O.
@ AST_ContainerStore
The store describes a container.
@ AST_ObjectStore
The store describes a single object.
virtual AuxStoreType getStoreType() const =0
Return the type of the store object.
virtual void setStore(IAuxStore *store)=0
Give an auxiliary store object to the holder object.
Interface providing I/O for a generic auxiliary store.
Definition IAuxStoreIO.h:44
virtual SG::auxid_set_t getSelectedAuxIDs() const
Get a list of dynamic variables that need to be written out.
Definition IAuxStoreIO.h:86
virtual const std::type_info * getIOType(SG::auxid_t auxid) const =0
Return the type of the data to be stored for one aux data item.
virtual const void * getIOData(SG::auxid_t auxid) const =0
Return a pointer to the data to be stored for one aux data item.
Interface for non-const operations on an auxiliary store.
Definition IAuxStore.h:51
A set of aux data identifiers.
Definition AuxTypes.h:47
Common base class for auxiliary info objects.
Definition AuxInfoBase.h:45
Class helping in dealing with dynamic branch selection.
Manager for EDM objects created by ROOT.
const THolder * holder() const
Accessor to the Holder object.
Class describing one branch of the ROOT file.
EventFormat m_inputEventFormat
Format of the current input file.
Definition Event.h:357
std::set< std::string > m_inputMissingObjects
Objects that have been asked for, but were found to be missing in the current input.
Definition Event.h:347
upgrade_mutex_t m_branchesMutex
Mutex for multithread synchronization.
Definition Event.h:390
std::unordered_map< std::string, std::unique_ptr< TVirtualManager > > Object_t
Definition of the internal data structure type.
Definition Event.h:340
Object_t m_inputObjects
Collection of all the managed input objects.
Definition Event.h:344
Event(std::string_view name, const EventContext *ctx=nullptr)
Constructor with a name.
Definition EventCore.cxx:29
static const char *const METADATA_OBJECT_NAME
Name of the metadata tree or RNTuple.
Definition Event.h:81
StatusCode keys(std::vector< std::string > &vkeys, bool metadata) const
Provide a list of all data object keys associated with a specific type.
void setActive() const
Set this event object as the currently active one.
Definition EventCore.cxx:65
SG::sgkey_t getHash(const std::string &key) const override
Function returning the hash describing an object name.
static const char *const EVENT_RNTUPLE_NAME
Name of the event RNTuple.
Definition Event.h:80
Object_t m_inputMetaObjects
Collection of all the managed input meta-objects.
Definition Event.h:352
std::unordered_map< std::string, std::set< std::string > > m_auxItemList
Rules for selecting which auxiliary branches to write.
Definition Event.h:362
EventFormat * m_outputEventFormat
Format of the current output file.
Definition Event.h:359
Object_t m_outputObjects
Collection of all the managed output object.
Definition Event.h:349
SG::SGKeyMap< BranchInfo > m_branches ATLAS_THREAD_SAFE
Map from hashed sgkey to BranchInfo.
Definition Event.h:394
AthContainers_detail::upgrading_lock< upgrade_mutex_t > upgrading_lock_t
Lock type for multithread synchronization.
Definition Event.h:387
const EventContext & currentContext() const
Return the event context corresponding to this event.
std::vector< TVirtualIncidentListener * > m_listeners
Listeners who should be notified when certain incidents happen.
Definition Event.h:365
Object_t m_outputMetaObjects
Collection of all the managed output meta-objects.
Definition Event.h:354
Manager for auxiliary branches created dynamically.
::Bool_t isPrimitive() const
Accessor to whether the field is a primitive type, e.g. int, float, bool.
StatusCode finishWritingTo(TFile &file) override
Finish writing to an output file.
Definition REvent.cxx:388
bool m_inputNTupleIsMissing
Whether the input has an event RNTuple or not.
Definition REvent.h:133
StatusCode addField(const std::string &key, const TVirtualManager &mgr)
Add field to RNTuple model given the StoreGate key and output object manager.
Definition REvent.cxx:1696
StatusCode putAux(TVirtualManager &mgr, ::Bool_t metadata=kFALSE)
Method saving the dynamically created auxiliary properties.
Definition REvent.cxx:1516
::Int_t fill() override
Method filling one event into the output.
Definition REvent.cxx:623
StatusCode setUpDynamicStore(RObjectManager &mgr, ROOT::RNTupleReader &ntupleReader)
event uses RNTupleReader:
Definition REvent.cxx:1826
std::unique_ptr< ROOT::RNTupleWriter > m_eventWriter
The main event writer: RNTupleWeader.
Definition REvent.h:144
StatusCode record(void *obj, const std::string &typeName, const std::string &key, bool overwrite, bool metadata, bool isOwner) override
Record an object into a connected output file.
Definition REvent.cxx:1361
std::unique_ptr< ROOT::RNTupleReader > m_eventReader
The main event data reader.
Definition REvent.h:131
StatusCode connectMetaAux(const std::string &prefix, bool standalone) override
Function setting up access to a set of auxiliary branches for a metadata object.
Definition REvent.cxx:1157
::Int_t getEntry(::Long64_t entry, ::Int_t getall=0) override
Function loading a given entry of the input RNTuple.
Definition REvent.cxx:569
std::unique_ptr< ROOT::RNTupleModel > m_model
The RNTuple model used for event fields.
Definition REvent.h:141
StatusCode writeTo(TFile &file) override
Connect the object to an output file.
Definition REvent.cxx:358
::TFile * m_outputFile
The output file for writing.
Definition REvent.h:147
std::unique_ptr< ROOT::RNTupleReader > m_metaReader
The metadata reader.
Definition REvent.h:135
StatusCode recordAux(TVirtualManager &mgr, const std::string &key, bool metadata) override
Record an auxiliary store into a connected output file.
Definition REvent.cxx:1479
StatusCode readFrom(TFile &inFile) override
Set up the reading of an input file from TFile This method implements the interface from Event.
Definition REvent.cxx:165
StatusCode setAuxStore(const std::string &key, Details::IObjectManager &mgr, bool metadata) override
Function connecting a DV object to its auxiliary store.
Definition REvent.cxx:1232
::Long64_t getEntries() const override
Get how many entries are available from the current input file(s).
Definition REvent.cxx:543
bool hasOutput() const override
Check if an output file is connected to the object.
Definition REvent.cxx:613
StatusCode getNames(const std::string &targetClassName, std::vector< std::string > &vkeys, bool metadata) const override
Function determining the list keys associated with a type name.
Definition REvent.cxx:759
StatusCode connectObject(const std::string &key, bool silent) override
Function setting up access to a particular object.
Definition REvent.cxx:850
::Long64_t m_entry
The entry to look at from the input.
Definition REvent.h:138
REvent(const EventContext *ctx=nullptr)
Default constructor.
Definition REvent.cxx:147
virtual ~REvent()
Destructor.
Definition REvent.cxx:151
StatusCode connectAux(const std::string &prefix, bool standalone) override
Function setting up access to a set of auxiliary branches.
Definition REvent.cxx:1087
StatusCode initStats()
Function to initialise the statistics for all RNTuple content.
Definition REvent.cxx:1742
StatusCode connectMetaObject(const std::string &key, bool silent) override
Function setting up access to a particular metadata object.
Definition REvent.cxx:1000
bool hasInput() const override
Check if an input file is connected to the object.
Definition REvent.cxx:608
Manager for EDM objects created by ROOT.
Manager for EDM objects to be written to RNTuple.
virtual void setObject(void *obj) override
Function replacing the object being handled.
ReadStats & stats()
Access the object belonging to the current thread.
Definition IOStats.cxx:17
static IOStats & instance()
Singleton object accessor.
Definition IOStats.cxx:11
"ROOT @c RNTuple implementation" of IAuxStore
Definition RAuxStore.h:41
StatusCode readFrom(ROOT::RNTupleReader &reader)
Connect the object to an input RNTuple.
Class describing the access statistics of a collection of branches.
Definition ReadStats.h:123
void nextEvent()
Function incrementing the processed event counter.
BranchStats * container(const std::string &name)
Access the description of a container. Creating it if necessary.
void setBranchNum(::Int_t num)
Set the total number of branches on the input.
void readContainer(const std::string &name)
Function incrementing the read counter on a specific container.
static const TEventFormatRegistry & instance()
Access the only instance of the object in memory.
EventFormat & getEventFormat(const TFile *file) const
Access the managed EventFormat object.
void add(std::string_view fileName)
Add information about a new file that got accessed.
static TFileAccessTracer & instance()
Access the singleton instance of this class.
const std::type_info * getTypeInfo() const
Definition THolder.cxx:412
const ::TClass * getClass() const
Definition THolder.cxx:402
virtual void * getAs(const std::type_info &tid, ::Bool_t silent=kFALSE) const
Return the object as a specific pointer.
Definition THolder.cxx:371
@ DATAVECTOR
A DataVector container.
Definition THolder.h:105
@ AUXELEMENT
A type inheriting from SG::AuxElement.
Definition THolder.h:106
Class describing a certain "incident" that is communicated to user code.
Definition TIncident.h:58
Class providing an interface for classes listening to xAOD incidents.
Interface class for the "manager classes".
virtual const void * object() const =0
Function getting a const pointer to the object being handled.
virtual::Int_t getEntry(::Int_t getall=0)=0
Function for updating the object in memory if needed.
EStructMode
"Structural" modes of the object
@ kObjectStore
The object describes a single object.
@ kContainerStore
The object describes an entire container.
virtual const SG::auxid_set_t & getAuxIDs() const override
Get the types(names) of variables handled by this container.
int r
Definition globals.cxx:22
std::string normalizedTypeinfoName(const std::type_info &info)
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
AuxElement(SG::AuxVectorData *container, size_t index)
Base class for elements of a container that can have aux data.
size_t auxid_t
Identifier for a particular aux data item.
Definition AuxTypes.h:27
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
bool hasAuxStore(const TClass &cl)
Helper function deciding if a given type "has an auxiliary store".
Definition IOUtils.cxx:40
bool isAuxStore(const TClass &cl)
Helper function deciding if a given type "is an auxiliary store".
Definition IOUtils.cxx:53
bool isStandalone(const TClass &cl)
Helper function deciding if a given type "is a standalone object".
Definition IOUtils.cxx:65
static const ::Int_t BeginEvent
A new event was just loaded.
Definition TIncident.h:29
static const ::Int_t EndInputFile
The processing of an input file has finished.
Definition TIncident.h:40
static const ::Int_t MetaDataStop
The metadata for the output file should be written out.
Definition TIncident.h:31
static const ::Int_t BeginInputFile
A new input file was just opened.
Definition TIncident.h:27
std::string dynBranchPrefix(const std::string &key)
This function is used to figure out what to name dynamic auxiliary branches coming from a container c...
std::string getFieldName(const ROOT::RNTupleDescriptor &descriptor, const std::string &key)
This function is used to find the name of the field in an RNTuple that stores the object with a given...
std::string getTypeName(const std::type_info &ti)
This function is necessary in order to create type names that ROOT can understand.
EventFormat_v1 EventFormat
Definition of the current event format version.
Definition EventFormat.h:16
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
TFile * file