Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
RRootDS.cxx
Go to the documentation of this file.
1 #include <ROOT/RDF/Utils.hxx>
2 #include <ROOT/RRootDS.hxx>
3 #include <ROOT/TSeq.hxx>
4 #include <TClass.h>
5 #include <TError.h>
6 #include <TROOT.h> // For the gROOTMutex
7 #include <TVirtualMutex.h> // For the R__LOCKGUARD
8 #include <ROOT/RMakeUnique.hxx>
9 
10 #include <algorithm>
11 #include <vector>
12 
13 namespace ROOT {
14 
15 namespace RDF {
16 
17 std::vector<void *> RRootDS::GetColumnReadersImpl(std::string_view name, const std::type_info &id)
18 {
19  const auto colTypeName = GetTypeName(name);
20  const auto &colTypeId = ROOT::Internal::RDF::TypeName2TypeID(colTypeName);
21  if (id != colTypeId) {
22  std::string err = "The type of column \"";
23  err += name;
24  err += "\" is ";
25  err += colTypeName;
26  err += " but a different one has been selected.";
27  throw std::runtime_error(err);
28  }
29 
30  const auto index =
31  std::distance(fListOfBranches.begin(), std::find(fListOfBranches.begin(), fListOfBranches.end(), name));
32  std::vector<void *> ret(fNSlots);
33  for (auto slot : ROOT::TSeqU(fNSlots)) {
34  ret[slot] = (void *)&fBranchAddresses[index][slot];
35  }
36  return ret;
37 }
38 
39 RRootDS::RRootDS(std::string_view treeName, std::string_view fileNameGlob)
40  : fTreeName(treeName), fFileNameGlob(fileNameGlob), fModelChain(std::string(treeName).c_str())
41 {
42  fModelChain.Add(fFileNameGlob.c_str());
43 
44  const TObjArray &lob = *fModelChain.GetListOfBranches();
45  fListOfBranches.resize(lob.GetEntries());
46 
47  TIterCategory<TObjArray> iter(&lob);
48  std::transform(iter.Begin(), iter.End(), fListOfBranches.begin(), [](TObject *o) { return o->GetName(); });
49 }
50 
51 RRootDS::~RRootDS()
52 {
53  for (auto addr : fAddressesToFree) {
54  delete addr;
55  }
56 }
57 
58 std::string RRootDS::GetTypeName(std::string_view colName) const
59 {
60  if (!HasColumn(colName)) {
61  std::string e = "The dataset does not have column ";
62  e += colName;
63  throw std::runtime_error(e);
64  }
65  // TODO: we need to factor out the routine for the branch alone...
66  // Maybe a cache for the names?
67  auto typeName =
68  ROOT::Internal::RDF::ColumnName2ColumnTypeName(std::string(colName), /*nsID=*/0, &fModelChain, /*ds=*/nullptr,
69  /*isCustomCol=*/false);
70  // We may not have yet loaded the library where the dictionary of this type is
71  TClass::GetClass(typeName.c_str());
72  return typeName;
73 }
74 
75 const std::vector<std::string> &RRootDS::GetColumnNames() const
76 {
77  return fListOfBranches;
78 }
79 
80 bool RRootDS::HasColumn(std::string_view colName) const
81 {
82  if (!fListOfBranches.empty())
83  GetColumnNames();
84  return fListOfBranches.end() != std::find(fListOfBranches.begin(), fListOfBranches.end(), colName);
85 }
86 
87 void RRootDS::InitSlot(unsigned int slot, ULong64_t firstEntry)
88 {
89  auto chain = new TChain(fTreeName.c_str());
90  chain->ResetBit(kMustCleanup);
91  chain->Add(fFileNameGlob.c_str());
92  chain->GetEntry(firstEntry);
93  TString setBranches;
94  for (auto i : ROOT::TSeqU(fListOfBranches.size())) {
95  auto colName = fListOfBranches[i].c_str();
96  auto &addr = fBranchAddresses[i][slot];
97  auto typeName = GetTypeName(colName);
98  auto typeClass = TClass::GetClass(typeName.c_str());
99  if (typeClass) {
100  chain->SetBranchAddress(colName, &addr, nullptr, typeClass, EDataType(0), true);
101  } else {
102  if (!addr) {
103  addr = new double();
104  fAddressesToFree.emplace_back((double *)addr);
105  }
106  chain->SetBranchAddress(colName, addr);
107  }
108  }
109  fChains[slot].reset(chain);
110 }
111 
112 void RRootDS::FinaliseSlot(unsigned int slot)
113 {
114  fChains[slot].reset(nullptr);
115 }
116 
117 std::vector<std::pair<ULong64_t, ULong64_t>> RRootDS::GetEntryRanges()
118 {
119  auto entryRanges(std::move(fEntryRanges)); // empty fEntryRanges
120  return entryRanges;
121 }
122 
123 bool RRootDS::SetEntry(unsigned int slot, ULong64_t entry)
124 {
125  fChains[slot]->GetEntry(entry);
126  return true;
127 }
128 
129 void RRootDS::SetNSlots(unsigned int nSlots)
130 {
131  R__ASSERT(0U == fNSlots && "Setting the number of slots even if the number of slots is different from zero.");
132 
133  fNSlots = nSlots;
134 
135  const auto nColumns = fListOfBranches.size();
136  // Initialise the entire set of addresses
137  fBranchAddresses.resize(nColumns, std::vector<void *>(fNSlots, nullptr));
138 
139  fChains.resize(fNSlots);
140 }
141 
142 void RRootDS::Initialise()
143 {
144  const auto nentries = fModelChain.GetEntries();
145  const auto chunkSize = nentries / fNSlots;
146  const auto reminder = 1U == fNSlots ? 0 : nentries % fNSlots;
147  auto start = 0UL;
148  auto end = 0UL;
149  for (auto i : ROOT::TSeqU(fNSlots)) {
150  start = end;
151  end += chunkSize;
152  fEntryRanges.emplace_back(start, end);
153  (void)i;
154  }
155  fEntryRanges.back().second += reminder;
156 }
157 
158 std::string RRootDS::GetLabel()
159 {
160  return "Root";
161 }
162 
163 RDataFrame MakeRootDataFrame(std::string_view treeName, std::string_view fileNameGlob)
164 {
165  ROOT::RDataFrame tdf(std::make_unique<RRootDS>(treeName, fileNameGlob));
166  return tdf;
167 }
168 
169 } // ns RDF
170 
171 } // ns ROOT