PODIO v00-16-03
An Event-Data-Model Toolkit for High Energy Physics Experiments
Loading...
Searching...
No Matches
ROOTLegacyReader.cc
Go to the documentation of this file.
3#include "rootUtils.h"
4
5// podio specific includes
10
11// ROOT specific includes
12#include "TChain.h"
13#include "TClass.h"
14#include "TFile.h"
15#include "TTree.h"
16#include "TTreeCache.h"
17
18#include <unordered_map>
19
20namespace podio {
21
22std::unique_ptr<ROOTFrameData> ROOTLegacyReader::readNextEntry(const std::string& name) {
23 if (name != m_categoryName) {
24 return nullptr;
25 }
26 return readEntry();
27}
28
29std::unique_ptr<podio::ROOTFrameData> ROOTLegacyReader::readEntry(const std::string& name, unsigned entry) {
30 if (name != m_categoryName) {
31 return nullptr;
32 }
33 m_eventNumber = entry;
34 return readEntry();
35}
36
37std::unique_ptr<podio::ROOTFrameData> ROOTLegacyReader::readEntry() {
39 for (const auto& collInfo : m_storedClasses) {
40 buffers.emplace(collInfo.first, getCollectionBuffers(collInfo));
41 }
42
43 auto parameters = readEventMetaData();
44
45 m_eventNumber++;
46 return std::make_unique<ROOTFrameData>(std::move(buffers), m_table, std::move(parameters));
47}
48
50ROOTLegacyReader::getCollectionBuffers(const std::pair<std::string, detail::CollectionInfo>& collInfo) {
51 const auto& name = collInfo.first;
52 const auto& [theClass, collectionClass, index] = collInfo.second;
53 auto& branches = m_collectionBranches[index];
54
55 // Create empty collection buffers, and connect them to the right branches
56 auto collBuffers = podio::CollectionReadBuffers();
57 // If we have a valid data buffer class we know that have to read data,
58 // otherwise we are handling a subset collection
59 const bool isSubsetColl = theClass == nullptr;
60 if (!isSubsetColl) {
61 collBuffers.data = theClass->New();
62 }
63
64 {
65 auto collection =
66 std::unique_ptr<podio::CollectionBase>(static_cast<podio::CollectionBase*>(collectionClass->New()));
67 collection->setSubsetCollection(isSubsetColl);
68
69 auto tmpBuffers = collection->createBuffers();
70 collBuffers.createCollection = std::move(tmpBuffers.createCollection);
71 collBuffers.recast = std::move(tmpBuffers.recast);
72
73 if (auto* refs = tmpBuffers.references) {
74 collBuffers.references = new podio::CollRefCollection(refs->size());
75 }
76 if (auto* vminfo = tmpBuffers.vectorMembers) {
77 collBuffers.vectorMembers = new podio::VectorMembersInfo();
78 collBuffers.vectorMembers->reserve(vminfo->size());
79
80 for (const auto& [type, _] : (*vminfo)) {
81 const auto* vecClass = TClass::GetClass(("vector<" + type + ">").c_str());
82 collBuffers.vectorMembers->emplace_back(type, vecClass->New());
83 }
84 }
85 }
86
87 const auto localEntry = m_chain->LoadTree(m_eventNumber);
88 // After switching trees in the chain, branch pointers get invalidated so
89 // they need to be reassigned.
90 // NOTE: root 6.22/06 requires that we get completely new branches here,
91 // with 6.20/04 we could just re-set them
92 if (localEntry == 0) {
93 branches.data = root_utils::getBranch(m_chain.get(), name.c_str());
94
95 // reference collections
96 if (auto* refCollections = collBuffers.references) {
97 for (size_t i = 0; i < refCollections->size(); ++i) {
98 const auto brName = root_utils::refBranch(name, i);
99 branches.refs[i] = root_utils::getBranch(m_chain.get(), brName.c_str());
100 }
101 }
102
103 // vector members
104 if (auto* vecMembers = collBuffers.vectorMembers) {
105 for (size_t i = 0; i < vecMembers->size(); ++i) {
106 const auto brName = root_utils::vecBranch(name, i);
107 branches.vecs[i] = root_utils::getBranch(m_chain.get(), brName.c_str());
108 }
109 }
110 }
111
112 // set the addresses and read the data
113 root_utils::setCollectionAddresses(collBuffers, branches);
114 root_utils::readBranchesData(branches, localEntry);
115
116 collBuffers.recast(collBuffers);
117
118 return collBuffers;
119}
120
121podio::GenericParameters ROOTLegacyReader::readEventMetaData() {
122 GenericParameters params;
123 auto [tree, entry] = getLocalTreeAndEntry("evt_metadata");
124 auto* branch = root_utils::getBranch(tree, "evtMD");
125 auto* emd = &params;
126 branch->SetAddress(&emd);
127 branch->GetEntry(entry);
128 return params;
129}
130
131void ROOTLegacyReader::openFile(const std::string& filename) {
132 openFiles({filename});
133}
134
135void ROOTLegacyReader::openFiles(const std::vector<std::string>& filenames) {
136 m_chain = std::make_unique<TChain>("events");
137 for (const auto& filename : filenames) {
138 //-1 forces the headers to be read so that
139 // the validity of the files can be checked
140 if (!m_chain->Add(filename.c_str(), -1)) {
141 throw std::runtime_error("File " + filename + " couldn't be found");
142 }
143 }
144
145 // read the meta data and build the collectionBranches cache
146 // NOTE: This is a small pessimization, if we do not read all collections
147 // afterwards, but it makes the handling much easier in general
148 auto metadatatree = static_cast<TTree*>(m_chain->GetFile()->Get("metadata"));
149 m_table = std::make_shared<CollectionIDTable>();
150 auto* table = m_table.get();
151 metadatatree->SetBranchAddress("CollectionIDs", &table);
152
153 podio::version::Version* versionPtr{nullptr};
154 if (auto* versionBranch = root_utils::getBranch(metadatatree, "PodioVersion")) {
155 versionBranch->SetAddress(&versionPtr);
156 }
157
158 // Check if the CollectionTypeInfo branch is there and assume that the file
159 // has been written with with podio pre #197 (<0.13.1) if that is not the case
160 if (auto* collInfoBranch = root_utils::getBranch(metadatatree, "CollectionTypeInfo")) {
161 auto collectionInfo = new std::vector<root_utils::CollectionInfoT>;
162 collInfoBranch->SetAddress(&collectionInfo);
163 metadatatree->GetEntry(0);
164 createCollectionBranches(*collectionInfo);
165 delete collectionInfo;
166 } else {
167 std::cout << "PODIO: Reconstructing CollectionTypeInfo branch from other sources in file: \'"
168 << m_chain->GetFile()->GetName() << "\'" << std::endl;
169 metadatatree->GetEntry(0);
170 const auto collectionInfo = root_utils::reconstructCollectionInfo(m_chain.get(), *m_table);
171 createCollectionBranches(collectionInfo);
172 }
173
174 m_fileVersion = versionPtr ? *versionPtr : podio::version::Version{0, 0, 0};
175 delete versionPtr;
176}
177
178unsigned ROOTLegacyReader::getEntries(const std::string& name) const {
179 if (name != m_categoryName) {
180 return 0;
181 }
182 return m_chain->GetEntries();
183}
184
185void ROOTLegacyReader::createCollectionBranches(const std::vector<root_utils::CollectionInfoT>& collInfo) {
186 size_t collectionIndex{0};
187
188 for (const auto& [collID, collType, isSubsetColl] : collInfo) {
189 // We only write collections that are in the collectionIDTable, so no need
190 // to check here
191 const auto name = m_table->name(collID);
192
193 root_utils::CollectionBranches branches{};
194 const auto collectionClass = TClass::GetClass(collType.c_str());
195
196 // Need the collection here to setup all the branches. Have to manage the
197 // temporary collection ourselves
198 auto collection =
199 std::unique_ptr<podio::CollectionBase>(static_cast<podio::CollectionBase*>(collectionClass->New()));
200 collection->setSubsetCollection(isSubsetColl);
201
202 if (!isSubsetColl) {
203 // This branch is guaranteed to exist since only collections that are
204 // also written to file are in the info metadata that we work with here
205 branches.data = root_utils::getBranch(m_chain.get(), name.c_str());
206 }
207
208 const auto buffers = collection->getBuffers();
209 for (size_t i = 0; i < buffers.references->size(); ++i) {
210 const auto brName = root_utils::refBranch(name, i);
211 branches.refs.push_back(root_utils::getBranch(m_chain.get(), brName.c_str()));
212 }
213
214 for (size_t i = 0; i < buffers.vectorMembers->size(); ++i) {
215 const auto brName = root_utils::vecBranch(name, i);
216 branches.vecs.push_back(root_utils::getBranch(m_chain.get(), brName.c_str()));
217 }
218
219 const std::string bufferClassName = "std::vector<" + collection->getDataTypeName() + ">";
220 const auto bufferClass = isSubsetColl ? nullptr : TClass::GetClass(bufferClassName.c_str());
221
222 m_storedClasses.emplace_back(name, std::make_tuple(bufferClass, collectionClass, collectionIndex++));
223 m_collectionBranches.push_back(branches);
224 }
225}
226
227std::pair<TTree*, unsigned> ROOTLegacyReader::getLocalTreeAndEntry(const std::string& treename) {
228 auto localEntry = m_chain->LoadTree(m_eventNumber);
229 auto* tree = static_cast<TTree*>(m_chain->GetFile()->Get(treename.c_str()));
230 return {tree, localEntry};
231}
232
233std::vector<std::string_view> ROOTLegacyReader::getAvailableCategories() const {
234 return {m_categoryName};
235}
236
237} // namespace podio
std::unordered_map< std::string, podio::CollectionReadBuffers > BufferMap
Definition: ROOTFrameData.h:19
std::unique_ptr< podio::ROOTFrameData > readEntry(const std::string &, const unsigned entry)
void openFile(const std::string &filename)
void openFiles(const std::vector< std::string > &filenames)
std::unique_ptr< podio::ROOTFrameData > readNextEntry(const std::string &)
std::vector< std::string_view > getAvailableCategories() const
Get the names of all the availalable Frame categories in the current file(s)
unsigned getEntries(const std::string &) const
Returns number of entries for a given category.
auto reconstructCollectionInfo(TTree *eventTree, podio::CollectionIDTable const &idTable)
Definition: rootUtils.h:130
std::string refBranch(const std::string &name, size_t index)
Definition: rootUtils.h:75
std::string vecBranch(const std::string &name, size_t index)
Definition: rootUtils.h:79
TBranch * getBranch(Tree *chain, const char *name)
Definition: rootUtils.h:66
void setCollectionAddresses(const BufferT &collBuffers, const CollectionBranches &branches)
Definition: rootUtils.h:84
void readBranchesData(const CollectionBranches &branches, Long64_t entry)
Definition: rootUtils.h:108
std::vector< std::pair< std::string, void * > > VectorMembersInfo
std::vector< UVecPtr< podio::ObjectID > > CollRefCollection