Logo ROOT   master
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 
29 namespace ROOT {
30 namespace 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
41 private:
44 public:
45  class RIterator : public std::iterator<std::forward_iterator_tag, NTupleSize_t> {
46  private:
49  public:
50  RIterator() = default;
51  explicit RIterator(NTupleSize_t index) : fIndex(index) {}
52  ~RIterator() = default;
53 
54  iterator operator++(int) /* postfix */ { auto r = *this; fIndex++; return r; }
55  iterator& operator++() /* prefix */ { ++fIndex; return *this; }
56  reference operator* () { return fIndex; }
57  pointer operator->() { return &fIndex; }
58  bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
59  bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
60  };
61 
64  RIterator end() { return RIterator(fEnd); }
65 };
66 
67 
68 // clang-format off
69 /**
70 \class ROOT::Experimental::RNTupleClusterRange
71 \ingroup NTuple
72 \brief Used to loop over entries of collections in a single cluster
73 */
74 // clang-format on
76 private:
80 public:
81  class RIterator : public std::iterator<std::forward_iterator_tag, RClusterIndex> {
82  private:
85  public:
86  RIterator() = default;
87  explicit RIterator(const RClusterIndex &index) : fIndex(index) {}
88  ~RIterator() = default;
89 
90  iterator operator++(int) /* postfix */ { auto r = *this; fIndex++; return r; }
91  iterator& operator++() /* prefix */ { fIndex++; return *this; }
92  reference operator* () { return fIndex; }
93  pointer operator->() { return &fIndex; }
94  bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
95  bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
96  };
97 
99  : fClusterId(clusterId), fStart(start), fEnd(end) {}
102 };
103 
104 
105 namespace Internal {
106 
107 template <class FieldT>
108 class IsMappable {
109 public:
110  using RSuccess = char;
111  struct RFailure { char x[2]; };
112 
113  template<class C, typename ... ArgsT>
114  using MapOverloadT = decltype(std::declval<C>().Map(std::declval<ArgsT>() ...)) (C::*)(ArgsT ...);
115 
116  template <class C> static RSuccess Test(MapOverloadT<C, NTupleSize_t>);
117  template <class C> static RFailure Test(...);
118 
119 public:
120  static constexpr bool value = sizeof(Test<FieldT>(0)) == sizeof(RSuccess);
121 };
122 
123 } // namespace Internal
124 
125 
126 // clang-format off
127 /**
128 \class ROOT::Experimental::RNTupleView
129 \ingroup NTuple
130 \brief An RNTupleView provides read-only access to a single field of the ntuple
131 
132 The view owns a field and its underlying columns in order to fill an ntuple value object with data. Data can be
133 accessed by index. For top level fields, the index refers to the entry number. Fields that are part of
134 nested collections have global index numbers that are derived from their parent indexes.
135 
136 Fields of simple types with a Map() method will use that and thus expose zero-copy access.
137 */
138 // clang-format on
139 template <typename T>
140 class RNTupleView {
141  friend class RNTupleReader;
142  friend class RNTupleViewCollection;
143 
144  using FieldT = RField<T>;
145 
146 private:
147  /// fFieldId has fParent always set to null; views access nested fields without looking at the parent
149  /// Used as a Read() destination for fields that are not mappable
151 
153  : fField(pageSource->GetDescriptor().GetFieldDescriptor(fieldId).GetFieldName()), fValue(fField.GenerateValue())
154  {
155  Detail::RFieldFuse::Connect(fieldId, *pageSource, fField);
156  std::unordered_map<const Detail::RFieldBase *, DescriptorId_t> field2Id;
157  field2Id[&fField] = fieldId;
158  for (auto &f : fField) {
159  auto subFieldId = pageSource->GetDescriptor().FindFieldId(f.GetName(), field2Id[f.GetParent()]);
160  Detail::RFieldFuse::Connect(subFieldId, *pageSource, f);
161  field2Id[&f] = subFieldId;
162  }
163  }
164 
165 public:
166  RNTupleView(const RNTupleView& other) = delete;
167  RNTupleView(RNTupleView&& other) = default;
168  RNTupleView& operator=(const RNTupleView& other) = delete;
169  RNTupleView& operator=(RNTupleView&& other) = default;
171 
173 
174  template <typename C = T>
175  typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C&>
176  operator()(NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
177 
178  template <typename C = T>
179  typename std::enable_if_t<!Internal::IsMappable<FieldT>::value, const C&>
180  operator()(NTupleSize_t globalIndex) {
181  fField.Read(globalIndex, &fValue);
182  return *fValue.Get<T>();
183  }
184 
185  template <typename C = T>
186  typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C&>
187  operator()(const RClusterIndex &clusterIndex) { return *fField.Map(clusterIndex); }
188 
189  template <typename C = T>
190  typename std::enable_if_t<!Internal::IsMappable<FieldT>::value, const C&>
191  operator()(const RClusterIndex &clusterIndex) {
192  fField.Read(clusterIndex, &fValue);
193  return *fValue.Get<T>();
194  }
195 };
196 
197 
198 // clang-format off
199 /**
200 \class ROOT::Experimental::RNTupleViewCollection
201 \ingroup NTuple
202 \brief A view for a collection, that can itself generate new ntuple views for its nested fields.
203 */
204 // clang-format on
205 class RNTupleViewCollection : public RNTupleView<ClusterSize_t> {
206  friend class RNTupleReader;
207 
208 private:
211 
213  : RNTupleView<ClusterSize_t>(fieldId, source)
214  , fSource(source)
215  , fCollectionFieldId(fieldId)
216  {}
217 
218 public:
219  RNTupleViewCollection(const RNTupleViewCollection& other) = delete;
220  RNTupleViewCollection(RNTupleViewCollection&& other) = default;
221  RNTupleViewCollection& operator=(const RNTupleViewCollection& other) = delete;
223  ~RNTupleViewCollection() = default;
224 
226  ClusterSize_t size;
227  RClusterIndex collectionStart;
228  fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
229  return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
230  collectionStart.GetIndex() + size);
231  }
233  ClusterSize_t size;
234  RClusterIndex collectionStart;
235  fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
236  return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
237  collectionStart.GetIndex() + size);
238  }
239 
240  template <typename T>
241  RNTupleView<T> GetView(std::string_view fieldName) {
242  auto fieldId = fSource->GetDescriptor().FindFieldId(fieldName, fCollectionFieldId);
243  return RNTupleView<T>(fieldId, fSource);
244  }
245  RNTupleViewCollection GetViewCollection(std::string_view fieldName) {
246  auto fieldId = fSource->GetDescriptor().FindFieldId(fieldName, fCollectionFieldId);
247  return RNTupleViewCollection(fieldId, fSource);
248  }
249 
251  ClusterSize_t size;
252  RClusterIndex collectionStart;
253  fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
254  return size;
255  }
256  ClusterSize_t operator()(const RClusterIndex &clusterIndex) {
257  ClusterSize_t size;
258  RClusterIndex collectionStart;
259  fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
260  return size;
261  }
262 };
263 
264 } // namespace Experimental
265 } // namespace ROOT
266 
267 #endif
decltype(std::declval< C >().Map(std::declval< ArgsT >() ...))(C::*)(ArgsT ...) MapOverloadT
An RNTupleView provides read-only access to a single field of the ntuple
An RNTuple that is used to read data from storage
Definition: RNTuple.hxx:73
Returns the available number of logical cores.
Definition: StringConv.hxx:21
NTupleSize_t GetNElements() const
Definition: RField.hxx:215
double T(double x)
Definition: ChebyshevPol.h:34
ClusterSize_t operator()(const RClusterIndex &clusterIndex)
RNTupleViewCollection(DescriptorId_t fieldId, Detail::RPageSource *source)
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
Definition: RNTupleUtil.hxx:78
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
Definition: RNTupleUtil.hxx:42
std::enable_if_t< Internal::IsMappable< FieldT >::value, const C & > operator()(const RClusterIndex &clusterIndex)
#define f(i)
Definition: RSha256.hxx:104
Abstract interface to read data from an ntuple
ClusterSize_t operator()(NTupleSize_t globalIndex)
bool operator==(const iterator &rh) const
Definition: RNTupleView.hxx:58
Used to loop over entries of collections in a single cluster
Definition: RNTupleView.hxx:75
Wrap the 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...
Definition: RNTupleUtil.hxx:45
RNTupleView(DescriptorId_t fieldId, Detail::RPageSource *pageSource)
Detail::RFieldValue fValue
Used as a Read() destination for fields that are not mappable.
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
static double C[]
void Read(NTupleSize_t globalIndex, RFieldValue *value)
Populate a single value with data from the tree, which needs to be of the fitting type...
Definition: RField.hxx:187
ROOT::R::TRInterface & r
Definition: Object.C:4
std::enable_if_t< Internal::IsMappable< FieldT >::value, const C & > operator()(NTupleSize_t globalIndex)
RNTupleViewCollection GetViewCollection(std::string_view fieldName)
std::enable_if_t<!Internal::IsMappable< FieldT >::value, const C & > operator()(const RClusterIndex &clusterIndex)
RNTupleView & operator=(const RNTupleView &other)=delete
FieldT fField
fFieldId has fParent always set to null; views access nested fields without looking at the parent ...
RNTupleGlobalRange(NTupleSize_t start, NTupleSize_t end)
Definition: RNTupleView.hxx:62
const RNTupleDescriptor & GetDescriptor() const
std::enable_if_t<!Internal::IsMappable< FieldT >::value, const C & > operator()(NTupleSize_t globalIndex)
Template specializations for concrete C++ types.
Definition: RField.hxx:458
RNTupleGlobalRange GetFieldRange() const
Used to loop over indexes (entries or collections) between start and end
Definition: RNTupleView.hxx:40
const ClusterSize_t::ValueType fEnd
Definition: RNTupleView.hxx:79
A view for a collection, that can itself generate new ntuple views for its nested fields...
RNTupleView< T > GetView(std::string_view fieldName)
auto Map(Args &&... args) -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...), std::make_index_sequence< sizeof...(args) - 1 >()))
Create new collection applying a callable to the elements of the input collection.
Definition: RVec.hxx:909
DescriptorId_t GetClusterId() const
RNTupleViewCollection & operator=(const RNTupleViewCollection &other)=delete
static RSuccess Test(MapOverloadT< C, NTupleSize_t >)
bool operator!=(const iterator &rh) const
Definition: RNTupleView.hxx:59
ClusterSize_t::ValueType GetIndex() const
constexpr NTupleSize_t kInvalidNTupleIndex
Definition: RNTupleUtil.hxx:43
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Special help for offset fields.
Definition: RField.hxx:493
RNTupleClusterRange GetCollectionRange(const RClusterIndex &clusterIndex)
RNTupleClusterRange GetCollectionRange(NTupleSize_t globalIndex)
Addresses a column element or field item relative to a particular cluster, instead of a global NTuple...
Definition: RNTupleUtil.hxx:82
RNTupleClusterRange(DescriptorId_t clusterId, ClusterSize_t::ValueType start, ClusterSize_t::ValueType end)
Definition: RNTupleView.hxx:98
const ClusterSize_t::ValueType fStart
Definition: RNTupleView.hxx:78
void DestroyValue(const Detail::RFieldValue &value, bool dtorOnly=false) final
Releases the resources acquired during GenerateValue (memory and constructor) This implementation wor...
Definition: RField.cxx:546
static void Connect(DescriptorId_t fieldId, RPageStorage &pageStorage, RFieldBase &field)
Definition: RField.cxx:76