Logo ROOT  
Reference Guide
RNTupleView.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleView.hxx
2/// \ingroup NTuple ROOT7
3/// \author Jakob Blomer <jblomer@cern.ch>
4/// \date 2018-10-05
5/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
6/// is welcome!
7
8/*************************************************************************
9 * Copyright (C) 1995-2019, Rene Brun and Fons Rademakers. *
10 * All rights reserved. *
11 * *
12 * For the licensing terms see $ROOTSYS/LICENSE. *
13 * For the list of contributors see $ROOTSYS/README/CREDITS. *
14 *************************************************************************/
15
16#ifndef ROOT7_RNTupleView
17#define ROOT7_RNTupleView
18
19#include <ROOT/RField.hxx>
20#include <ROOT/RNTupleUtil.hxx>
21#include <ROOT/RStringView.hxx>
22
23#include <iterator>
24#include <memory>
25#include <type_traits>
26#include <utility>
27#include <unordered_map>
28
29namespace ROOT {
30namespace Experimental {
31
32
33// clang-format off
34/**
35\class ROOT::Experimental::RNTupleGlobalRange
36\ingroup NTuple
37\brief Used to loop over indexes (entries or collections) between start and end
38*/
39// clang-format on
41private:
44public:
45 class RIterator {
46 private:
48 public:
50 using iterator_category = std::forward_iterator_tag;
55
56 RIterator() = default;
57 explicit RIterator(NTupleSize_t index) : fIndex(index) {}
58 ~RIterator() = default;
59
60 iterator operator++(int) /* postfix */ { auto r = *this; fIndex++; return r; }
61 iterator& operator++() /* prefix */ { ++fIndex; return *this; }
63 pointer operator->() { return &fIndex; }
64 bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
65 bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
66 };
67
70 RIterator end() { return RIterator(fEnd); }
71};
72
73
74// clang-format off
75/**
76\class ROOT::Experimental::RNTupleClusterRange
77\ingroup NTuple
78\brief Used to loop over entries of collections in a single cluster
79*/
80// clang-format on
82private:
86public:
87 class RIterator {
88 private:
90 public:
92 using iterator_category = std::forward_iterator_tag;
97
98 RIterator() = default;
99 explicit RIterator(const RClusterIndex &index) : fIndex(index) {}
100 ~RIterator() = default;
101
102 iterator operator++(int) /* postfix */ { auto r = *this; fIndex++; return r; }
103 iterator& operator++() /* prefix */ { fIndex++; return *this; }
105 pointer operator->() { return &fIndex; }
106 bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
107 bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
108 };
109
111 : fClusterId(clusterId), fStart(start), fEnd(end) {}
114};
115
116
117namespace Internal {
118
119template <class FieldT>
121public:
122 using RSuccess = char;
123 struct RFailure { char x[2]; };
124
125 template<class C, typename ... ArgsT>
126 using MapOverloadT = decltype(std::declval<C>().Map(std::declval<ArgsT>() ...)) (C::*)(ArgsT ...);
127
128 template <class C> static RSuccess Test(MapOverloadT<C, NTupleSize_t>);
129 template <class C> static RFailure Test(...);
130
131public:
132 static constexpr bool value = sizeof(Test<FieldT>(0)) == sizeof(RSuccess);
133};
134
135} // namespace Internal
136
137
138// clang-format off
139/**
140\class ROOT::Experimental::RNTupleView
141\ingroup NTuple
142\brief An RNTupleView provides read-only access to a single field of the ntuple
143
144The view owns a field and its underlying columns in order to fill an ntuple value object with data. Data can be
145accessed by index. For top-level fields, the index refers to the entry number. Fields that are part of
146nested collections have global index numbers that are derived from their parent indexes.
147
148Fields of simple types with a Map() method will use that and thus expose zero-copy access.
149*/
150// clang-format on
151template <typename T>
154
156
157private:
158 /// fFieldId has fParent always set to null; views access nested fields without looking at the parent
160 /// Used as a Read() destination for fields that are not mappable
162
163public:
164
166 : fField(pageSource->GetDescriptor().GetFieldDescriptor(fieldId).GetFieldName()), fValue(fField.GenerateValue())
167 {
168 fField.SetOnDiskId(fieldId);
169 fField.ConnectPageSource(*pageSource);
170 for (auto &f : fField) {
171 auto subFieldId = pageSource->GetDescriptor().FindFieldId(f.GetName(), f.GetParent()->GetOnDiskId());
172 f.SetOnDiskId(subFieldId);
173 f.ConnectPageSource(*pageSource);
174 }
175 }
176
177 RNTupleView(const RNTupleView& other) = delete;
178 RNTupleView(RNTupleView&& other) = default;
179 RNTupleView& operator=(const RNTupleView& other) = delete;
180 RNTupleView& operator=(RNTupleView&& other) = default;
181 ~RNTupleView() { fField.DestroyValue(fValue); }
182
183 RNTupleGlobalRange GetFieldRange() const { return RNTupleGlobalRange(0, fField.GetNElements()); }
184
185 template <typename C = T>
186 typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C&>
187 operator()(NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
188
189 template <typename C = T>
190 typename std::enable_if_t<!Internal::IsMappable<FieldT>::value, const C&>
192 fField.Read(globalIndex, &fValue);
193 return *fValue.Get<T>();
194 }
195
196 template <typename C = T>
197 typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C&>
198 operator()(const RClusterIndex &clusterIndex) { return *fField.Map(clusterIndex); }
199
200 template <typename C = T>
201 typename std::enable_if_t<!Internal::IsMappable<FieldT>::value, const C&>
202 operator()(const RClusterIndex &clusterIndex) {
203 fField.Read(clusterIndex, &fValue);
204 return *fValue.Get<T>();
205 }
206
207 template <typename C = T>
208 typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C*>
209 MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
210 return fField.MapV(globalIndex, nItems);
211 }
212
213 template <typename C = T>
214 typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C*>
215 MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
216 return fField.MapV(clusterIndex, nItems);
217 }
218};
219
220
221// clang-format off
222/**
223\class ROOT::Experimental::RNTupleViewCollection
224\ingroup NTuple
225\brief A view for a collection, that can itself generate new ntuple views for its nested fields.
226*/
227// clang-format on
228class RNTupleViewCollection : public RNTupleView<ClusterSize_t> {
229 friend class RNTupleReader;
230
231private:
234
236 : RNTupleView<ClusterSize_t>(fieldId, source)
237 , fSource(source)
238 , fCollectionFieldId(fieldId)
239 {}
240
241public:
247
250 RClusterIndex collectionStart;
251 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
252 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
253 collectionStart.GetIndex() + size);
254 }
257 RClusterIndex collectionStart;
258 fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
259 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
260 collectionStart.GetIndex() + size);
261 }
262
263 /// Raises an exception if there is no field with the given name.
264 template <typename T>
266 auto fieldId = fSource->GetDescriptor().FindFieldId(fieldName, fCollectionFieldId);
267 if (fieldId == kInvalidDescriptorId) {
268 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in RNTuple '"
269 + fSource->GetDescriptor().GetName() + "'"
270 ));
271 }
272 return RNTupleView<T>(fieldId, fSource);
273 }
274 /// Raises an exception if there is no field with the given name.
276 auto fieldId = fSource->GetDescriptor().FindFieldId(fieldName, fCollectionFieldId);
277 if (fieldId == kInvalidDescriptorId) {
278 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in RNTuple '"
279 + fSource->GetDescriptor().GetName() + "'"
280 ));
281 }
282 return RNTupleViewCollection(fieldId, fSource);
283 }
284
287 RClusterIndex collectionStart;
288 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
289 return size;
290 }
293 RClusterIndex collectionStart;
294 fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
295 return size;
296 }
297};
298
299} // namespace Experimental
300} // namespace ROOT
301
302#endif
ROOT::R::TRInterface & r
Definition: Object.C:4
#define R__FAIL(msg)
Short-hand to return an RResult<T> in an error state; the RError is implicitly converted into RResult...
Definition: RError.hxx:291
#define f(i)
Definition: RSha256.hxx:104
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
Abstract interface to read data from an ntuple.
const RNTupleDescriptor & GetDescriptor() const
decltype(std::declval< C >().Map(std::declval< ArgsT >() ...))(C::*)(ArgsT ...) MapOverloadT
static RSuccess Test(MapOverloadT< C, NTupleSize_t >)
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
DescriptorId_t GetClusterId() const
ClusterSize_t::ValueType GetIndex() const
Base class for all ROOT issued exceptions.
Definition: RError.hxx:114
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Special help for offset fields.
Definition: RField.hxx:584
Classes with dictionaries that can be inspected by TClass.
Definition: RField.hxx:480
Used to loop over entries of collections in a single cluster.
Definition: RNTupleView.hxx:81
const ClusterSize_t::ValueType fStart
Definition: RNTupleView.hxx:84
RNTupleClusterRange(DescriptorId_t clusterId, ClusterSize_t::ValueType start, ClusterSize_t::ValueType end)
const ClusterSize_t::ValueType fEnd
Definition: RNTupleView.hxx:85
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
bool operator==(const iterator &rh) const
Definition: RNTupleView.hxx:64
bool operator!=(const iterator &rh) const
Definition: RNTupleView.hxx:65
Used to loop over indexes (entries or collections) between start and end.
Definition: RNTupleView.hxx:40
RNTupleGlobalRange(NTupleSize_t start, NTupleSize_t end)
Definition: RNTupleView.hxx:68
An RNTuple that is used to read data from storage.
Definition: RNTuple.hxx:102
A view for a collection, that can itself generate new ntuple views for its nested fields.
RNTupleClusterRange GetCollectionRange(const RClusterIndex &clusterIndex)
RNTupleViewCollection GetViewCollection(std::string_view fieldName)
Raises an exception if there is no field with the given name.
RNTupleViewCollection(RNTupleViewCollection &&other)=default
RNTupleViewCollection & operator=(RNTupleViewCollection &&other)=default
RNTupleViewCollection & operator=(const RNTupleViewCollection &other)=delete
RNTupleViewCollection(DescriptorId_t fieldId, Detail::RPageSource *source)
ClusterSize_t operator()(const RClusterIndex &clusterIndex)
ClusterSize_t operator()(NTupleSize_t globalIndex)
RNTupleView< T > GetView(std::string_view fieldName)
Raises an exception if there is no field with the given name.
RNTupleClusterRange GetCollectionRange(NTupleSize_t globalIndex)
RNTupleViewCollection(const RNTupleViewCollection &other)=delete
An RNTupleView provides read-only access to a single field of the ntuple.
Detail::RFieldValue fValue
Used as a Read() destination for fields that are not mappable.
RNTupleView & operator=(RNTupleView &&other)=default
std::enable_if_t< Internal::IsMappable< FieldT >::value, const C & > operator()(NTupleSize_t globalIndex)
std::enable_if_t<!Internal::IsMappable< FieldT >::value, const C & > operator()(const RClusterIndex &clusterIndex)
RNTupleView & operator=(const RNTupleView &other)=delete
RNTupleView(RNTupleView &&other)=default
RNTupleView(const RNTupleView &other)=delete
RNTupleView(DescriptorId_t fieldId, Detail::RPageSource *pageSource)
std::enable_if_t< Internal::IsMappable< FieldT >::value, const C & > operator()(const RClusterIndex &clusterIndex)
std::enable_if_t< Internal::IsMappable< FieldT >::value, const C * > MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
std::enable_if_t<!Internal::IsMappable< FieldT >::value, const C & > operator()(NTupleSize_t globalIndex)
FieldT fField
fFieldId has fParent always set to null; views access nested fields without looking at the parent
std::enable_if_t< Internal::IsMappable< FieldT >::value, const C * > MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems)
RNTupleGlobalRange GetFieldRange() const
basic_string_view< char > string_view
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Definition: RNTupleUtil.hxx:77
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr NTupleSize_t kInvalidNTupleIndex
Definition: RNTupleUtil.hxx:78
constexpr DescriptorId_t kInvalidDescriptorId
static double C[]
double T(double x)
Definition: ChebyshevPol.h:34
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...
Definition: RNTupleUtil.hxx:80