ATLAS Offline Software
Loading...
Searching...
No Matches
EventIO.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).
10
11// Project include(s).
14
15// ROOT include(s).
16#include <TFile.h>
17#include <TTree.h>
18#include <TKey.h>
19
20// System include(s).
21#include <regex>
22#include <string>
23#include <vector>
24#include <memory>
25#include <set>
26#include <typeinfo>
27
28// Set up message printing functions for the static function(s).
29ANA_MSG_SOURCE(xAODEvent, "xAOD::Event")
30
31namespace xAOD {
32
33// Initialise some static data.
35const char* const Event::EVENT_RNTUPLE_NAME = "EventData";
37const char* const Event::EVENT_TREE_NAME = "CollectionTree";
39const char* const Event::METADATA_OBJECT_NAME = "MetaData";
40
43std::unique_ptr<Event> Event::createAndReadFrom(TFile& inFile) {
44
45 // Make use of the messaging function(s) from the xAODEvent namespace.
46 using xAODEvent::msg;
47
48 if (inFile.FindKey(EVENT_RNTUPLE_NAME) != nullptr) {
49 // Create and set up an REvent object
50 auto event = std::make_unique<Experimental::REvent>();
51 if (event->readFrom(inFile).isFailure()) {
52 ANA_MSG_ERROR("Could not read RNTuple from: " << inFile.GetName());
53 return {};
54 }
55 return event;
56 } else if (inFile.FindKey(EVENT_TREE_NAME) != nullptr) {
57 // Create and set up a TEvent object
58 // Check if file is AOD, in which case kAthenaAccess must be used
59 auto eauxMode = TEvent::kClassAccess;
60 std::string sauxMode = "kClassAccess";
61 auto metaData = dynamic_cast<TTree*>(inFile.Get("MetaData"));
62 if (metaData) {
63 auto rc = metaData->LoadTree(0);
64 if (rc < 0)[[unlikely]]{
65 ANA_MSG_ERROR("Error from LoadTree: "<< rc);
66 return {};
67 }
68 if (metaData->GetBranch("StreamAOD")) {
69 eauxMode = TEvent::kAthenaAccess;
70 sauxMode = "kAthenaAccess";
71 }
72 }
73 ANA_MSG_INFO("Using aux mode " << sauxMode << " for file " << inFile.GetName());
74 auto event = std::make_unique<TEvent>(eauxMode);
75 if (event->readFrom(inFile).isFailure()) {
76 ANA_MSG_ERROR("Could not read TTree from: " << inFile.GetName());
77 return {};
78 }
79 return event;
80 } else {
81 ANA_MSG_ERROR("Could not recognize file: " << inFile.GetName());
82 return {};
83 }
84}
85
95StatusCode Event::copy(const std::string& pattern) {
96
97 // Tell the user what's happening.
98 ATH_MSG_DEBUG("Copying objects matching pattern \"" << pattern
99 << "\" to the output");
100
101 // Collect a list of keys to copy.
102 std::set<std::string> keys;
103
104 // The regular expression to use.
105 std::regex re{pattern};
106
107 // Loop over the known input containers.
108 for (const auto& [key, efe] : m_inputEventFormat) {
109
110 // Tell the user what's happening.
111 ATH_MSG_VERBOSE("Considering input object with key \"" << key << "\"");
112
113 // Check if the class in question matches the requested pattern.
114 if (std::regex_match(key, re) == false) {
115 continue;
116 }
117 // Skip all branches ending in "Aux.":
118 if (key.ends_with("Aux.")) {
119 continue;
120 }
121 // Also skip dynamic branches:
122 if (efe.parentName() != "") {
123 continue;
124 }
125 // Ignore objects that don't exist on the input.
126 static const bool SILENT = true;
127 if (connectObject(key, SILENT).isSuccess() == false) {
128 continue;
129 }
130 // Add the key to the list.
131 ATH_MSG_VERBOSE("Matched key \"" << key << "\"");
132 keys.insert(key);
133 }
134
135 // Check if the pattern matches any of the name remapping rules.
136 for (const auto& [newname, onfile] : m_nameRemapping) {
137
138 // Tell the user what's happening.
139 ATH_MSG_VERBOSE("Considering remapped key \"" << newname << "\"");
140
141 // Check if the remapped name matches the pattern.
142 if (std::regex_match(newname, re) == false) {
143 continue;
144 }
145 // Ignore objects that don't exist on the input.
146 static const bool SILENT = true;
147 if (connectObject(onfile, SILENT).isSuccess() == false) {
148 continue;
149 }
150 // Add the remapped name to the list.
151 ATH_MSG_VERBOSE("Matched remapped key \"" << newname << "\"");
152 keys.insert(newname);
153 }
154
155 // Now loop over all of the found keys.
156 for (const std::string& key : keys) {
157
158 // Check if a name re-mapping should be applied or not.
159 std::string keyToUse = key;
160 auto remap_itr = m_nameRemapping.find(key);
161 if ((remap_itr != m_nameRemapping.end()) &&
162 (!m_inputEventFormat.exists(key)) &&
163 m_inputEventFormat.exists(remap_itr->second)) {
164 keyToUse = remap_itr->second;
165 }
166
167 // Make sure that the input object got connected to.
168 static const bool SILENT = false;
169 ATH_CHECK(connectObject(keyToUse, SILENT));
170
171 // Make sure that the input object is properly updated.
172 Object_t::const_iterator vobjMgr = m_inputObjects.find(keyToUse);
173 if (vobjMgr == m_inputObjects.end()) {
174 ATH_MSG_FATAL("Internal logic error detected");
175 return StatusCode::FAILURE;
176 }
178 dynamic_cast<Details::IObjectManager*>(vobjMgr->second.get());
179 if (objMgr == nullptr) {
180 ATH_MSG_FATAL("Internal logic error detected");
181 return StatusCode::FAILURE;
182 }
183 static const bool METADATA = false;
184 if (getInputObject(keyToUse, *(objMgr->holder()->getClass()->GetTypeInfo()),
185 SILENT, METADATA) == nullptr) {
186 ATH_MSG_FATAL("Internal logic error detected");
187 return StatusCode::FAILURE;
188 }
189
190 // Put the interface object into the output.
191 static const bool OVERWRITE = true;
192 static const bool IS_OWNER = true;
193 ATH_CHECK(record(objMgr->object(), objMgr->holder()->getClass()->GetName(),
194 key, OVERWRITE, METADATA, IS_OWNER));
195
196 // If there is also an auxiliary store for this object/container, copy that
197 // as well.
198 const std::string auxKey = keyToUse + "Aux.";
199 if (m_inputObjects.contains(auxKey)) {
200 ATH_CHECK(
201 recordAux(*(m_inputObjects.at(auxKey)), key + "Aux.", METADATA));
202 }
203 }
204
205 // Return gracefully:
206 return StatusCode::SUCCESS;
207}
208
221void* Event::getOutputObject(const std::string& key, const std::type_info& ti,
222 bool metadata) const {
223
224 // Select which object container to use:
225 const Object_t& objects = (metadata ? m_outputMetaObjects : m_outputObjects);
226
227 // Check if the object can be found:
228 auto itr = objects.find(key);
229 if (itr == objects.end()) {
230 // Do the following only for event data:
231 if (!metadata) {
232 // It's not in the event. Let's check if we find it in an active
233 // TStore object. (getAs fails for const objects, and wrong types.)
234 const TStore* store = TActiveStore::store();
235 const THolder* holder = (store ? store->holder(key) : nullptr);
236 static constexpr bool SILENT = true;
237 return (holder ? holder->getAs(ti, SILENT) : nullptr);
238 } else {
239 // For metadata we don't use external resources.
240 return nullptr;
241 }
242 }
243
244 // If the object is not set in this event yet, we can't continue:
245 if (itr->second->isSet() == false) {
246 return nullptr;
247 }
248
249 // If it does exist, check if it's the right kind of object:
251 dynamic_cast<Details::IObjectManager*>(itr->second.get());
252 if (mgr == nullptr) {
253 ATH_MSG_ERROR("Object of wrong type found for key \"" << key << "\"");
254 return nullptr;
255 }
256
257 // Ask the holder object for the object of this type:
258 void* result = mgr->holder()->getAs(ti);
259 if (result == nullptr) {
260 ATH_MSG_WARNING("Couldn't retrieve object as \""
261 << SG::normalizedTypeinfoName(ti) << "\"");
262 return nullptr;
263 }
264
265 // Return the object:
266 return result;
267}
268
281const void* Event::getInputObject(const std::string& key,
282 const std::type_info& ti, bool silent,
283 bool metadata) {
284
285 // Check if a name remapping should be applied or not:
286 std::string keyToUse = key;
287 auto remap_itr = m_nameRemapping.find(key);
288 if ((remap_itr != m_nameRemapping.end()) &&
289 (!m_inputEventFormat.exists(key)) &&
290 m_inputEventFormat.exists(remap_itr->second)) {
291 keyToUse = remap_itr->second;
292 }
293
294 // The following catches the cases when we ask for a transient
295 // ConstDataVector object to be returned as "const DataVector".
296 const TStore* store = TActiveStore::store();
297 if (const THolder* holder = (store ? store->holder(keyToUse) : nullptr)) {
298 static constexpr bool SILENT = true;
299 const void* result = holder->getAsConst(ti, SILENT);
300 if (result && !holder->getAs(ti, SILENT)) {
301 return result;
302 }
303 }
304
305 // A sanity check before checking for an object from the input file.
306 if (hasInput() == false) {
307 if (silent == false) {
308 ATH_MSG_WARNING("No input file connected to the Event object");
309 }
310 return nullptr;
311 }
312
313 // Make sure that the requested input is connected to.
314 const StatusCode sc = (metadata ? connectMetaObject(keyToUse, silent)
315 : connectObject(keyToUse, silent));
316 if (sc.isSuccess() == false) {
317 return nullptr;
318 }
319
320 // Select which object container to use:
321 Object_t& objects = (metadata ? m_inputMetaObjects : m_inputObjects);
322
323 // Access the object's manager:
324 auto itr = objects.find(keyToUse);
325 if (itr == objects.end()) {
326 ATH_MSG_FATAL("There is an internal logic error in the code...");
327 return nullptr;
328 }
329
330 // This has to be an ObjectManager object:
332 dynamic_cast<Details::IObjectManager*>(itr->second.get());
333 if (mgr == nullptr) {
334 if (key == keyToUse) {
335 ATH_MSG_ERROR("Object of wrong type found for key \"" << key << "\"");
336 } else {
337 ATH_MSG_ERROR("Object of wrong type found for key \""
338 << key << "\"/\"" << keyToUse << "\"");
339 }
340 return nullptr;
341 }
342
343 // Make sure that the current entry is loaded for event data objects.
344 if (metadata == false) {
345 const Int_t readBytes = mgr->getEntry();
346 if (readBytes > 0) {
347 // Connect the auxiliary store to objects needing it. This call also
348 // takes care of updating the dynamic store of auxiliary containers,
349 // when they are getting accessed directly.
350 static const bool IS_METADATA = false;
351 if (setAuxStore(key, *mgr, IS_METADATA).isSuccess() == false) {
352 ATH_MSG_ERROR("Failed to set the auxiliary store for "
353 << mgr->holder()->getClass()->GetName() << "/"
354 << keyToUse);
355 return nullptr;
356 }
357 } else if (readBytes < 0) {
358 ATH_MSG_ERROR("Failed to load current entry for object "
359 << mgr->holder()->getClass()->GetName() << "/" << keyToUse);
360 return nullptr;
361 }
362 }
363
364 // Ask the holder object for the object of this type:
365 const void* result = mgr->holder()->getAsConst(ti, silent);
366 if (result == nullptr) {
367 if (!silent) {
368 ATH_MSG_WARNING("Could not retrieve object with key \""
369 << keyToUse << "\" as \""
370 << SG::normalizedTypeinfoName(ti) << "\"");
371 }
372 return nullptr;
373 }
374
375 // We succeeded:
376 return result;
377}
378
388::Bool_t Event::contains(const std::string& key, const std::type_info& ti,
389 ::Bool_t metadata) {
390
391 static const bool SILENT = true;
392 return ((getOutputObject(key, ti, metadata) != nullptr) ||
393 (getInputObject(key, ti, SILENT, metadata) != nullptr));
394}
395
407::Bool_t Event::transientContains(const std::string& key,
408 const std::type_info& ti,
409 ::Bool_t metadata) const {
410
411 return (getOutputObject(key, ti, metadata) != nullptr);
412}
413
414} // namespace xAOD
const std::regex re(r_e)
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_DEBUG(x,...)
#define ATH_MSG_ERROR(x,...)
#define ATH_MSG_WARNING(x,...)
#define ATH_MSG_VERBOSE(x,...)
#define ATH_MSG_FATAL(x,...)
macros for messaging and checking status codes
#define ANA_MSG_ERROR(xmsg,...)
Macro printing error messages.
#define ANA_MSG_INFO(xmsg,...)
Macro printing info messages.
#define ANA_MSG_SOURCE(NAME, TITLE)
the source code part of ANA_MSG_SOURCE
static Double_t sc
static Double_t rc
Manager for EDM objects created by ROOT.
const THolder * holder() const
Accessor to the Holder object.
virtual bool hasInput() const =0
Check if an input file is connected to the object.
EventFormat m_inputEventFormat
Format of the current input file.
Definition Event.h:355
virtual StatusCode recordAux(TVirtualManager &mgr, const std::string &key, bool metadata)=0
Record an auxiliary store into a connected output file.
static std::unique_ptr< Event > createAndReadFrom(TFile &file)
static method to create an Event object and readFrom a file, given by a TFile.
Definition EventIO.cxx:43
bool contains(const std::string &key)
Function checking if an object is available from the store.
const void * getInputObject(SG::sgkey_t key, const std::type_info &ti, bool silent) override
Function for retrieving an input object in a non-template way.
virtual StatusCode connectObject(const std::string &key, bool silent)=0
Function setting up access to a particular object.
std::unordered_map< std::string, std::unique_ptr< TVirtualManager > > Object_t
Definition of the internal data structure type.
Definition Event.h:338
Object_t m_inputObjects
Collection of all the managed input objects.
Definition Event.h:342
static const char *const EVENT_TREE_NAME
Default name of the event TTree.
Definition Event.h:77
StatusCode copy(const std::string &pattern=".*")
Copy an object directly from the input to the output.
Definition EventIO.cxx:95
void * getOutputObject(SG::sgkey_t key, const std::type_info &ti) override
Function for retrieving an output object in a non-template way.
virtual StatusCode connectMetaObject(const std::string &key, bool silent)=0
Function setting up access to a particular metadata object.
virtual StatusCode setAuxStore(const std::string &key, Details::IObjectManager &mgr, bool metadata)=0
Function connecting a DV object to its auxiliary store.
StatusCode record(T *obj, const std::string &key)
Add an output object to the event.
StatusCode keys(std::vector< std::string > &vkeys, bool metadata) const
Provide a list of all data object keys associated with a specific type.
static const char *const EVENT_RNTUPLE_NAME
Name of the event RNTuple.
Definition Event.h:78
std::unordered_map< std::string, std::string > m_nameRemapping
Container name re-mapping rules.
Definition Event.h:366
Object_t m_inputMetaObjects
Collection of all the managed input meta-objects.
Definition Event.h:350
Object_t m_outputObjects
Collection of all the managed output object.
Definition Event.h:347
Object_t m_outputMetaObjects
Collection of all the managed output meta-objects.
Definition Event.h:352
static TStore * store()
Access the currently active TStore object.
@ kAthenaAccess
Access containers/objects like Athena does.
@ kClassAccess
Access auxiliary data using the aux containers.
This class takes care of holding EDM objects in memory.
Definition THolder.h:35
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
A relatively simple transient store for objects created in analysis.
Definition TStore.h:46
virtual const void * object() const =0
Function getting a const pointer to the object being handled.
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...
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
const void * getInputObject(xAOD::Event &event, const std::string &key, const std::type_info &ti, bool silent, bool metadata)
Retrieve an input object from an xAODTEvent or xAODREvent in a non-template way.
Definition xAODEvent.h:49
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
#define unlikely(x)