ATLAS Offline Software
RAuxStore.cxx
Go to the documentation of this file.
1 // Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
2 
3 // Local include(s).
5 
6 #include "ROOTTypes.h"
7 #include "isRegisteredType.h"
8 #include "lookupVectorType.h"
13 
14 // Athena include(s).
18 
19 // ROOT include(s).
20 #include <TClass.h>
21 #include <TROOT.h>
22 
23 // System include(s).
24 #include <cassert>
25 #include <memory>
26 #include <string>
27 
28 namespace {
29 
39 bool isContainerField(const ROOT::RFieldDescriptor& fieldDesc,
40  SG::auxid_t auxid) {
41 
42  // For unknown types it doesn't matter if the field describes a
43  // container or a single element.
44  if (!xAOD::details::isRegisteredType(auxid)) {
45  return true;
46  }
47 
48  // If it's a primitive field, then it's not a container.
49  if (xAOD::Utils::isPrimitiveType(fieldDesc.GetTypeName())) {
50  return false;
51  }
52 
53  // For non-primitive types, get the dictionary of the type.
54  TClass* cl = TClass::GetClass(fieldDesc.GetTypeName().c_str());
55 
56  // If there is no class associated with the field then it should be
57  // a field describing a standalone object. (As it should be a
58  // "primitive" field in this case.)
59  if (!cl) {
60  ::Warning("::isPContainerField",
61  XAOD_MESSAGE("Couldn't get a dictionary for type \"%s\""),
62  fieldDesc.GetTypeName().c_str());
63  return false;
64  }
65 
66  // If there is a class, ask for the type_info of its type:
67  const std::type_info* root_ti = cl->GetTypeInfo();
68  if (!root_ti) {
69  // This may be an emulated class. One known case is when the type name
70  // is saved as "basic_string<char>" rather than "string" by Athena I/O.
71  // (It's not fully understood why this happens for dynamic branches...)
72  // So, let's see if we can get a functional TClass by massaging the
73  // type name a bit.
74  ::TString typeName(cl->GetName());
75  typeName.ReplaceAll("basic_string<char>", "string");
76  ::TClass* newCl = ::TClass::GetClass(typeName);
77  if (newCl) {
78  root_ti = newCl->GetTypeInfo();
79  }
80  }
81  if (!root_ti) {
82  ::Error("::isContainerField",
83  XAOD_MESSAGE("Couldn't get an std::type_info object out of "
84  "type \"%s\""),
85  cl->GetName());
86  return false;
87  }
88 
89  // Ask for the auxiliary type infos:
90  const std::type_info* aux_obj_ti =
92  if (!aux_obj_ti) {
93  ::Error("::isContainerField",
94  XAOD_MESSAGE("Couldn't get std::type_info object for "
95  "auxiliary id: %i"),
96  static_cast<int>(auxid));
97  return false;
98  }
99  const std::type_info* aux_vec_ti =
101  if (!aux_vec_ti) {
102  ::Error("::isContainerField",
103  XAOD_MESSAGE("Couldn't get std::type_info object for "
104  "auxiliary id: %i"),
105  static_cast<int>(auxid));
106  return false;
107  }
108 
109  // Check which one the ROOT type info agrees with:
110  if (*root_ti == *aux_obj_ti) {
111  // This branch describes a single object:
112  return false;
113  } else if (*root_ti == *aux_vec_ti) {
114  // This branch describes a container of objects:
115  return true;
116  }
117 
118  // For enum and vector<enum> types (PFO...) the type given by
119  // the aux type registry is vector<int>. We have to take it into account
120  // here...
121  if (cl->GetCollectionProxy() && (*aux_vec_ti == typeid(std::vector<int>))) {
122  return true;
123  }
124 
125  TClass* cl2 = xAOD::details::lookupVectorType(*cl);
126  if (cl2) {
127  if (*cl2->GetTypeInfo() == *aux_vec_ti) {
128  return true;
129  }
130  }
131 
132  // If we got this far, the branch may have undergone schema evolution. If
133  // it's one that ROOT can deal with itself, then we should still be able
134  // to read the branch with this code.
135  //
136  // Note that even after looking at the ROOT source code, I'm still not
137  // 100% sure whether we would need to delete the objects returned by
138  // TClass::GetConversionStreamerInfo(...) in this code. :-( But based on
139  // general experience with the ROOT code, I'm going to say no...
140  TClass* aux_vec_cl =
141  TClass::GetClass(xAOD::Utils::getTypeName(*aux_vec_ti).c_str());
142  if (aux_vec_cl &&
143  aux_vec_cl->GetConversionStreamerInfo(cl, cl->GetClassVersion())) {
144  return true;
145  }
146  TClass* aux_obj_cl =
147  TClass::GetClass(xAOD::Utils::getTypeName(*aux_obj_ti).c_str());
148  if (aux_obj_cl &&
149  aux_obj_cl->GetConversionStreamerInfo(cl, cl->GetClassVersion())) {
150  return false;
151  }
152 
153  // If neither, then something went wrong...
154  ::Error("::isContainerField",
155  XAOD_MESSAGE("Couldn't determine if field describes a single "
156  "object or a container"));
157  ::Error("::isContainerField", XAOD_MESSAGE("ROOT type : %s"),
158  xAOD::Utils::getTypeName(*root_ti).c_str());
159  ::Error("::isContainerField", XAOD_MESSAGE("Object type: %s"),
160  xAOD::Utils::getTypeName(*aux_obj_ti).c_str());
161  ::Error("::isContainerField", XAOD_MESSAGE("Vector type: %s"),
162  xAOD::Utils::getTypeName(*aux_vec_ti).c_str());
163  return kFALSE;
164 }
165 
167 class RFieldHandle {
168 
169  public:
171  RFieldHandle(ROOT::RNTupleView<void> field, SG::auxid_t auxid,
172  std::string_view prefix, void* object, const std::type_info* ti)
173  : m_field(std::move(field)),
174  m_auxid(auxid),
175  m_prefix(prefix),
176  m_object(object),
177  m_typeInfo(ti) {}
178 
180  StatusCode getEntry(::Long64_t entry) {
181 
182  // Check if anything needs to be done:
183  if ((m_entry == entry) && (!m_needsRead)) {
184  return StatusCode::SUCCESS;
185  }
186 
187  try {
188  // Load the entry
189  m_field(entry);
190  } catch (const ROOT::RException& e) {
191  ::Error("::RFieldInfo::getEntry",
192  "Failed to load entry %lld for field %s.%s: %s", entry,
193  m_prefix.data(),
194  SG::AuxTypeRegistry::instance().getName(m_auxid).c_str(),
195  e.what());
196  return StatusCode::FAILURE;
197  }
198 
199  // Remember what entry was loaded for this field.
200  m_entry = entry;
201  m_needsRead = false;
202  return StatusCode::SUCCESS;
203  }
204 
211  void* objectPtr() { return m_object; }
212 
214  const std::type_info* typeInfo() const { return m_typeInfo; }
215 
217  void reset() { m_needsRead = true; }
218 
219  private:
221  ROOT::RNTupleView<void> m_field;
223  SG::auxid_t m_auxid;
225  std::string_view m_prefix;
227  void* m_object = nullptr;
229  const std::type_info* m_typeInfo = nullptr;
231  ::Long64_t m_entry = -1;
233  bool m_needsRead = true;
234 
235 }; // class RFieldInfo
236 
237 bool fieldExists(std::string_view fieldName,
238  ROOT::RNTupleReader& ntupleReader) {
239  // If it cannot find a field id it will give the maximum value of
240  // unsigned long
241  return (ntupleReader.GetDescriptor().FindFieldId(fieldName) !=
243 }
244 
245 } // namespace
246 
247 namespace xAOD {
248 
250 
259 
260  // Check if an input ntuple is even available.
261  if (!m_inTuple) {
262  // It's not an error if it isn't.
263  return StatusCode::SUCCESS;
264  }
265 
266  // Check if the input was already scanned.
267  if (m_inputScanned) {
268  return StatusCode::SUCCESS;
269  }
270 
271  // Iterate over all fields of the input ntuple.
272  for (const ROOT::RFieldBase* field :
273 #if ROOT_VERSION_CODE >= ROOT_VERSION(6, 35, 0)
274  m_inTuple->GetModel().GetConstFieldZero().GetConstSubfields()
275 #else
276  m_inTuple->GetModel().GetConstFieldZero().GetSubFields()
277 #endif // ROOT_VERSION_CODE >= ROOT_VERSION(6, 35, 0)
278  ) {
279 
280  // Get the name of the current field.
281  const std::string fieldName = field->GetQualifiedFieldName();
282 
283  // Look for static fields.
284  if (m_data.m_topStore && (fieldName == m_data.m_prefix)) {
285 
286  // Loop over the sub-fields of this field.
287  for (const ROOT::RFieldBase* subField :
288 #if ROOT_VERSION_CODE >= ROOT_VERSION(6, 35, 0)
289  field->GetConstSubfields()
290 #else
291  field->GetSubFields()
292 #endif // ROOT_VERSION_CODE >= ROOT_VERSION(6, 35, 0)
293  ) {
294 
295  // Get the type of this sub-field.
296  const std::string& typeName = subField->GetTypeName();
297 
298  // Skip this entry if it refers to a base class.
299  if (typeName.starts_with("xAOD::") ||
300  typeName.starts_with("SG::") ||
301  typeName.starts_with("DMTest::") ||
302  typeName.starts_with("ILockable")) {
303  continue;
304  }
305 
306  // Set up this field.
307  RETURN_CHECK("xAOD::RAuxStore::impl::scanInputNtuple",
308  setupAuxField(*subField, subField->GetFieldName()));
309  }
310  // Don't check the rest of the loop's body:
311  continue;
312  }
313 
314  // if fieldname doesnt start with the value of m_dynPrefix, skip
315  if (fieldName.starts_with(m_data.m_dynPrefix) == false) {
316  continue;
317  }
318  if (fieldName == m_data.m_dynPrefix) {
319  ::Error("xAOD::RAuxStore::impl::scanInputNtuple",
320  "Dynamic field with empty name found on container: %s",
321  m_data.m_prefix.c_str());
322  continue;
323  }
324  // The auxiliary property name:
325  std::string_view auxName = fieldName;
326  auxName = auxName.substr(auxName.find(':') + 1);
327  // Leave the rest up to the function that is shared with the
328  // dynamic fields:
329  RETURN_CHECK("xAOD::RAuxStore::scanInputNtuple",
330  setupAuxField(*field, auxName));
331  }
332 
333  // the input was successfully scanned:
334  m_inputScanned = true;
335  return StatusCode::SUCCESS;
336  }
337 
347  const std::type_info* auxFieldType(const ROOT::RFieldBase& field,
348  std::string* expectedClassName = nullptr) {
349 
350  // Get the type name of the field. Not worrying about automatic schema
351  // evolution for now.
352  const std::string typeName = field.GetTypeName();
353  ::TClass* expectedClass = ::TClass::GetClass(typeName.c_str());
354  if (expectedClassName) {
355  if (expectedClass) {
356  *expectedClassName = expectedClass->GetName();
357  } else {
358  *expectedClassName = typeName;
359  }
360  }
361 
362  // If this is a primitive variable, and we're still not sure whether this
363  // is a store for an object or a container, the answer is given...
367  }
368 
369  // Get the type_info of the branch.
370  const std::type_info* ti = nullptr;
372  if (expectedClass) {
373  ti = expectedClass->GetTypeInfo();
374  } else {
375  ti = &(Utils::getTypeInfo(typeName));
376  }
377  } else {
378  if (!expectedClass) {
379  ::Warning("xAOD::RAuxStore::impl::auxFieldType",
380  "Couldn't get the type of field \"%s\"",
381  field.GetFieldName().c_str());
382  } else {
383  ::TVirtualCollectionProxy* prox = expectedClass->GetCollectionProxy();
384 
385  if (!prox) {
386  TClass* cl2 = details::lookupVectorType(*expectedClass);
387  if (cl2) {
388  prox = cl2->GetCollectionProxy();
389  }
390  }
391 
392  if (!prox) {
393  ::Warning("xAOD::RAuxStore::impl::auxFieldType",
394  "Couldn't get the type of field \"%s\"",
395  field.GetFieldName().c_str());
396  } else {
397  if (prox->GetValueClass()) {
398  ti = prox->GetValueClass()->GetTypeInfo();
399  } else {
400  ti = &(Utils::getTypeInfo(prox->GetType()));
401  }
402  }
403  }
404  }
405 
406  return ti;
407  }
408 
421  StatusCode setupAuxField(const ROOT::RFieldBase& field,
422  std::string_view auxName) {
423 
424  // Get the (on disk) type of the field.
425  std::string expectedClassName;
426  const std::type_info* ti = auxFieldType(field, &expectedClassName);
427  if (ti == nullptr) {
428  // If we didn't find a type_info for the field, give up now...
429  return StatusCode::SUCCESS;
430  }
431 
432  // Get the registry:
434 
435  // Check if the registry already knows this variable name. If yes, let's
436  // use the type known by the registry. To be able to deal with simple
437  // schema evolution in dynamic fields.
438  const std::string auxNameStr{auxName};//Get rid of this if everything is migrated to string_view
439  if (const SG::auxid_t regAuxid = registry.findAuxID(auxNameStr);
440  regAuxid != SG::null_auxid) {
441  m_data.m_auxIDs.insert(regAuxid);
442  return StatusCode::SUCCESS;
443  }
444 
446  SG::auxid_t linkedAuxId = SG::null_auxid;
447 
448  if (SG::AuxTypeRegistry::isLinkedName(auxNameStr)) {
450  } else if (SG::AuxTypeRegistry::classNameHasLink(expectedClassName)) {
451  const std::string linkedAttr =
453  const std::string linkedFieldName =
454  SG::AuxTypeRegistry::linkedName(field.GetFieldName());
455  const std::type_info* linkedTi = nullptr;
456  if (::fieldExists(linkedFieldName, *m_inTuple)) {
457  linkedTi =
458  auxFieldType(m_inTuple->GetModel().GetConstField(linkedFieldName));
459  }
460  if (linkedTi) {
461  linkedAuxId = registry.getAuxID(
462  *linkedTi, linkedAttr, "",
464  }
465  if (linkedAuxId == SG::null_auxid) {
466  ::Error("xAOD::RAuxStore::setupAuxField",
467  "Could not find linked variable for %s type %s", auxName.data(),
468  expectedClassName.c_str());
469  }
470  }
471 
472  // Check for an auxiliary ID for this field:
473  SG::auxid_t auxid =
474  registry.getAuxID(*ti, auxNameStr, "", flags, linkedAuxId);
475 
476  // First try to find a compiled factory for the vector type:
477  if (auxid == SG::null_auxid) {
478 
479  // Construct the name of the factory's class:
480  // But be careful --- if we don't exactly match the name
481  // in TClassTable, then we may trigger autoparsing. Besides the
482  // resource usage that implies, that can lead to crashes in dbg
483  // builds due to cling bugs.
484  std::string typeName = Utils::getTypeName(*ti);
485  if (typeName.starts_with("std::vector<"))
486  typeName.erase(0, 5);
487  std::string factoryClassName =
488  "SG::AuxTypeVectorFactory<" + typeName + ",allocator<" + typeName;
489  if (factoryClassName[factoryClassName.size() - 1] == '>') {
490  factoryClassName += ' ';
491  }
492  factoryClassName += "> >";
493 
494  // Look for the dictionary of this type:
495  ::TClass* factoryClass = TClass::GetClass(factoryClassName.c_str());
496  if (factoryClass && factoryClass->IsLoaded()) {
497  ::TClass* baseClass = ::TClass::GetClass("SG::IAuxTypeVectorFactory");
498  if (baseClass && baseClass->IsLoaded()) {
499  const Int_t offset = factoryClass->GetBaseClassOffset(baseClass);
500  if (offset >= 0) {
501  void* factoryVoidPointer = factoryClass->New();
502  if (factoryVoidPointer) {
503  unsigned long tmp =
504  reinterpret_cast<unsigned long>(factoryVoidPointer) + offset;
505  SG::IAuxTypeVectorFactory* factory =
506  reinterpret_cast<SG::IAuxTypeVectorFactory*>(tmp);
507  registry.addFactory(
508  *ti, *factory->tiAlloc(),
509  std::unique_ptr<SG::IAuxTypeVectorFactory>(factory));
510  auxid = registry.getAuxID(*ti, auxNameStr, "", flags,
511  linkedAuxId);
512  }
513  }
514  }
515  }
516  }
517 
518  // If that didn't succeed, let's assign a generic factory to this type:
519  if (auxid == SG::null_auxid && linkedAuxId == SG::null_auxid) {
520  // Construct the name of the vector type:
521  std::string vectorClassName = "std::vector<" + Utils::getTypeName(*ti);
522  if (vectorClassName[vectorClassName.size() - 1] == '>') {
523  vectorClassName += ' ';
524  }
525  vectorClassName += '>';
526 
527  // Get the dictionary for the type:
528  ::TClass* vectorClass = ::TClass::GetClass(vectorClassName.c_str());
529  if (vectorClass && vectorClass->IsLoaded()) {
530  auto factory = std::make_unique<TAuxVectorFactory>(vectorClass);
531  if (factory->tiAlloc()) {
532  const std::type_info* tiAlloc = factory->tiAlloc();
533  registry.addFactory(*ti, *tiAlloc, std::move(factory));
534  } else {
535  std::string tiAllocName = factory->tiAllocName();
536  registry.addFactory(*ti, tiAllocName, std::move(factory));
537  }
538  auxid = registry.getAuxID(*ti, auxNameStr, "",
540  } else {
541  ::Warning("xAOD::RAuxStore::setupAuxField",
542  "Couldn't find dictionary for type: %s",
543  vectorClassName.c_str());
544  }
545  }
546 
547  // Check if we succeeded:
548  if (auxid == SG::null_auxid) {
549  if (linkedAuxId != SG::null_auxid) {
550  ::Error("xAOD::RAuxStore::setupAuxField",
551  XAOD_MESSAGE("Dynamic ROOT vector factory not implemented for "
552  "linked types; field \"%s\""),
553  field.GetFieldName().c_str());
554  } else {
555  ::Error("xAOD::RAuxStore::setupAuxField",
556  XAOD_MESSAGE("Couldn't assign auxiliary ID to field \"%s\""),
557  field.GetFieldName().c_str());
558  }
559  return StatusCode::FAILURE;
560  }
561 
562  // Remember the auxiliary ID:
563  m_data.m_auxIDs.insert(auxid);
564  return StatusCode::SUCCESS;
565  }
566 
569 
571  ROOT::RNTupleReader* m_inTuple = nullptr;
573  ROOT::RNTupleWriter* m_outTuple = nullptr;
574 
576  bool m_inputScanned = false;
577 
579  ::Long64_t m_entry;
580 
582  std::vector<std::unique_ptr<RFieldHandle> > m_fields;
584  std::vector<bool> m_fieldsWritten;
586  std::vector<bool> m_missingFields;
587 
589  mutable mutex_t m_mutex;
590 
591 }; // struct RAuxStore::impl
592 
593 RAuxStore::RAuxStore(std::string_view prefix, bool topStore, EStructMode mode)
594  : details::AuxStoreBase(topStore, mode),
595  m_impl{std::make_unique<impl>(m_data)} {
596 
597  setPrefix(prefix);
598 }
599 
600 RAuxStore::~RAuxStore() = default;
601 
602 void RAuxStore::setPrefix(std::string_view prefix) {
603 
606  reset();
607 }
608 
616 StatusCode RAuxStore::readFrom(ROOT::RNTupleReader& reader) {
617 
618  assert(m_impl);
619 
620  // Make sure that everything will be re-read after this:
621  reset();
622 
623  // We will need to check again which branches are available:
624  m_impl->m_missingFields.clear();
625 
626  // Remember the tree:
627  m_impl->m_inTuple = &reader;
628 
629  // Catalogue all the branches:
630  RETURN_CHECK("xAOD::RAuxStore::readFrom", m_impl->scanInputTuple());
631 
632  // Return gracefully.
633  return StatusCode::SUCCESS;
634 }
635 
642 StatusCode RAuxStore::writeTo(ROOT::RNTupleWriter& writer) {
643 
644  assert(m_impl);
645 
646  // Look for any auxiliary fields that have not been connected to yet.
647  RETURN_CHECK("xAOD::RAuxStore::writeTo", m_impl->scanInputTuple());
648 
649  // Put the object into "output writing" mode.
650  m_impl->m_outTuple = &writer;
651 
652  // Create all the variables that we already know about. Notice that the
653  // code makes a copy of the auxid set on purpose. Because the underlying
654  // AuxSelection object gets modified while doing the for loop.
655  const SG::auxid_set_t selAuxIDs = getSelectedAuxIDs();
656  for (SG::auxid_t id : selAuxIDs) {
657  RETURN_CHECK("xAOD::RAuxStore::writeTo", setupOutputData(id));
658  }
659 
660  // Return gracefully.
661  return StatusCode::SUCCESS;
662 }
663 
664 StatusCode RAuxStore::getEntry(std::int64_t entry, int getall) {
665 
666  assert(m_impl);
667 
668  // Guard against multi-threaded execution:
669  guard_t guard(m_impl->m_mutex);
670 
671  m_impl->m_entry = entry;
672 
673  // Reset the transient store. TEvent::fill() calls this function with
674  // getall==99. When that is happening, we need to keep the transient
675  // store still around. Since the user may want to interact with the
676  // object after it was written out. (And since TEvent::fill() asks for
677  // the transient decorations after calling getEntry(...).)
678  if (m_data.m_transientStore && (getall != 99)) {
679  // Remove the transient auxiliary IDs from the internal list:
680  m_data.m_auxIDs -= m_data.m_transientStore->getAuxIDs();
681  m_data.m_decorIDs -= m_data.m_transientStore->getDecorIDs();
682  // Delete the object:
683  m_data.m_transientStore.reset();
684  }
685 
686  // Now remove the IDs of the decorations that are getting persistified:
687  if (getall != 99) {
688  for (SG::auxid_t auxid = 0; auxid < m_data.m_isDecoration.size(); ++auxid) {
689  if (!m_data.m_isDecoration[auxid]) {
690  continue;
691  }
692  m_data.m_auxIDs.erase(auxid);
693  m_data.m_decorIDs.erase(auxid);
694  }
695  }
696 
697  // If we don't need everything loaded, return now:
698  if (!getall) {
699  return StatusCode::SUCCESS;
700  }
701 
702  // Get all the variables at once:
703  for (auto& field : m_impl->m_fields) {
704  if (field) {
705  RETURN_CHECK("xAOD::RAuxStore::getEntry", field->getEntry(entry));
706  }
707  }
708 
709  // Return gracefully.
710  return StatusCode::SUCCESS;
711 }
712 
714 
715  assert(m_impl);
716 
717  // Loop through all of the output variables.
718  for (SG::auxid_t id : getSelectedAuxIDs()) {
719  // Now connect the output entry to the variable.
720  const std::string fieldName =
723  void* fieldPtr = const_cast<void*>(getIOData(id));
724  if (fieldPtr) {
725  entry.BindRawPtr(fieldName, fieldPtr);
726  } else {
727  entry.EmplaceNewValue(fieldName);
728  }
729  }
730 
731  // Return gracefully.
732  return StatusCode::SUCCESS;
733 }
734 
736 
737  assert(m_impl);
738 
739  for (auto& field : m_impl->m_fields) {
740  if (field) {
741  field->reset();
742  }
743  }
744  m_impl->m_inputScanned = false;
745 }
746 
748 
749  assert(m_impl);
750  return ((m_impl->m_fields.size() > auxid) && m_impl->m_fields[auxid]);
751 }
752 
754 
755  // Guard against multi-threaded execution:
756  guard_t guard(m_impl->m_mutex);
757 
758  assert(m_impl);
759  assert(m_impl->m_fields.size() > auxid);
760  assert(m_impl->m_fields[auxid]);
761  RETURN_CHECK("xAOD::RAuxStore::getEntryFor",
762  m_impl->m_fields[auxid]->getEntry(m_impl->m_entry));
763  return StatusCode::SUCCESS;
764 }
765 
766 bool RAuxStore::hasOutput() const {
767 
768  assert(m_impl);
769  return (m_impl->m_outTuple != nullptr);
770 }
771 
780 
781  // Return right away if we already know that the field is missing.
782  if ((auxid < m_impl->m_missingFields.size()) &&
783  m_impl->m_missingFields[auxid]) {
784  return StatusCode::RECOVERABLE;
785  }
786 
787  // We may call this function without an input being used. That's not an
788  // error either.
789  if (m_impl->m_inTuple == nullptr) {
790  return StatusCode::RECOVERABLE;
791  }
792 
793  // Make sure the internal storage is large enough:
794  if (m_data.m_vecs.size() <= auxid) {
795  m_data.m_vecs.resize(auxid + 1);
796  }
797  if (m_impl->m_fields.size() <= auxid) {
798  m_impl->m_fields.resize(auxid + 1);
799  }
800 
801  // Check if we need to do anything. Remember, output-only variables don't
802  // have an associated RFieldHandle. To tell the caller that no input is
803  // actually available for the variable (only an output), use a different
804  // return value.
805  if (m_data.m_vecs[auxid]) {
806  return (m_impl->m_fields[auxid] ? StatusCode::SUCCESS
807  : StatusCode::RECOVERABLE);
808  }
809 
810  // Convenience access to the registry.
812 
813  // Get the property name:
814  const std::string statFieldName =
815  std::format("{}{}", m_data.m_prefix, r.getName(auxid));
816  const std::string dynFieldName =
817  std::format("{}{}", m_data.m_dynPrefix, r.getName(auxid));
818 
819  // Check if the field exists:
820  std::string fieldName = statFieldName;
821  ROOT::DescriptorId_t fieldId;
822  if ((fieldId = m_impl->m_inTuple->GetDescriptor().FindFieldId(
823  statFieldName)) == std::numeric_limits<unsigned long>::max()) {
824  if ((fieldId = m_impl->m_inTuple->GetDescriptor().FindFieldId(
825  dynFieldName)) == std::numeric_limits<unsigned long>::max()) {
826  // Remember that the field is missing.
827  if (m_impl->m_missingFields.size() <= auxid) {
828  m_impl->m_missingFields.resize(auxid + 1);
829  }
830  m_impl->m_missingFields[auxid] = true;
831  // The field doesn't exist, but this is not an error per se.
832  // The user may just be calling isAvailable(...) on the variable.
833  return StatusCode::RECOVERABLE;
834  }
835  // We have a dynamic field:
836  fieldName = std::move(dynFieldName);
837  }
838 
839  // Get the object describing this field.
840  const ROOT::RFieldDescriptor& fieldDesc =
841  m_impl->m_inTuple->GetDescriptor().GetFieldDescriptor(fieldId);
842 
843  // Check if it's a "primitive field":
844  const bool primitiveField = Utils::isPrimitiveType(fieldDesc.GetTypeName());
845  // Check if it's a "container field":
846  const bool containerField =
847  (primitiveField ? false : isContainerField(fieldDesc, auxid));
848 
849  // Set the structure mode if it has not been defined externally:
853  }
854 
855  // Check that the branch type makes sense:
856  if ((containerField &&
858  !r.isLinked(auxid)) ||
859  ((!containerField) &&
861  ::Error("xAOD::RAuxStore::setupInputData",
862  XAOD_MESSAGE("Field type and requested structure mode "
863  "differ for field: %s"),
864  fieldName.c_str());
865  return StatusCode::FAILURE;
866  }
867 
868  // Get the property type:
869  const std::type_info* fieldType = nullptr;
870  if (details::isRegisteredType(auxid)) {
871  // Get the type from the auxiliary type registry:
872  fieldType = (containerField ? r.getVecType(auxid) : r.getType(auxid));
873  } else {
874  // Get the type from the input field itself:
875  TClass* clDummy = ::TClass::GetClass(fieldDesc.GetTypeName().c_str());
876  fieldType = (clDummy ? clDummy->GetTypeInfo()
877  : &(Utils::getTypeInfo(fieldDesc.GetTypeName())));
878  }
879  if (!fieldType) {
880  ::Error("xAOD::RAuxStore::setupInputData",
881  XAOD_MESSAGE("Can't read/copy variable %s (%s)"), fieldName.c_str(),
882  fieldDesc.GetTypeName().c_str());
883  return StatusCode::RECOVERABLE;
884  }
885  const TString fieldTypeName = Utils::getTypeName(*fieldType).c_str();
886 
887  // Check if we have the needed dictionary for an object field:
888  ::TClass* fieldClass = nullptr;
889  if (!primitiveField) {
890  // Get the property's class:
891  fieldClass = ::TClass::GetClass(*fieldType, true, true);
892  if (!fieldClass) {
893  fieldClass = ::TClass::GetClass(fieldTypeName);
894  }
895  if (!fieldClass) {
896  ::Error("xAOD::RAuxStore::setupInputData",
897  XAOD_MESSAGE("No dictionary available for class \"%s\""),
898  fieldTypeName.Data());
899  return StatusCode::FAILURE;
900  }
901  }
902 
903  // Create the smart object holding this vector:
904  if (details::isRegisteredType(auxid)) {
905  m_data.m_vecs[auxid] = r.makeVector(auxid, (size_t)0, (size_t)0);
906  if (!containerField) {
907  m_data.m_vecs[auxid]->resize(1);
908  }
909  if (fieldClass &&
910  strncmp(fieldClass->GetName(), "SG::PackedContainer<", 20) == 0) {
911  std::unique_ptr<SG::IAuxTypeVector> packed =
912  m_data.m_vecs[auxid]->toPacked();
913  std::swap(m_data.m_vecs[auxid], packed);
914  }
915  } else {
916  ::Error("xAOD::RAuxStore::setupInputData",
917  XAOD_MESSAGE("Couldn't create in-memory vector for "
918  "variable %s (%i)"),
919  fieldName.c_str(), static_cast<int>(auxid));
920  return StatusCode::FAILURE;
921  }
922 
923  // Access/create the field, and create a field handle object.
924  void* objectPtr = (containerField ? m_data.m_vecs[auxid]->toVector()
925  : m_data.m_vecs[auxid]->toPtr());
926  m_impl->m_fields[auxid] = std::make_unique<RFieldHandle>(
927  m_impl->m_inTuple->GetView<void>(fieldName.c_str(), objectPtr), auxid,
928  m_data.m_prefix, objectPtr, fieldType);
929 
930  // Get the current entry.
931  RETURN_CHECK("xAOD::RAuxStore::setupInputData",
932  m_impl->m_fields[auxid]->getEntry(m_impl->m_entry));
933 
934  // Remember which variable got created:
935  m_data.m_auxIDs.insert(auxid);
936 
937  // Check if we just replaced a generic object:
938  if (details::isRegisteredType(auxid)) {
939  // The name of the variable we just created:
940  const std::string auxname = r.getName(auxid);
941  // Check if there's another variable with this name already:
942  for (SG::auxid_t i = 0; i < m_data.m_vecs.size(); ++i) {
943  // Check if we have this aux ID:
944  if (!m_data.m_vecs[i]) {
945  continue;
946  }
947  // Ingore the object that we *just* created:
948  if (i == auxid) {
949  continue;
950  }
951  // The name of the variable:
952  const std::string testname = r.getName(i);
953  // Check if it has the same name:
954  if (testname != auxname) {
955  continue;
956  }
957  // Check that the other one is a non-registered type:
959  ::Error("xAOD::RAuxStore::setupInputData",
960  XAOD_MESSAGE("Internal logic error!"));
961  continue;
962  }
963  // Okay, we do need to remove this object:
964  m_data.m_vecs[i].reset();
965  m_impl->m_fields[i].reset();
967  }
968  }
969 
970  SG::auxid_t linked_auxid = r.linkedVariable(auxid);
971  if (linked_auxid != SG::null_auxid) {
972  return setupInputData(linked_auxid);
973  }
974 
975  // Return gracefully:
976  return StatusCode::SUCCESS;
977 }
978 
987 
988  assert(m_impl);
989 
990  // Check whether we need to do anything.
991  if (!m_impl->m_outTuple) {
992  return StatusCode::SUCCESS;
993  }
994 
995  // Check if the variable needs to be written out.
996  if (!isAuxIDSelected(auxid)) {
997  return StatusCode::SUCCESS;
998  }
999 
1000  // Make sure that containers are large enough:
1001  if (m_data.m_vecs.size() <= auxid) {
1002  m_data.m_vecs.resize(auxid + 1);
1003  }
1004  if (m_impl->m_fieldsWritten.size() <= auxid) {
1005  m_impl->m_fieldsWritten.resize(auxid + 1);
1006  }
1007 
1008  // Check if this auxiliary variable is already in the output:
1009  if (m_impl->m_fieldsWritten[auxid]) {
1010  return StatusCode::SUCCESS;
1011  }
1012 
1013  // After this point, we either succeed with setting up the writing of this
1014  // variable, or the code fails completely. So let's set this flag already,
1015  // as unfortunately we can recursively end up here using the code below.
1016  m_impl->m_fieldsWritten[auxid] = true;
1017 
1018  // The registry:
1020 
1021  // Check if the variable was put into the transient store as a
1022  // decoration, and now needs to be put into the output file:
1023  if ((!m_data.m_vecs[auxid]) && m_data.m_transientStore &&
1024  (m_data.m_transientStore->getAuxIDs().test(auxid))) {
1025 
1026  // Get the variable from the transient store:
1027  const void* pptr = m_data.m_transientStore->getData(auxid);
1028  if (!pptr) {
1029  ::Fatal("xAOD::RAuxStore::setupOutputData",
1030  XAOD_MESSAGE("Internal logic error detected"));
1031  return StatusCode::FAILURE;
1032  }
1033 
1034  // Create the new object:
1035  m_data.m_vecs[auxid] = reg.makeVector(auxid, m_data.m_size, m_data.m_size);
1036  void* ptr = m_data.m_vecs[auxid]->toPtr();
1037  if (!ptr) {
1038  ::Error("xAOD::RAuxStore::setupOutputData",
1039  XAOD_MESSAGE("Couldn't create decoration in memory "
1040  "for writing"));
1041  return StatusCode::FAILURE;
1042  }
1043 
1044  // Get the type of this variable:
1045  const std::type_info* type = reg.getType(auxid);
1046  if (!type) {
1047  ::Error("xAOD::RAuxStore::setupOutputData",
1048  XAOD_MESSAGE("Couldn't get the type of transient "
1049  "variable %i"),
1050  static_cast<int>(auxid));
1051  return StatusCode::FAILURE;
1052  }
1053  // Now get the factory for this variable:
1054  const SG::IAuxTypeVectorFactory* factory = reg.getFactory(auxid);
1055  if (!factory) {
1056  ::Error("xAOD::RAuxStore::setupOutputData",
1057  XAOD_MESSAGE("No factory found for transient variable "
1058  "%i"),
1059  static_cast<int>(auxid));
1060  return StatusCode::FAILURE;
1061  }
1062 
1063  // Mark it as a decoration already, otherwise the copy may fail.
1064  if (m_data.m_isDecoration.size() <= auxid) {
1065  m_data.m_isDecoration.resize(auxid + 1);
1066  }
1067  m_data.m_isDecoration[auxid] = true;
1068 
1069  // Finally, do the copy, and remove the variable from the transient store.
1070  factory->copy(auxid, SG::AuxVectorInterface(*this), 0,
1072  m_data.m_size);
1073  }
1074 
1075  // Check if we know about this variable to be on the input,
1076  // but haven't connected to it yet:
1077  if ((m_data.m_auxIDs.test(auxid)) && (!m_data.m_vecs[auxid]) &&
1078  (!m_impl->m_fields[auxid])) {
1079  RETURN_CHECK("xAOD::RAuxStore::setupOutputData", setupInputData(auxid));
1080  }
1081 
1082  // Check that we know the store's type:
1085  ::Error("xAOD::RAuxStore::setupOutputData",
1086  XAOD_MESSAGE("Structure mode unknown for variable %s"),
1087  reg.getName(auxid).c_str());
1088  return StatusCode::FAILURE;
1089  }
1090 
1091  // Check if the variable exists already in memory:
1092  if (!m_data.m_vecs[auxid]) {
1093  m_data.m_vecs[auxid] = reg.makeVector(auxid, (size_t)0, (size_t)0);
1095  m_data.m_vecs[auxid]->resize(1);
1096  }
1097  }
1098 
1099  // Figure out the type and name of the output field.
1100  const std::string fieldName =
1101  std::format("{}{}", m_data.m_dynPrefix, reg.getName(auxid));
1102  const std::string typeName = SG::normalizedTypeinfoName(
1104  ? reg.getVecType(auxid)
1105  : reg.getType(auxid)));
1106 
1107  // Update the output ntuple's model.
1108  {
1109  auto field = ROOT::RFieldBase::Create(fieldName, typeName).Unwrap();
1110  auto updater = m_impl->m_outTuple->CreateModelUpdater();
1111  updater->BeginUpdate();
1112  updater->AddField(std::move(field));
1113  updater->CommitUpdate();
1114  }
1115 
1116  // Remember that we now handle this variable.
1117  m_data.m_auxIDs.insert(auxid);
1118 
1119  // We were successful:
1120  return StatusCode::SUCCESS;
1121 }
1122 
1123 const void* RAuxStore::getInputObject(SG::auxid_t auxid) const {
1124 
1125  assert(m_impl);
1126  assert(m_impl->m_fields.size() > auxid);
1127  assert(m_impl->m_fields[auxid]);
1128  return m_impl->m_fields[auxid]->objectPtr();
1129 }
1130 
1131 const std::type_info* RAuxStore::getInputType(SG::auxid_t auxid) const {
1132 
1133  assert(m_impl);
1134  assert(m_impl->m_fields.size() > auxid);
1135  assert(m_impl->m_fields[auxid]);
1136  return m_impl->m_fields[auxid]->typeInfo();
1137 }
1138 
1139 } // namespace xAOD
SG::AuxTypeRegistry::getFactory
const IAuxTypeVectorFactory * getFactory(const std::type_info &ti, const std::type_info &ti_alloc)
Return the vector factory for a given vector element type.
Definition: AuxTypeRegistry.cxx:1111
xAOD::RAuxStore::hasOutput
virtual bool hasOutput() const override
Check if an output is being written by the object.
Definition: RAuxStore.cxx:766
xAOD::details::AuxStoreBase::prefix
const std::string & prefix() const
Get the currently configured object name prefix.
Definition: AuxStoreBase.cxx:40
xAOD::RAuxStore::impl::m_fieldsWritten
std::vector< bool > m_fieldsWritten
"Write status" of the different variables
Definition: RAuxStore.cxx:584
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
beamspotman.r
def r
Definition: beamspotman.py:672
RETURN_CHECK
#define RETURN_CHECK(CONTEXT, EXP)
Helper macro for checking return codes in a compact form in the code.
Definition: ReturnCheck.h:26
SG::AuxTypeRegistry::addFactory
const IAuxTypeVectorFactory * addFactory(const std::type_info &ti, const std::type_info &ti_alloc, std::unique_ptr< const IAuxTypeVectorFactory > factory)
Add a new type -> factory mapping.
Definition: AuxTypeRegistry.cxx:1173
xAOD::RAuxStore::impl::m_entry
::Long64_t m_entry
The entry to load from the ntuple.
Definition: RAuxStore.cxx:579
xAOD::RAuxStore::impl::setupAuxField
StatusCode setupAuxField(const ROOT::RFieldBase &field, std::string_view auxName)
This function sets up an auxiliary field by determining its type and attempting to register it with t...
Definition: RAuxStore.cxx:421
xAOD::details::lookupVectorType
TClass * lookupVectorType(TClass &cl)
Internal function used by xAOD::TAuxStore and xAOD::RAuxStore.
Definition: lookupVectorType.cxx:12
SG::SkipNameCheck
@ SkipNameCheck
Definition: AuxTypes.h:81
lookupVectorType.h
vtune_athena.format
format
Definition: vtune_athena.py:14
xAOD::details::AuxStoreBase::Members::m_vecs
std::vector< std::unique_ptr< SG::IAuxTypeVector > > m_vecs
Variables handled currently by the object (indexed by auxiliary ID)
Definition: AuxStoreBase.h:191
xAOD::RAuxStore::setPrefix
virtual void setPrefix(std::string_view prefix) override
Set the object name prefix.
Definition: RAuxStore.cxx:602
xAOD::RAuxStore::impl::m_missingFields
std::vector< bool > m_missingFields
Mark fields we've found to be missing.
Definition: RAuxStore.cxx:586
SG::AuxTypeRegistry::instance
static AuxTypeRegistry & instance()
Return the singleton registry instance.
Definition: AuxTypeRegistry.cxx:640
AuxVectorInterface.h
Make an AuxVectorData object from either a raw vector or an aux store.
SG::AuxTypeRegistry::findAuxID
SG::auxid_t findAuxID(const std::string &name, const std::string &clsname="") const
Look up a name -> auxid_t mapping.
Definition: AuxTypeRegistry.cxx:757
SG::normalizedTypeinfoName
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...
Definition: normalizedTypeinfoName.cxx:120
RAuxStore.h
AthenaPoolTestRead.flags
flags
Definition: AthenaPoolTestRead.py:8
max
constexpr double max()
Definition: ap_fixedTest.cxx:33
SG::AuxTypeRegistry::getName
std::string getName(SG::auxid_t auxid) const
Return the name of an aux data item.
Definition: AuxTypeRegistry.cxx:882
xAOD::details::AuxStoreBase::Members::m_auxIDs
SG::auxid_set_t m_auxIDs
Internal list of auxiliary variable IDs handled currently by the object.
Definition: AuxStoreBase.h:186
xAOD::details::AuxStoreBase::EStructMode
EStructMode
"Structural" modes of the object
Definition: AuxStoreBase.h:30
xAOD::RAuxStore::~RAuxStore
virtual ~RAuxStore()
Destructor.
xAOD::RAuxStore::getInputObject
virtual const void * getInputObject(SG::auxid_t auxid) const override
Get a pointer to an input object, as it is in memory, for getIOData()
Definition: RAuxStore.cxx:1123
isRegisteredType.h
xAOD::details::AuxStoreBase::guard_t
AthContainers_detail::lock_guard< mutex_t > guard_t
Guard type for multithreaded synchronisation.
Definition: AuxStoreBase.h:206
xAOD::details::AuxStoreBase::Members::m_transientStore
std::unique_ptr< SG::AuxStoreInternal > m_transientStore
Store for the in-memory-only variables.
Definition: AuxStoreBase.h:183
xAOD::RAuxStore::impl::m_outTuple
ROOT::RNTupleWriter * m_outTuple
The ntuple being written to.
Definition: RAuxStore.cxx:573
xAOD::Utils::dynFieldPrefix
std::string dynFieldPrefix(const std::string &key)
This function is used to figure out what to name dynamic auxiliary field coming from a container call...
Definition: Control/xAODRootAccess/Root/Utils.cxx:170
xAOD::RAuxStore::impl::m_mutex
mutex_t m_mutex
Mutex object used for multithreaded synchronisation.
Definition: RAuxStore.cxx:589
xAOD::details::AuxStoreBase::Members::m_size
std::size_t m_size
The current size of the container being described.
Definition: AuxStoreBase.h:193
xAOD
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
Definition: ICaloAffectedTool.h:24
xAOD::RAuxStore::impl::m_fields
std::vector< std::unique_ptr< RFieldHandle > > m_fields
Fields containing the various auxiliary variables.
Definition: RAuxStore.cxx:582
xAOD::details::isRegisteredType
bool isRegisteredType(SG::auxid_t auxid)
Check if the auxiliary variable has a registered type.
Definition: isRegisteredType.cxx:11
SG::AuxTypeRegistry::linkedName
static std::string linkedName(const std::string &name)
Given a variable name, return the name of the corresponding linked variable.
Definition: AuxTypeRegistry.cxx:1303
XAOD_MESSAGE
#define XAOD_MESSAGE(MESSAGE)
Simple macro for printing error/verbose messages.
Definition: Control/xAODRootAccess/xAODRootAccess/tools/Message.h:19
xAOD::Utils::isPrimitiveType
bool isPrimitiveType(std::string_view typeName)
Check if the type name describes a primitive type.
Definition: Control/xAODRootAccess/Root/Utils.cxx:280
xAOD::RAuxStore::getEntryFor
virtual StatusCode getEntryFor(SG::auxid_t auxid) override
Load a single variable from the input.
Definition: RAuxStore.cxx:753
ReadOfcFromCool.field
field
Definition: ReadOfcFromCool.py:48
Utils.h
dbg::ptr
void * ptr(T *p)
Definition: SGImplSvc.cxx:74
xAOD::RAuxStore::getEntry
StatusCode getEntry(std::int64_t entry, int getall=0)
Get entry from the input RNTuple.
Definition: RAuxStore.cxx:664
SG::AuxTypeRegistry::classNameHasLink
static bool classNameHasLink(const std::string &className)
Test to see if a class name corresponds to a class with a linked variable.
Definition: AuxTypeRegistry.cxx:1313
xAOD::RAuxStore::impl::m_data
Members & m_data
Variables coming from AuxStoreBase.
Definition: RAuxStore.cxx:568
xAOD::details::AuxStoreBase::EStructMode::kObjectStore
@ kObjectStore
The object describes a single object.
ReturnCheck.h
xAOD::RAuxStore::setupOutputData
virtual StatusCode setupOutputData(SG::auxid_t auxid) override
Connect a variable to the output.
Definition: RAuxStore.cxx:986
xAOD::details::AuxStoreBase::EStructMode::kContainerStore
@ kContainerStore
The object describes an entire container.
python.CaloAddPedShiftConfig.type
type
Definition: CaloAddPedShiftConfig.py:42
xAOD::RAuxStore::impl::scanInputTuple
StatusCode scanInputTuple()
Scans the input ntuple for auxiliary data fields and sets up the necessary structures to access them.
Definition: RAuxStore.cxx:258
xAOD::details::AuxStoreBase::Members::m_decorIDs
SG::auxid_set_t m_decorIDs
Internal list of auxiliary decoration IDs handled currently by the object.
Definition: AuxStoreBase.h:189
WriteCalibToCrest.swap
swap
Definition: WriteCalibToCrest.py:96
SG::IAuxTypeVectorFactory::tiAllocName
virtual std::string tiAllocName() const =0
Return the (demangled) name of the vector allocator.
SG::AuxTypeRegistry
Handle mappings between names and auxid_t.
Definition: AuxTypeRegistry.h:61
SG::Linked
@ Linked
Mark that this variable is linked to another one.
Definition: AuxTypes.h:77
xAOD::RAuxStore::impl::m_inTuple
ROOT::RNTupleReader * m_inTuple
The ntuple being read from.
Definition: RAuxStore.cxx:571
SG::auxid_t
size_t auxid_t
Identifier for a particular aux data item.
Definition: AuxTypes.h:27
SG::AuxTypeRegistry::getType
const std::type_info * getType(SG::auxid_t auxid) const
Return the type of an aux data item.
Definition: AuxTypeRegistry.cxx:909
H5Utils::internal::packed
H5::CompType packed(H5::CompType in)
Definition: common.cxx:16
xAOD::details::AuxStoreBase::m_data
Members m_data
Member variables of the base class.
Definition: AuxStoreBase.h:201
xAOD::RAuxStore::hasEntryFor
virtual bool hasEntryFor(SG::auxid_t auxid) const override
Check if a given variable is available from the input.
Definition: RAuxStore.cxx:747
details
Definition: IParticleWriter.h:21
xAOD::details::AuxStoreBase::mutex_t
AthContainers_detail::mutex mutex_t
Mutex type for multithread synchronization.
Definition: AuxStoreBase.h:204
xAOD::Utils::getTypeName
std::string getTypeName(const std::type_info &ti)
This function is necessary in order to create type names that ROOT can understand.
Definition: Control/xAODRootAccess/Root/Utils.cxx:354
lumiFormat.i
int i
Definition: lumiFormat.py:85
CxxUtils::ConcurrentBitset::insert
ConcurrentBitset & insert(bit_t bit, bit_t new_nbits=0)
Set a bit to 1.
EL::StatusCode
::StatusCode StatusCode
StatusCode definition for legacy code.
Definition: PhysicsAnalysis/D3PDTools/EventLoop/EventLoop/StatusCode.h:22
Message.h
SG::IAuxTypeVectorFactory
Interface for factory objects that create vectors.
Definition: IAuxTypeVectorFactory.h:50
SG::IAuxTypeVectorFactory::tiAlloc
virtual const std::type_info * tiAlloc() const =0
Return the type_info of the vector allocator.
taskman.fieldName
fieldName
Definition: taskman.py:489
xAOD::details::AuxStoreBase::Members::m_prefix
std::string m_prefix
Static prefix for the branch names.
Definition: AuxStoreBase.h:178
checkCorrelInHIST.prefix
dictionary prefix
Definition: checkCorrelInHIST.py:391
Preparation.mode
mode
Definition: Preparation.py:107
SG::AuxTypeRegistry::isLinkedName
static bool isLinkedName(const std::string &name)
Test if a variable name corresponds to a linked variable.
Definition: AuxTypeRegistry.cxx:1293
SG::IAuxTypeVectorFactory::copy
virtual void copy(SG::auxid_t auxid, AuxVectorData &dst, size_t dst_index, const AuxVectorData &src, size_t src_index, size_t n) const =0
Copy elements between vectors.
SG::AuxTypeRegistry::getVecType
const std::type_info * getVecType(SG::auxid_t auxid) const
Return the type of the STL vector used to hold an aux data item.
Definition: AuxTypeRegistry.cxx:937
DeMoUpdate.tmp
string tmp
Definition: DeMoUpdate.py:1167
xAOD::RAuxStore::getInputType
virtual const std::type_info * getInputType(SG::auxid_t auxid) const override
Get the type of an input object, for getIOType()
Definition: RAuxStore.cxx:1131
SG::AuxVarFlags
AuxVarFlags
Additional flags to qualify an auxiliary variable.
Definition: AuxTypes.h:58
xAOD::details::AuxStoreBase::getSelectedAuxIDs
virtual SG::auxid_set_t getSelectedAuxIDs() const override
Get the IDs of the selected aux variables.
Definition: AuxStoreBase.cxx:632
xAOD::details::AuxStoreBase::isAuxIDSelected
bool isAuxIDSelected(SG::auxid_t auxid) const
Check if an auxiliary variable is selected for ouput writing.
Definition: AuxStoreBase.cxx:648
GetAllXsec.entry
list entry
Definition: GetAllXsec.py:132
xAOD::RAuxStore::readFrom
StatusCode readFrom(ROOT::RNTupleReader &reader)
Connect the object to an input RNTuple.
Definition: RAuxStore.cxx:616
SG::AuxTypeRegistry::makeVector
std::unique_ptr< IAuxTypeVector > makeVector(SG::auxid_t auxid, size_t size, size_t capacity) const
Construct a new vector to hold an aux item.
Definition: AuxTypeRegistry.cxx:818
xAOD::details::AuxStoreBase::Members::m_structMode
EStructMode m_structMode
The "structural" mode of the object.
Definition: AuxStoreBase.h:174
ROOTTypes.h
xAOD::RAuxStore::setupInputData
virtual StatusCode setupInputData(SG::auxid_t auxid) override
Connect a variable to the input.
Definition: RAuxStore.cxx:779
xAOD::RAuxStore::impl::auxFieldType
const std::type_info * auxFieldType(const ROOT::RFieldBase &field, std::string *expectedClassName=nullptr)
This function retrieves the type information for a given auxiliary field.
Definition: RAuxStore.cxx:347
xAOD::Utils::getTypeInfo
const std::type_info & getTypeInfo(EDataType type)
This function is used when reading a primitive branch from an input file without the user explicitly ...
Definition: Control/xAODRootAccess/Root/Utils.cxx:194
SG::AuxVectorInterface
Make an AuxVectorData object from either a raw array or an aux store.
Definition: AuxVectorInterface.h:33
xAOD::RAuxStore::impl
Definition: RAuxStore.cxx:249
ReadCalibFromCrest.typeName
typeName
Definition: ReadCalibFromCrest.py:439
CxxUtils::reset
constexpr std::enable_if_t< is_bitmask_v< E >, E & > reset(E &lhs, E rhs)
Convenience function to clear bits in a class enum bitmask.
Definition: bitmask.h:251
AuxTypeRegistry.h
Handle mappings between names and auxid_t.
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
xAOD::details::AuxStoreBase::getIOData
virtual const void * getIOData(SG::auxid_t auxid) const override
Get a pointer to the data being stored for one aux data item.
Definition: AuxStoreBase.cxx:519
xAOD::RAuxStore::reset
virtual void reset() override
Tell the object that all branches will need to be re-read.
Definition: RAuxStore.cxx:735
xAOD::RAuxStore::RAuxStore
RAuxStore(std::string_view prefix="", bool topStore=true, EStructMode mode=EStructMode::kUndefinedStore)
Constructor.
Definition: RAuxStore.cxx:593
xAOD::details::AuxStoreBase::EStructMode::kUndefinedStore
@ kUndefinedStore
The structure mode is not defined.
xAOD::RAuxStore::writeTo
StatusCode writeTo(ROOT::RNTupleWriter &writer)
Add the variables of the store to an output RNTuple.
Definition: RAuxStore.cxx:642
SG::auxid_set_t
A set of aux data identifiers.
Definition: AuxTypes.h:47
ZDCMsg::Fatal
@ Fatal
Definition: ZDCMsg.h:23
pickleTool.object
object
Definition: pickleTool.py:29
L1Topo::Error
Error
The different types of error that can be flagged in the L1TopoRDO.
Definition: Error.h:16
xAOD::RAuxStore::m_impl
std::unique_ptr< impl > m_impl
Pointer to the internal object.
Definition: RAuxStore.h:87
collisions.reader
reader
read the goodrunslist xml file(s)
Definition: collisions.py:22
CxxUtils::ConcurrentBitset::erase
ConcurrentBitset & erase(bit_t bit)
Turn off one bit.
xAOD::details::AuxStoreBase::Members::m_isDecoration
std::vector< bool > m_isDecoration
Per variable lock status (indexed by auxiliary ID)
Definition: AuxStoreBase.h:196
example.writer
writer
show summary of content
Definition: example.py:36
AuxStoreInternal.h
An auxiliary data store that holds data internally.
xAOD::details::AuxStoreBase::Members::m_dynPrefix
std::string m_dynPrefix
Dynamic prefix for the branch names.
Definition: AuxStoreBase.h:180
dq_make_web_display.cl
cl
print [x.__class__ for x in toList(dqregion.getSubRegions()) ]
Definition: dq_make_web_display.py:25
xAOD::details::AuxStoreBase::Members::m_topStore
bool m_topStore
Flag stating whether this is a "top store".
Definition: AuxStoreBase.h:176
TAuxVectorFactory.h
xAOD::RAuxStore::commitTo
StatusCode commitTo(ROOT::REntry &entry)
Commit a new entry to the output RNTuple.
Definition: RAuxStore.cxx:713
xAOD::RAuxStore::impl::m_inputScanned
bool m_inputScanned
"Scan status" of the input RNTuple
Definition: RAuxStore.cxx:576
SG::AuxTypeRegistry::getAuxID
SG::auxid_t getAuxID(const std::string &name, const std::string &clsname="", const Flags flags=Flags::None, const SG::auxid_t linkedVariable=SG::null_auxid)
Look up a name -> auxid_t mapping.
xAOD::details::AuxStoreBase::Members
Struct collecting all member variables of this base class.
Definition: AuxStoreBase.h:171
CxxUtils::ConcurrentBitset::test
bool test(bit_t bit) const
Test to see if a bit is set.