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