Belle II Software light-2411-aldebaran
RootFileInfo.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <iostream>
10#include <framework/io/RootFileInfo.h>
11#include <framework/io/RootIOUtilities.h>
12#include <framework/dataobjects/FileMetaData.h>
13#include <framework/datastore/DataStore.h>
14
15#include <TTree.h>
16#include <TFile.h>
17
19 RootFileInfo::RootFileInfo(const std::string& filename)
20 {
21 // make sure TDirectory is reset after this function
22 TDirectory::TContext directoryGuard;
23 // Open the file
24 m_file.reset(TFile::Open(filename.c_str(), "READ"));
25 if (!m_file || !m_file->IsOpen()) throw std::invalid_argument("Could not open file");
26 // We want to get two trees the same way but only need that here ... lambda it is
27 auto getTree = [&file = this->m_file](const std::string & label, const std::string & name, std::unique_ptr<TTree>& destination) {
28 TTree* tmp{nullptr};
29 file->GetObject(name.c_str(), tmp);
30 if (!tmp) throw std::runtime_error("No " + label + " tree found");
31 destination.reset(tmp);
32 };
33 // So get the trees from the file and store them in the members
34 getTree("persistent", c_treeNames[DataStore::c_Persistent], m_persistent);
35 auto description = getFileMetaData().getDataDescription();
36 auto isNtuple = description.find("isNtupleMetaData");
37 if ((isNtuple == description.end()) || (isNtuple->second != "True")) {
38 getTree("event", c_treeNames[DataStore::c_Event], m_events);
39 }
40 // And finally check the number of entries in the persistent tree
41 if (auto npersistent = m_persistent->GetEntries(); npersistent != 1) {
42 throw std::runtime_error("Expected exactly one entry in persistent tree, found " + std::to_string(npersistent));
43 }
44 }
45
47 {
48 if (!m_metadata) {
49 // object not set yet, get it from file
50 FileMetaData* metadata{nullptr};
51 auto branchStatus = m_persistent->SetBranchAddress("FileMetaData", &metadata);
52 if (branchStatus < 0) throw std::runtime_error("Error retrieving FileMetaData branch: " + std::to_string(branchStatus));
53 if (m_persistent->GetEntry(0) <= 0 || !metadata) throw std::runtime_error("Cannot read FileMetaData");
54 // and remembber
55 m_metadata.reset(metadata);
56 }
57 return *m_metadata;
58 }
59
60 const std::set<std::string>& RootFileInfo::getBranchNames(bool persistent)
61 {
62 // which set of branches are we looking at?
63 std::optional<std::set<std::string>>& cache{persistent ? m_persistentBranches : m_eventBranches};
64 // if we didn't create the list already do it now
65 if (!cache) {
66 TTree& tree{persistent ? *m_persistent :* m_events};
67 std::set<std::string> result;
68 for (const TObject* obj : * (tree.GetListOfBranches())) {
69 const auto* branch = dynamic_cast<const TBranch*>(obj);
70 if (!branch) throw std::runtime_error("Entry in list of branches is no branch");
71 result.emplace(branch->GetName());
72 }
73 // and remember
74 cache.emplace(std::move(result));
75 }
76 // and just return the content
77 return *cache;
78 }
79
80 const std::set<std::string> RootFileInfo::getNtupleBranchNames(std::string treeName)
81 {
82 std::set<std::string> branches;
83 auto* tree = dynamic_cast<TTree*>(m_file->Get(treeName.c_str()));
84 for (const TObject* obj : * (tree->GetListOfBranches())) {
85 const auto* branch = dynamic_cast<const TBranch*>(obj);
86 if (!branch) throw std::runtime_error("Entry in list of branches is no branch");
87 branches.emplace(branch->GetName());
88 }
89 return branches;
90 }
91
92 void RootFileInfo::checkMissingBranches(const std::set<std::string>& required, bool persistent)
93 {
94 // So let's get the list of existing branches
95 const auto& existing = getBranchNames(persistent);
96 // and fill a list of branches which are in required but not existing
97 std::vector<std::string> missing;
98 std::set_difference(required.begin(), required.end(), existing.begin(), existing.end(),
99 std::inserter(missing, missing.begin()));
100 // and if that is not empty we complain
101 if (!missing.empty()) {
102 std::stringstream message;
103 message << "Branches missing from event tree: ";
104 for (const auto& name : missing) {
105 message << name << ", ";
106 }
107 throw std::runtime_error(message.str());
108 }
109 }
110
111 const std::set<std::string> RootFileInfo::getTreeNames()
112 {
113 std::set<std::string> treeNames;
114 TList* keylist = m_file->GetListOfKeys();
115 TIter next(keylist);
116 while (auto&& key = next()) {
117 if (strcmp(key->GetName(), "persistent") != 0) {
118 treeNames.emplace(key->GetName());
119 }
120 }
121 return treeNames;
122 }
123
124 /* Destructor. Declared here to allow forward declaration of TFile,TTree,... in header */
125 RootFileInfo::~RootFileInfo() = default;
126}
@ c_Persistent
Object is available during entire execution time.
Definition: DataStore.h:60
@ c_Event
Different object in each event, all objects/arrays are invalidated after event() function has been ca...
Definition: DataStore.h:59
Metadata information about a file.
Definition: FileMetaData.h:29
const std::map< std::string, std::string > & getDataDescription() const
get data description.
Definition: FileMetaData.h:133
const std::set< std::string > getTreeNames()
Return a set of event tree names in the file.
const FileMetaData & getFileMetaData()
Return the event metadata from the file.
Definition: RootFileInfo.cc:46
std::unique_ptr< TTree > m_events
Pointer to the event tree.
Definition: RootFileInfo.h:63
void checkMissingBranches(const std::set< std::string > &required, bool persistent=false)
Check if the event or persistent tree contain at least all the branches in the set of required branch...
Definition: RootFileInfo.cc:92
std::unique_ptr< FileMetaData > m_metadata
Pointer to the file metadata once it has been read.
Definition: RootFileInfo.h:65
std::optional< std::set< std::string > > m_persistentBranches
Cached set of persistent branch names.
Definition: RootFileInfo.h:67
std::unique_ptr< TFile > m_file
Pointer to the file object.
Definition: RootFileInfo.h:59
std::optional< std::set< std::string > > m_eventBranches
Cached set of event branch names.
Definition: RootFileInfo.h:69
RootFileInfo(const std::string &filename)
Create an object from a given filename or url.
Definition: RootFileInfo.cc:19
~RootFileInfo()
Close the file and delete all structures associated with it.
const std::set< std::string > getNtupleBranchNames(std::string treeName)
Return a set of branch names residing in the passed tree.
Definition: RootFileInfo.cc:80
std::unique_ptr< TTree > m_persistent
Pointer to the persistent tree.
Definition: RootFileInfo.h:61
const std::set< std::string > & getBranchNames(bool persistent=false)
Return a set of branch names for either the event or the persistent tree.
Definition: RootFileInfo.cc:60
Some constants and helpers common to the RootInput and RootOutput modules.
Definition: RootFileInfo.h:23
const std::string c_treeNames[]
Names of trees.