Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
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;
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// TODO(bgruber): convert this trait into a requires clause in C++20
119template <typename FieldT, typename SFINAE = void>
120inline constexpr bool isMappable = false;
121
122template <typename FieldT>
123inline constexpr bool isMappable<FieldT, std::void_t<decltype(std::declval<FieldT>().Map(NTupleSize_t{}))>> = true;
124} // namespace Internal
125
126
127// clang-format off
128/**
129\class ROOT::Experimental::RNTupleView
130\ingroup NTuple
131\brief An RNTupleView provides read-only access to a single field of the ntuple
132
133The view owns a field and its underlying columns in order to fill an ntuple value object with data. Data can be
134accessed by index. For top-level fields, the index refers to the entry number. Fields that are part of
135nested collections have global index numbers that are derived from their parent indexes.
136
137Fields of simple types with a Map() method will use that and thus expose zero-copy access.
138*/
139// clang-format on
140template <typename T>
143
145
146private:
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
152public:
153 using FieldTypeT = T;
154
156 : fField(pageSource->GetSharedDescriptorGuard()->GetFieldDescriptor(fieldId).GetFieldName()),
157 fValue(fField.GenerateValue())
158 {
159 fField.SetOnDiskId(fieldId);
160 fField.ConnectPageSource(*pageSource);
161 if ((fField.GetTraits() & Detail::RFieldBase::kTraitMappable) && fField.HasReadCallbacks())
162 throw RException(R__FAIL("view disallowed on field with mappable type and read callback"));
163 for (auto &f : fField) {
164 auto subFieldId =
165 pageSource->GetSharedDescriptorGuard()->FindFieldId(f.GetName(), f.GetParent()->GetOnDiskId());
166 f.SetOnDiskId(subFieldId);
167 f.ConnectPageSource(*pageSource);
168 }
169 }
170
171 RNTupleView(const RNTupleView& other) = delete;
172 RNTupleView(RNTupleView&& other) = default;
173 RNTupleView& operator=(const RNTupleView& other) = delete;
174 RNTupleView& operator=(RNTupleView&& other) = default;
175 ~RNTupleView() = default;
176
177 RNTupleGlobalRange GetFieldRange() const { return RNTupleGlobalRange(0, fField.GetNElements()); }
178
179 const T &operator()(NTupleSize_t globalIndex)
180 {
181 if constexpr (Internal::isMappable<FieldT>)
182 return *fField.Map(globalIndex);
183 else {
184 fValue.Read(globalIndex);
185 return *fValue.Get<T>();
186 }
187 }
188
189 const T &operator()(const RClusterIndex &clusterIndex)
190 {
191 if constexpr (Internal::isMappable<FieldT>)
192 return *fField.Map(clusterIndex);
193 else {
194 fValue.Read(clusterIndex);
195 return *fValue.Get<T>();
196 }
197 }
198
199 // TODO(bgruber): turn enable_if into requires clause with C++20
200 template <typename C = T, std::enable_if_t<Internal::isMappable<FieldT>, C*> = nullptr>
201 const C *MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
202 {
203 return fField.MapV(globalIndex, nItems);
204 }
205
206 // TODO(bgruber): turn enable_if into requires clause with C++20
207 template <typename C = T, std::enable_if_t<Internal::isMappable<FieldT>, C*> = nullptr>
208 const C *MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems)
209 {
210 return fField.MapV(clusterIndex, nItems);
211 }
212};
213
214
215// clang-format off
216/**
217\class ROOT::Experimental::RNTupleViewCollection
218\ingroup NTuple
219\brief A view for a collection, that can itself generate new ntuple views for its nested fields.
220*/
221// clang-format on
222class RNTupleViewCollection : public RNTupleView<ClusterSize_t> {
223 friend class RNTupleReader;
224
225private:
228
230 : RNTupleView<ClusterSize_t>(fieldId, source)
231 , fSource(source)
232 , fCollectionFieldId(fieldId)
233 {}
234
235public:
241
244 RClusterIndex collectionStart;
245 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
246 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
247 collectionStart.GetIndex() + size);
248 }
251 RClusterIndex collectionStart;
252 fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
253 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
254 collectionStart.GetIndex() + size);
255 }
256
257 /// Raises an exception if there is no field with the given name.
258 template <typename T>
259 RNTupleView<T> GetView(std::string_view fieldName) {
260 auto fieldId = fSource->GetSharedDescriptorGuard()->FindFieldId(fieldName, fCollectionFieldId);
261 if (fieldId == kInvalidDescriptorId) {
262 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in RNTuple '" +
264 }
265 return RNTupleView<T>(fieldId, fSource);
266 }
267 /// Raises an exception if there is no field with the given name.
268 RNTupleViewCollection GetViewCollection(std::string_view fieldName) {
269 auto fieldId = fSource->GetSharedDescriptorGuard()->FindFieldId(fieldName, fCollectionFieldId);
270 if (fieldId == kInvalidDescriptorId) {
271 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in RNTuple '" +
273 }
274 return RNTupleViewCollection(fieldId, fSource);
275 }
276
279 RClusterIndex collectionStart;
280 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
281 return size;
282 }
285 RClusterIndex collectionStart;
286 fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
287 return size;
288 }
289};
290
291} // namespace Experimental
292} // namespace ROOT
293
294#endif
#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:303
#define f(i)
Definition RSha256.hxx:104
size_t size(const MatrixT &matrix)
retrieve the size of a square matrix
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
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t index
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
Definition RField.hxx:140
void Read(NTupleSize_t globalIndex)
Definition RField.hxx:184
static constexpr int kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
Definition RField.hxx:97
Abstract interface to read data from an ntuple.
const RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
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:78
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Special help for offset fields.
Definition RField.hxx:1490
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:1224
Used to loop over entries of collections in a single cluster.
const ClusterSize_t::ValueType fStart
RNTupleClusterRange(DescriptorId_t clusterId, ClusterSize_t::ValueType start, ClusterSize_t::ValueType end)
const ClusterSize_t::ValueType fEnd
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
Used to loop over indexes (entries or collections) between start and end.
RNTupleGlobalRange(NTupleSize_t start, NTupleSize_t end)
An RNTuple that is used to read data from storage.
Definition RNTuple.hxx:101
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.
RNTupleView & operator=(RNTupleView &&other)=default
const C * MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems)
RNTupleView & operator=(const RNTupleView &other)=delete
RNTupleView(RNTupleView &&other)=default
const C * MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems)
Detail::RFieldBase::RValue fValue
Used as a Read() destination for fields that are not mappable.
const T & operator()(const RClusterIndex &clusterIndex)
RNTupleView(const RNTupleView &other)=delete
RNTupleView(DescriptorId_t fieldId, Detail::RPageSource *pageSource)
const T & operator()(NTupleSize_t globalIndex)
FieldT fField
fFieldId has fParent always set to null; views access nested fields without looking at the parent
RNTupleGlobalRange GetFieldRange() const
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
constexpr NTupleSize_t kInvalidNTupleIndex
constexpr DescriptorId_t kInvalidDescriptorId
This file contains a specialised ROOT message handler to test for diagnostic in unit tests.
Wrap the integer in a struct in order to avoid template specialization clash with std::uint32_t.