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