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