Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RTreeColumnReader.hxx
Go to the documentation of this file.
1// Author: Enrico Guiraud CERN 09/2020
2// Author: Vincenzo Eduardo Padulano CERN 09/2024
3
4/*************************************************************************
5 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#ifndef ROOT_RDF_RTREECOLUMNREADER
13#define ROOT_RDF_RTREECOLUMNREADER
14
15#include "RColumnReaderBase.hxx"
16#include <ROOT/RVec.hxx>
17#include <Rtypes.h> // Long64_t, R__CLING_PTRCHECK
18#include <TTreeReader.h>
19#include <TTreeReaderValue.h>
20#include <TTreeReaderArray.h>
21
22#include <array>
23#include <memory>
24#include <string>
25
26namespace ROOT {
27namespace Internal {
28namespace RDF {
29
30/// RTreeColumnReader specialization for TTree values read via TTreeReaderValues
31template <typename T>
32class R__CLING_PTRCHECK(off) RTreeColumnReader final : public ROOT::Detail::RDF::RColumnReaderBase {
33 std::unique_ptr<TTreeReaderValue<T>> fTreeValue;
34
35 void *GetImpl(Long64_t) final { return fTreeValue->Get(); }
36public:
37 /// Construct the RTreeColumnReader. Actual initialization is performed lazily by the Init method.
38 RTreeColumnReader(TTreeReader &r, const std::string &colName)
39 : fTreeValue(std::make_unique<TTreeReaderValue<T>>(r, colName.c_str()))
40 {
41 }
42};
43
44class R__CLING_PTRCHECK(off) RTreeOpaqueColumnReader final : public ROOT::Detail::RDF::RColumnReaderBase {
45 std::unique_ptr<ROOT::Internal::TTreeReaderOpaqueValue> fTreeValue;
46
47 void *GetImpl(Long64_t) final { return fTreeValue->GetAddress(); }
48
49public:
50 /// Construct the RTreeColumnReader. Actual initialization is performed lazily by the Init method.
51 RTreeOpaqueColumnReader(TTreeReader &r, const std::string &colName)
52 : fTreeValue(std::make_unique<ROOT::Internal::TTreeReaderOpaqueValue>(r, colName.c_str()))
53 {
54 }
55};
56
57/// RTreeColumnReader specialization for TTree values read via TTreeReaderArrays.
58///
59/// TTreeReaderArrays are used whenever the RDF column type is RVec<T>.
60template <typename T>
61class R__CLING_PTRCHECK(off) RTreeColumnReader<RVec<T>> final : public ROOT::Detail::RDF::RColumnReaderBase {
62 std::unique_ptr<TTreeReaderArray<T>> fTreeArray;
63
64 /// Enumerator for the memory layout of the branch
65 enum class EStorageType : char { kContiguous, kUnknown, kSparse };
66
67 /// We return a reference to this RVec to clients, to guarantee a stable address and contiguous memory layout.
69
70 /// Signal whether we ever checked that the branch we are reading with a TTreeReaderArray stores array elements
71 /// in contiguous memory.
72 EStorageType fStorageType = EStorageType::kUnknown;
73 Long64_t fLastEntry = -1;
74
75 /// Whether we already printed a warning about performing a copy of the TTreeReaderArray contents
76 bool fCopyWarningPrinted = false;
77
78 void *GetImpl(Long64_t entry) final
79 {
80 if (entry == fLastEntry)
81 return &fRVec; // we already pointed our fRVec to the right address
82
83 auto &readerArray = *fTreeArray;
84 // We only use TTreeReaderArrays to read columns that users flagged as type `RVec`, so we need to check
85 // that the branch stores the array as contiguous memory that we can actually wrap in an `RVec`.
86 // Currently we need the first entry to have been loaded to perform the check
87 // TODO Move check to constructor once ROOT-10823 is fixed and TTreeReaderArray itself exposes this information
88 const auto readerArraySize = readerArray.GetSize();
89
90 // The reader could not read an array, signal this back to the node requesting the value
92 return nullptr;
93
94 if (EStorageType::kUnknown == fStorageType && readerArraySize > 1) {
95 // We can decide since the array is long enough
96 fStorageType = EStorageType::kContiguous;
97 for (auto i = 0u; i < readerArraySize - 1; ++i) {
98 if ((char *)&readerArray[i + 1] - (char *)&readerArray[i] != sizeof(T)) {
99 fStorageType = EStorageType::kSparse;
100 break;
101 }
102 }
103 }
104
105 if (EStorageType::kContiguous == fStorageType ||
106 (EStorageType::kUnknown == fStorageType && readerArray.GetSize() < 2)) {
107 if (readerArraySize > 0) {
108 // trigger loading of the contents of the TTreeReaderArray
109 // the address of the first element in the reader array is not necessarily equal to
110 // the address returned by the GetAddress method
111 auto readerArrayAddr = &readerArray.At(0);
112 RVec<T> rvec(readerArrayAddr, readerArraySize);
113 swap(fRVec, rvec);
114 } else {
115 RVec<T> emptyVec{};
116 swap(fRVec, emptyVec);
117 }
118 } else {
119 // The storage is not contiguous or we don't know yet: we cannot but copy into the rvec
120#ifndef NDEBUG
121 if (!fCopyWarningPrinted) {
122 Warning("RTreeColumnReader::Get",
123 "Branch %s hangs from a non-split branch. A copy is being performed in order "
124 "to properly read the content.",
125 readerArray.GetBranchName());
126 fCopyWarningPrinted = true;
127 }
128#else
129 (void)fCopyWarningPrinted;
130#endif
131 if (readerArraySize > 0) {
132 RVec<T> rvec(readerArray.begin(), readerArray.end());
133 swap(fRVec, rvec);
134 } else {
135 RVec<T> emptyVec{};
136 swap(fRVec, emptyVec);
137 }
138 }
139 fLastEntry = entry;
140 return &fRVec;
141 }
142
143public:
144 RTreeColumnReader(TTreeReader &r, const std::string &colName)
145 : fTreeArray(std::make_unique<TTreeReaderArray<T>>(r, colName.c_str()))
146 {
147 }
148};
149
150/// RTreeColumnReader specialization for arrays of boolean values read via TTreeReaderArrays.
151///
152/// TTreeReaderArray<bool> is used whenever the RDF column type is RVec<bool>.
153template <>
154class R__CLING_PTRCHECK(off) RTreeColumnReader<RVec<bool>> final : public ROOT::Detail::RDF::RColumnReaderBase {
155
156 std::unique_ptr<TTreeReaderArray<bool>> fTreeArray;
157
158 /// We return a reference to this RVec to clients, to guarantee a stable address and contiguous memory layout
160
161 // We always copy the contents of TTreeReaderArray<bool> into an RVec<bool> (never take a view into the memory
162 // buffer) because the underlying memory buffer might be the one of a std::vector<bool>, which is not a contiguous
163 // slab of bool values.
164 // Note that this also penalizes the case in which the column type is actually bool[], but the possible performance
165 // gains in this edge case is probably not worth the extra complication required to differentiate the two cases.
166 void *GetImpl(Long64_t) final
167 {
168 auto &readerArray = *fTreeArray;
169 const auto readerArraySize = readerArray.GetSize();
170 if (readerArraySize > 0) {
171 // always perform a copy
172 RVec<bool> rvec(readerArray.begin(), readerArray.end());
173 swap(fRVec, rvec);
174 } else {
175 RVec<bool> emptyVec{};
176 swap(fRVec, emptyVec);
177 }
178 return &fRVec;
179 }
180
181public:
182 RTreeColumnReader(TTreeReader &r, const std::string &colName)
183 : fTreeArray(std::make_unique<TTreeReaderArray<bool>>(r, colName.c_str()))
184 {
185 }
186};
187
188/// RTreeColumnReader specialization for TTree values read via TTreeReaderArrays.
189///
190/// This specialization is used when the requested type for reading is std::array
191template <typename T, std::size_t N>
192class R__CLING_PTRCHECK(off) RTreeColumnReader<std::array<T, N>> final : public ROOT::Detail::RDF::RColumnReaderBase {
193 std::unique_ptr<TTreeReaderArray<T>> fTreeArray;
194
195 /// We return a reference to this RVec to clients, to guarantee a stable address and contiguous memory layout
196 RVec<T> fArray;
197
198 Long64_t fLastEntry = -1;
199
200 void *GetImpl(Long64_t entry) final
201 {
202 if (entry == fLastEntry)
203 return fArray.data();
204
205 // This is a non-owning view on the contents of the TTreeReaderArray
206 RVec<T> view{&fTreeArray->At(0), fTreeArray->GetSize()};
207 swap(fArray, view);
208
209 fLastEntry = entry;
210 // The data member of this class is an RVec, to avoid an extra copy
211 // but we need to return the array buffer as the reader expects
212 // a std::array
213 return fArray.data();
214 }
215
216public:
217 RTreeColumnReader(TTreeReader &r, const std::string &colName)
218 : fTreeArray(std::make_unique<TTreeReaderArray<T>>(r, colName.c_str()))
219 {
220 }
221};
222
223} // namespace RDF
224} // namespace Internal
225} // namespace ROOT
226
227#endif
#define R__unlikely(expr)
Definition RConfig.hxx:586
long long Long64_t
Definition RtypesCore.h:69
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:229
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t r
@ kUnknown
Definition TStructNode.h:19
std::unique_ptr< TTreeReaderArray< T > > fTreeArray
RTreeColumnReader(TTreeReader &r, const std::string &colName)
EStorageType
Enumerator for the memory layout of the branch.
RVec< T > fRVec
We return a reference to this RVec to clients, to guarantee a stable address and contiguous memory la...
RVec< bool > fRVec
We return a reference to this RVec to clients, to guarantee a stable address and contiguous memory la...
std::unique_ptr< TTreeReaderArray< bool > > fTreeArray
RTreeColumnReader(TTreeReader &r, const std::string &colName)
RTreeColumnReader specialization for TTree values read via TTreeReaderValues.
RTreeColumnReader(TTreeReader &r, const std::string &colName)
Construct the RTreeColumnReader. Actual initialization is performed lazily by the Init method.
std::unique_ptr< TTreeReaderValue< T > > fTreeValue
std::unique_ptr< ROOT::Internal::TTreeReaderOpaqueValue > fTreeValue
RTreeOpaqueColumnReader(TTreeReader &r, const std::string &colName)
Construct the RTreeColumnReader. Actual initialization is performed lazily by the Init method.
Read a value in a branch without knowledge of its type.
pointer data() noexcept
Return a pointer to the vector's buffer, even if empty().
Definition RVec.hxx:280
A "std::vector"-like collection of values implementing handy operation to analyse them.
Definition RVec.hxx:1529
An interface for reading collections stored in ROOT columnar datasets.
An interface for reading values stored in ROOT columnar datasets.
A simple, robust and fast interface to read values from ROOT columnar datasets such as TTree,...
Definition TTreeReader.h:46
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...