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...
234 TStore* store = TActiveStore::store();
235 if ((!store) || (!store->contains(key, ti)) || store->isConst(key, ti)) {
236 // Nope, not there either...
237 return nullptr;
238 }
239 // Let's return the object from the TStore:
240 void* result = store->getObject(key, ti);
241 return result;
242 } else {
243 // For metadata we don't use external resources.
244 return nullptr;
245 }
246 }
247
248 // If the object is not set in this event yet, we can't continue:
249 if (itr->second->isSet() == false) {
250 return nullptr;
251 }
252
253 // If it does exist, check if it's the right kind of object:
255 dynamic_cast<Details::IObjectManager*>(itr->second.get());
256 if (mgr == nullptr) {
257 ATH_MSG_ERROR("Object of wrong type found for key \"" << key << "\"");
258 return nullptr;
259 }
260
261 // Ask the holder object for the object of this type:
262 void* result = mgr->holder()->getAs(ti);
263 if (result == nullptr) {
264 ATH_MSG_WARNING("Couldn't retrieve object as \""
265 << SG::normalizedTypeinfoName(ti) << "\"");
266 return nullptr;
267 }
268
269 // Return the object:
270 return result;
271}
272
285const void* Event::getInputObject(const std::string& key,
286 const std::type_info& ti, bool silent,
287 bool metadata) {
288
289 // Check if a name remapping should be applied or not:
290 std::string keyToUse = key;
291 auto remap_itr = m_nameRemapping.find(key);
292 if ((remap_itr != m_nameRemapping.end()) &&
293 (!m_inputEventFormat.exists(key)) &&
294 m_inputEventFormat.exists(remap_itr->second)) {
295 keyToUse = remap_itr->second;
296 }
297
298 // The following catches the cases when we ask for a transient
299 // ConstDataVector object to be returned as "const DataVector".
300 TStore* store = TActiveStore::store();
301 if (store && store->contains(keyToUse, ti) && store->isConst(keyToUse, ti)) {
302 const void* result = store->getConstObject(keyToUse, ti);
303 return result;
304 }
305
306 // A sanity check before checking for an object from the input file.
307 if (hasInput() == false) {
308 if (silent == false) {
309 ATH_MSG_WARNING("No input file connected to the Event object");
310 }
311 return nullptr;
312 }
313
314 // Make sure that the requested input is connected to.
315 const StatusCode sc = (metadata ? connectMetaObject(keyToUse, silent)
316 : connectObject(keyToUse, silent));
317 if (sc.isSuccess() == false) {
318 return nullptr;
319 }
320
321 // Select which object container to use:
322 Object_t& objects = (metadata ? m_inputMetaObjects : m_inputObjects);
323
324 // Access the object's manager:
325 auto itr = objects.find(keyToUse);
326 if (itr == objects.end()) {
327 ATH_MSG_FATAL("There is an internal logic error in the code...");
328 return nullptr;
329 }
330
331 // This has to be an ObjectManager object:
333 dynamic_cast<Details::IObjectManager*>(itr->second.get());
334 if (mgr == nullptr) {
335 if (key == keyToUse) {
336 ATH_MSG_ERROR("Object of wrong type found for key \"" << key << "\"");
337 } else {
338 ATH_MSG_ERROR("Object of wrong type found for key \""
339 << key << "\"/\"" << keyToUse << "\"");
340 }
341 return nullptr;
342 }
343
344 // Make sure that the current entry is loaded for event data objects.
345 if (metadata == false) {
346 const Int_t readBytes = mgr->getEntry();
347 if (readBytes > 0) {
348 // Connect the auxiliary store to objects needing it. This call also
349 // takes care of updating the dynamic store of auxiliary containers,
350 // when they are getting accessed directly.
351 static const bool IS_METADATA = false;
352 if (setAuxStore(key, *mgr, IS_METADATA).isSuccess() == false) {
353 ATH_MSG_ERROR("Failed to set the auxiliary store for "
354 << mgr->holder()->getClass()->GetName() << "/"
355 << keyToUse);
356 return nullptr;
357 }
358 } else if (readBytes < 0) {
359 ATH_MSG_ERROR("Failed to load current entry for object "
360 << mgr->holder()->getClass()->GetName() << "/" << keyToUse);
361 return nullptr;
362 }
363 }
364
365 // Ask the holder object for the object of this type:
366 const void* result = mgr->holder()->getAsConst(ti, silent);
367 if (result == nullptr) {
368 if (!silent) {
369 ATH_MSG_WARNING("Could not retrieve object with key \""
370 << keyToUse << "\" as \""
371 << SG::normalizedTypeinfoName(ti) << "\"");
372 }
373 return nullptr;
374 }
375
376 // We succeeded:
377 return result;
378}
379
389::Bool_t Event::contains(const std::string& key, const std::type_info& ti,
390 ::Bool_t metadata) {
391
392 static const bool SILENT = true;
393 return ((getOutputObject(key, ti, metadata) != nullptr) ||
394 (getInputObject(key, ti, SILENT, metadata) != nullptr));
395}
396
408::Bool_t Event::transientContains(const std::string& key,
409 const std::type_info& ti,
410 ::Bool_t metadata) const {
411
412 return (getOutputObject(key, ti, metadata) != nullptr);
413}
414
415} // namespace xAOD
const boost::regex re(r_e)
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
macros for messaging and checking status codes
#define ANA_MSG_INFO(xmsg)
Macro printing info messages.
#define ANA_MSG_ERROR(xmsg)
Macro printing error 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:350
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:333
Object_t m_inputObjects
Collection of all the managed input objects.
Definition Event.h:337
static const char *const EVENT_TREE_NAME
Default name of the event TTree.
Definition Event.h:76
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:77
std::unordered_map< std::string, std::string > m_nameRemapping
Container name re-mapping rules.
Definition Event.h:361
Object_t m_inputMetaObjects
Collection of all the managed input meta-objects.
Definition Event.h:345
Object_t m_outputObjects
Collection of all the managed output object.
Definition Event.h:342
Object_t m_outputMetaObjects
Collection of all the managed output meta-objects.
Definition Event.h:347
static TStore * store()
Access the currently active TStore object.
@ kAthenaAccess
Access containers/objects like Athena does.
@ kClassAccess
Access auxiliary data using the aux containers.
const ::TClass * getClass() const
Definition THolder.cxx:402
A relatively simple transient store for objects created in analysis.
Definition TStore.h:45
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.
Convert a type_info to a normalized string representation (matching the names used in the root dictio...
#define unlikely(x)