Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
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 <utility>
26 #include <unordered_map>
27 
28 namespace ROOT {
29 namespace Experimental {
30 
31 
32 // clang-format off
33 /**
34 \class ROOT::Experimental::RNTupleGlobalRange
35 \ingroup NTuple
36 \brief Used to loop over indexes (entries or collections) between start and end
37 */
38 // clang-format on
39 class RNTupleGlobalRange {
40 private:
41  const NTupleSize_t fStart;
42  const NTupleSize_t fEnd;
43 public:
44  class RIterator : public std::iterator<std::forward_iterator_tag, NTupleSize_t> {
45  private:
46  using iterator = RIterator;
47  NTupleSize_t fIndex = kInvalidNTupleIndex;
48  public:
49  RIterator() = default;
50  explicit RIterator(NTupleSize_t index) : fIndex(index) {}
51  ~RIterator() = default;
52 
53  iterator operator++(int) /* postfix */ { auto r = *this; fIndex++; return r; }
54  iterator& operator++() /* prefix */ { ++fIndex; return *this; }
55  reference operator* () { return fIndex; }
56  pointer operator->() { return &fIndex; }
57  bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
58  bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
59  };
60 
61  RNTupleGlobalRange(NTupleSize_t start, NTupleSize_t end) : fStart(start), fEnd(end) {}
62  RIterator begin() { return RIterator(fStart); }
63  RIterator end() { return RIterator(fEnd); }
64 };
65 
66 
67 // clang-format off
68 /**
69 \class ROOT::Experimental::RNTupleClusterRange
70 \ingroup NTuple
71 \brief Used to loop over entries of collections in a single cluster
72 */
73 // clang-format on
74 class RNTupleClusterRange {
75 private:
76  const DescriptorId_t fClusterId;
77  const ClusterSize_t::ValueType fStart;
78  const ClusterSize_t::ValueType fEnd;
79 public:
80  class RIterator : public std::iterator<std::forward_iterator_tag, RClusterIndex> {
81  private:
82  using iterator = RIterator;
83  RClusterIndex fIndex;
84  public:
85  RIterator() = default;
86  explicit RIterator(const RClusterIndex &index) : fIndex(index) {}
87  ~RIterator() = default;
88 
89  iterator operator++(int) /* postfix */ { auto r = *this; fIndex++; return r; }
90  iterator& operator++() /* prefix */ { fIndex++; return *this; }
91  reference operator* () { return fIndex; }
92  pointer operator->() { return &fIndex; }
93  bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
94  bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
95  };
96 
97  RNTupleClusterRange(DescriptorId_t clusterId, ClusterSize_t::ValueType start, ClusterSize_t::ValueType end)
98  : fClusterId(clusterId), fStart(start), fEnd(end) {}
99  RIterator begin() { return RIterator(RClusterIndex(fClusterId, fStart)); }
100  RIterator end() { return RIterator(RClusterIndex(fClusterId, fEnd)); }
101 };
102 
103 
104 // clang-format off
105 /**
106 \class ROOT::Experimental::RNTupleView
107 \ingroup NTuple
108 \brief An RNTupleView provides read-only access to a single field of the ntuple
109 
110 (NB(jblomer): The ntuple view is very close to TTreeReader. Do we simply want to teach TTreeReader to deal with
111 RNTuple?)
112 
113 The view owns a field and its underlying columns in order to fill an ntuple value object with data. Data can be
114 accessed by index. For top level fields, the index refers to the entry number. Fields that are part of
115 nested collections have global index numbers that are derived from their parent indexes.
116 
117 The RNTupleView object is an iterable. That means, all field values in the tree can be sequentially read from begin()
118 to end().
119 
120 For simple types, template specializations let the reading become a pure mapping into a page buffer.
121 */
122 // clang-format on
123 template <typename T>
124 class RNTupleView {
125  friend class RNTupleReader;
126  friend class RNTupleViewCollection;
127 
128 protected:
129  /**
130  * fFieldId has fParent always set to null; views access nested fields without looking at the parent
131  */
132  RField<T> fField;
133  Detail::RFieldValue fValue;
134 
135  RNTupleView(DescriptorId_t fieldId, Detail::RPageSource* pageSource)
136  : fField(pageSource->GetDescriptor().GetFieldDescriptor(fieldId).GetFieldName()), fValue(fField.GenerateValue())
137  {
138  Detail::RFieldFuse::Connect(fieldId, *pageSource, fField);
139  std::unordered_map<const Detail::RFieldBase *, DescriptorId_t> field2Id;
140  field2Id[&fField] = fieldId;
141  for (auto &f : fField) {
142  auto subFieldId = pageSource->GetDescriptor().FindFieldId(f.GetName(), field2Id[f.GetParent()]);
143  Detail::RFieldFuse::Connect(subFieldId, *pageSource, f);
144  field2Id[&f] = subFieldId;
145  }
146  }
147 
148 public:
149  RNTupleView(const RNTupleView& other) = delete;
150  RNTupleView(RNTupleView&& other) = default;
151  RNTupleView& operator=(const RNTupleView& other) = delete;
152  RNTupleView& operator=(RNTupleView&& other) = default;
153  ~RNTupleView() { fField.DestroyValue(fValue); }
154 
155  const T& operator()(NTupleSize_t globalIndex) {
156  fField.Read(globalIndex, &fValue);
157  return *fValue.Get<T>();
158  }
159 
160  const T& operator()(const RClusterIndex &clusterIndex) {
161  fField.Read(clusterIndex, &fValue);
162  return *fValue.Get<T>();
163  }
164 };
165 
166 // Template specializations in order to directly map simple types into the page pool
167 
168 template <>
169 class RNTupleView<float> {
170  friend class RNTupleReader;
171  friend class RNTupleViewCollection;
172 
173 protected:
174  RField<float> fField;
175  RNTupleView(DescriptorId_t fieldId, Detail::RPageSource* pageSource)
176  : fField(pageSource->GetDescriptor().GetFieldDescriptor(fieldId).GetFieldName())
177  {
178  Detail::RFieldFuse::Connect(fieldId, *pageSource, fField);
179  }
180 
181 public:
182  RNTupleView(const RNTupleView& other) = delete;
183  RNTupleView(RNTupleView&& other) = default;
184  RNTupleView& operator=(const RNTupleView& other) = delete;
185  RNTupleView& operator=(RNTupleView&& other) = default;
186  ~RNTupleView() = default;
187 
188  float operator()(NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
189  float operator()(const RClusterIndex &clusterIndex) { return *fField.Map(clusterIndex); }
190 };
191 
192 
193 template <>
194 class RNTupleView<double> {
195  friend class RNTupleReader;
196  friend class RNTupleViewCollection;
197 
198 protected:
199  RField<double> fField;
200  RNTupleView(DescriptorId_t fieldId, Detail::RPageSource* pageSource)
201  : fField(pageSource->GetDescriptor().GetFieldDescriptor(fieldId).GetFieldName())
202  {
203  Detail::RFieldFuse::Connect(fieldId, *pageSource, fField);
204  }
205 
206 public:
207  RNTupleView(const RNTupleView& other) = delete;
208  RNTupleView(RNTupleView&& other) = default;
209  RNTupleView& operator=(const RNTupleView& other) = delete;
210  RNTupleView& operator=(RNTupleView&& other) = default;
211  ~RNTupleView() = default;
212 
213  double operator()(NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
214  double operator()(const RClusterIndex &clusterIndex) { return *fField.Map(clusterIndex); }
215 };
216 
217 
218 template <>
219 class RNTupleView<std::int32_t> {
220  friend class RNTupleReader;
221  friend class RNTupleViewCollection;
222 
223 protected:
224  RField<std::int32_t> fField;
225  RNTupleView(DescriptorId_t fieldId, Detail::RPageSource* pageSource)
226  : fField(pageSource->GetDescriptor().GetFieldDescriptor(fieldId).GetFieldName())
227  {
228  Detail::RFieldFuse::Connect(fieldId, *pageSource, fField);
229  }
230 
231 public:
232  RNTupleView(const RNTupleView& other) = delete;
233  RNTupleView(RNTupleView&& other) = default;
234  RNTupleView& operator=(const RNTupleView& other) = delete;
235  RNTupleView& operator=(RNTupleView&& other) = default;
236  ~RNTupleView() = default;
237 
238  std::int32_t operator()(NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
239  std::int32_t operator()(const RClusterIndex &clusterIndex) { return *fField.Map(clusterIndex); }
240 };
241 
242 template <>
243 class RNTupleView<ClusterSize_t> {
244  friend class RNTupleReader;
245  friend class RNTupleViewCollection;
246 
247 protected:
248  RField<ClusterSize_t> fField;
249  RNTupleView(DescriptorId_t fieldId, Detail::RPageSource* pageSource)
250  : fField(pageSource->GetDescriptor().GetFieldDescriptor(fieldId).GetFieldName())
251  {
252  Detail::RFieldFuse::Connect(fieldId, *pageSource, fField);
253  }
254 
255 public:
256  RNTupleView(const RNTupleView& other) = delete;
257  RNTupleView(RNTupleView&& other) = default;
258  RNTupleView& operator=(const RNTupleView& other) = delete;
259  RNTupleView& operator=(RNTupleView&& other) = default;
260  ~RNTupleView() = default;
261 
262  ClusterSize_t operator()(NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
263  ClusterSize_t operator()(const RClusterIndex &clusterIndex) { return *fField.Map(clusterIndex); }
264 };
265 
266 
267 // clang-format off
268 /**
269 \class ROOT::Experimental::RNTupleViewCollection
270 \ingroup NTuple
271 \brief A view for a collection, that can itself generate new ntuple views for its nested fields.
272 */
273 // clang-format on
274 class RNTupleViewCollection : public RNTupleView<ClusterSize_t> {
275  friend class RNTupleReader;
276 
277 private:
278  Detail::RPageSource* fSource;
279  DescriptorId_t fCollectionFieldId;
280 
281  RNTupleViewCollection(DescriptorId_t fieldId, Detail::RPageSource* source)
282  : RNTupleView<ClusterSize_t>(fieldId, source)
283  , fSource(source)
284  , fCollectionFieldId(fieldId)
285  {}
286 
287 public:
288  RNTupleViewCollection(const RNTupleViewCollection& other) = delete;
289  RNTupleViewCollection(RNTupleViewCollection&& other) = default;
290  RNTupleViewCollection& operator=(const RNTupleViewCollection& other) = delete;
291  RNTupleViewCollection& operator=(RNTupleViewCollection&& other) = default;
292  ~RNTupleViewCollection() = default;
293 
294  RNTupleClusterRange GetViewRange(NTupleSize_t globalIndex) {
295  ClusterSize_t size;
296  RClusterIndex collectionStart;
297  fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
298  return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
299  collectionStart.GetIndex() + size);
300  }
301  RNTupleClusterRange GetViewRange(const RClusterIndex &clusterIndex) {
302  ClusterSize_t size;
303  RClusterIndex collectionStart;
304  fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
305  return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
306  collectionStart.GetIndex() + size);
307  }
308 
309  template <typename T>
310  RNTupleView<T> GetView(std::string_view fieldName) {
311  auto fieldId = fSource->GetDescriptor().FindFieldId(fieldName, fCollectionFieldId);
312  return RNTupleView<T>(fieldId, fSource);
313  }
314  RNTupleViewCollection GetViewCollection(std::string_view fieldName) {
315  auto fieldId = fSource->GetDescriptor().FindFieldId(fieldName, fCollectionFieldId);
316  return RNTupleViewCollection(fieldId, fSource);
317  }
318 
319  ClusterSize_t operator()(NTupleSize_t globalIndex) {
320  ClusterSize_t size;
321  RClusterIndex collectionStart;
322  fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
323  return size;
324  }
325  ClusterSize_t operator()(const RClusterIndex &clusterIndex) {
326  ClusterSize_t size;
327  RClusterIndex collectionStart;
328  fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
329  return size;
330  }
331 };
332 
333 } // namespace Experimental
334 } // namespace ROOT
335 
336 #endif