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 <string_view>
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:
44
45public:
46 class RIterator {
47 private:
49 public:
51 using iterator_category = std::forward_iterator_tag;
56
57 RIterator() = default;
59 ~RIterator() = default;
60
61 iterator operator++(int) /* postfix */ { auto r = *this; fIndex++; return r; }
62 iterator& operator++() /* prefix */ { ++fIndex; return *this; }
64 pointer operator->() { return &fIndex; }
65 bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
66 bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
67 };
68
71 RIterator end() { return RIterator(fEnd); }
72 NTupleSize_t size() { return fEnd - fStart; }
73};
74
75
76// clang-format off
77/**
78\class ROOT::Experimental::RNTupleClusterRange
79\ingroup NTuple
80\brief Used to loop over entries of collections in a single cluster
81*/
82// clang-format on
84private:
88public:
89 class RIterator {
90 private:
92 public:
94 using iterator_category = std::forward_iterator_tag;
99
100 RIterator() = default;
102 ~RIterator() = default;
103
104 iterator operator++(int) /* postfix */ { auto r = *this; fIndex++; return r; }
105 iterator& operator++() /* prefix */ { fIndex++; return *this; }
107 pointer operator->() { return &fIndex; }
108 bool operator==(const iterator& rh) const { return fIndex == rh.fIndex; }
109 bool operator!=(const iterator& rh) const { return fIndex != rh.fIndex; }
110 };
111
113 : fClusterId(clusterId), fStart(start), fEnd(end) {}
116};
117
118namespace Internal {
119
120/// Helper to get the iteration space of the given field that needs to be connected to the given page source.
121/// The indexes are given by the number of elements of the principal column of the field or, if none exists,
122/// by the number of elements of the first principal column found in the subfields searched by BFS.
123/// If the field hierarchy is empty on columns, throw an exception.
124RNTupleGlobalRange GetFieldRange(const RFieldBase &field, const RPageSource &pageSource);
125
126} // namespace Internal
127
128// clang-format off
129/**
130\class ROOT::Experimental::RNTupleViewBase
131\ingroup NTuple
132\brief An RNTupleView provides read-only access to a single field of the ntuple
133
134\tparam T The type of the object that will be read by the view; can be void if unknown at compile time.
135
136The view owns a field and its underlying columns in order to fill an RField::RValue object with data. Data can be
137accessed by index. For top-level fields, the index refers to the entry number. Fields that are part of
138nested collections have global index numbers that are derived from their parent indexes.
139
140View can only be created by a reader or by a collection view.
141*/
142// clang-format on
143template <typename T>
145protected:
146 std::unique_ptr<RFieldBase> fField;
149
150 static std::unique_ptr<RFieldBase> CreateField(DescriptorId_t fieldId, Internal::RPageSource &pageSource)
151 {
152 std::unique_ptr<RFieldBase> field;
153 {
154 const auto &desc = pageSource.GetSharedDescriptorGuard().GetRef();
155 const auto &fieldDesc = desc.GetFieldDescriptor(fieldId);
156 if constexpr (std::is_void_v<T>) {
157 field = fieldDesc.CreateField(desc);
158 } else {
159 field = std::make_unique<RField<T>>(fieldDesc.GetFieldName());
160 }
161 }
162 field->SetOnDiskId(fieldId);
163 Internal::CallConnectPageSourceOnField(*field, pageSource);
164 return field;
165 }
166
167 RNTupleViewBase(std::unique_ptr<RFieldBase> field, RNTupleGlobalRange range)
168 : fField(std::move(field)), fFieldRange(range), fValue(fField->CreateValue())
169 {
170 }
171
172 RNTupleViewBase(std::unique_ptr<RFieldBase> field, RNTupleGlobalRange range, std::shared_ptr<T> objPtr)
173 : fField(std::move(field)), fFieldRange(range), fValue(fField->BindValue(objPtr))
174 {
175 }
176
177 RNTupleViewBase(std::unique_ptr<RFieldBase> field, RNTupleGlobalRange range, T *rawPtr)
178 : fField(std::move(field)), fFieldRange(range), fValue(fField->BindValue(Internal::MakeAliasedSharedPtr(rawPtr)))
179 {
180 }
181
182public:
183 RNTupleViewBase(const RNTupleViewBase &other) = delete;
187 ~RNTupleViewBase() = default;
188
189 const RFieldBase &GetField() const { return *fField; }
190 const RFieldBase::RValue &GetValue() const { return fValue; }
192
193 void Bind(std::shared_ptr<T> objPtr) { fValue.Bind(objPtr); }
194 void BindRawPtr(T *rawPtr) { fValue.BindRawPtr(rawPtr); }
196};
197
198// clang-format off
199/**
200\class ROOT::Experimental::RNTupleView
201\ingroup NTuple
202\brief An RNTupleView for a known type. See RNTupleViewBase.
203*/
204// clang-format on
205template <typename T>
206class RNTupleView : public RNTupleViewBase<T> {
207 friend class RNTupleReader;
209
210protected:
211 RNTupleView(std::unique_ptr<RFieldBase> field, RNTupleGlobalRange range)
212 : RNTupleViewBase<T>(std::move(field), range)
213 {
214 }
215
216 RNTupleView(std::unique_ptr<RFieldBase> field, RNTupleGlobalRange range, std::shared_ptr<T> objPtr)
217 : RNTupleViewBase<T>(std::move(field), range, objPtr)
218 {
219 }
220
221 RNTupleView(std::unique_ptr<RFieldBase> field, RNTupleGlobalRange range, T *rawPtr)
222 : RNTupleViewBase<T>(std::move(field), range, rawPtr)
223 {
224 }
225
226public:
227 RNTupleView(const RNTupleView &other) = delete;
228 RNTupleView(RNTupleView &&other) = default;
229 RNTupleView &operator=(const RNTupleView &other) = delete;
230 RNTupleView &operator=(RNTupleView &&other) = default;
231 ~RNTupleView() = default;
232
233 const T &operator()(NTupleSize_t globalIndex)
234 {
235 RNTupleViewBase<T>::fValue.Read(globalIndex);
236 return RNTupleViewBase<T>::fValue.template GetRef<T>();
237 }
238
239 const T &operator()(RClusterIndex clusterIndex)
240 {
241 RNTupleViewBase<T>::fValue.Read(clusterIndex);
242 return RNTupleViewBase<T>::fValue.template GetRef<T>();
243 }
244};
245
246// clang-format off
247/**
248\class ROOT::Experimental::RNTupleView
249\ingroup NTuple
250\brief An RNTupleView that can be used when the type is unknown at compile time. See RNTupleViewBase.
251*/
252// clang-format on
253template <>
254class RNTupleView<void> final : public RNTupleViewBase<void> {
255 friend class RNTupleReader;
257
258protected:
259 RNTupleView(std::unique_ptr<RFieldBase> field, RNTupleGlobalRange range)
260 : RNTupleViewBase<void>(std::move(field), range)
261 {
262 }
263
264 RNTupleView(std::unique_ptr<RFieldBase> field, RNTupleGlobalRange range, std::shared_ptr<void> objPtr)
265 : RNTupleViewBase<void>(std::move(field), range, objPtr)
266 {
267 }
268
269 RNTupleView(std::unique_ptr<RFieldBase> field, RNTupleGlobalRange range, void *rawPtr)
270 : RNTupleViewBase<void>(std::move(field), range, rawPtr)
271 {
272 }
273
274public:
275 RNTupleView(const RNTupleView &other) = delete;
276 RNTupleView(RNTupleView &&other) = default;
277 RNTupleView &operator=(const RNTupleView &other) = delete;
278 RNTupleView &operator=(RNTupleView &&other) = default;
279 ~RNTupleView() = default;
280
281 void operator()(NTupleSize_t globalIndex) { fValue.Read(globalIndex); }
282 void operator()(RClusterIndex clusterIndex) { fValue.Read(clusterIndex); }
283};
284
285// clang-format off
286/**
287\class ROOT::Experimental::RNTupleDirectAccessView
288\ingroup NTuple
289\brief A view variant that provides direct access to the I/O buffers. Only works for mappable fields.
290*/
291// clang-format on
292template <typename T>
294 friend class RNTupleReader;
296
297protected:
300
302 {
303 const auto &desc = pageSource.GetSharedDescriptorGuard().GetRef();
304 const auto &fieldDesc = desc.GetFieldDescriptor(fieldId);
305 if (fieldDesc.GetTypeName() != RField<T>::TypeName()) {
306 throw RException(R__FAIL("type mismatch for field " + fieldDesc.GetFieldName() + ": " +
307 fieldDesc.GetTypeName() + " vs. " + RField<T>::TypeName()));
308 }
309 RField<T> field(fieldDesc.GetFieldName());
310 field.SetOnDiskId(fieldId);
312 return field;
313 }
314
315 RNTupleDirectAccessView(RField<T> field, RNTupleGlobalRange range) : fField(std::move(field)), fFieldRange(range) {}
316
317public:
323
324 const RFieldBase &GetField() const { return fField; }
326
327 const T &operator()(NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
328 const T &operator()(RClusterIndex clusterIndex) { return *fField.Map(clusterIndex); }
329};
330
331// clang-format off
332/**
333\class ROOT::Experimental::RNTupleCollectionView
334\ingroup NTuple
335\brief A view for a collection, that can itself generate new ntuple views for its nested fields.
336*/
337// clang-format on
339 friend class RNTupleReader;
340
341private:
345
346 RNTupleCollectionView(DescriptorId_t fieldId, const std::string &fieldName, Internal::RPageSource *source)
347 : fSource(source), fField(fieldName), fValue(fField.CreateValue())
348 {
349 fField.SetOnDiskId(fieldId);
351 }
352
354 {
355 std::string fieldName;
356 {
357 const auto &desc = source->GetSharedDescriptorGuard().GetRef();
358 const auto &fieldDesc = desc.GetFieldDescriptor(fieldId);
359 if (fieldDesc.GetStructure() != ENTupleStructure::kCollection) {
360 throw RException(
361 R__FAIL("invalid attemt to create collection view on non-collection field " + fieldDesc.GetFieldName()));
362 }
363 fieldName = fieldDesc.GetFieldName();
364 }
365 return RNTupleCollectionView(fieldId, fieldName, source);
366 }
367
368 DescriptorId_t GetFieldId(std::string_view fieldName)
369 {
370 auto descGuard = fSource->GetSharedDescriptorGuard();
371 auto fieldId = descGuard->FindFieldId(fieldName, fField.GetOnDiskId());
372 if (fieldId == kInvalidDescriptorId) {
373 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in collection '" +
374 descGuard->GetQualifiedFieldName(fField.GetOnDiskId()) + "'"));
375 }
376 return fieldId;
377 }
378
379public:
385
388 RClusterIndex collectionStart;
389 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
390 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
391 collectionStart.GetIndex() + size);
392 }
394 {
396 RClusterIndex collectionStart;
397 fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
398 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
399 collectionStart.GetIndex() + size);
400 }
401
402 /// Raises an exception if there is no field with the given name.
403 template <typename T>
404 RNTupleView<T> GetView(std::string_view fieldName)
405 {
406 auto field = RNTupleView<T>::CreateField(GetFieldId(fieldName), *fSource);
407 auto range = Internal::GetFieldRange(*field, *fSource);
408 return RNTupleView<T>(std::move(field), range);
409 }
410
411 /// Raises an exception if there is no field with the given name.
412 template <typename T>
414 {
416 auto range = Internal::GetFieldRange(field, *fSource);
417 return RNTupleDirectAccessView<T>(std::move(field), range);
418 }
419
420 /// Raises an exception if there is no field with the given name.
421 RNTupleCollectionView GetCollectionView(std::string_view fieldName)
422 {
424 }
425
426 std::uint64_t operator()(NTupleSize_t globalIndex)
427 {
428 fValue.Read(globalIndex);
429 return fValue.GetRef<std::uint64_t>();
430 }
431
432 std::uint64_t operator()(RClusterIndex clusterIndex)
433 {
434 fValue.Read(clusterIndex);
435 return fValue.GetRef<std::uint64_t>();
436 }
437};
438
439} // namespace Experimental
440} // namespace ROOT
441
442#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:290
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
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
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
void Read(NTupleSize_t globalIndex)
void EmplaceNew()
Replace the current object pointer by a pointer to a new object constructed by the field.
void Bind(std::shared_ptr< void > objPtr)
A field translates read and write calls from/to underlying columns to/from tree values.
void SetOnDiskId(DescriptorId_t id)
Definition RField.cxx:1058
std::unique_ptr< RFieldBase > CreateField(const RNTupleDescriptor &ntplDesc, bool continueOnError=false) const
In general, we create a field simply from the C++ type name.
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:241
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
A view for a collection, that can itself generate new ntuple views for its nested fields.
RNTupleCollectionView & operator=(RNTupleCollectionView &&other)=default
RNTupleClusterRange GetCollectionRange(RClusterIndex clusterIndex)
RNTupleCollectionView(RNTupleCollectionView &&other)=default
RNTupleCollectionView GetCollectionView(std::string_view fieldName)
Raises an exception if there is no field with the given name.
RNTupleCollectionView & operator=(const RNTupleCollectionView &other)=delete
RField< RNTupleCardinality< std::uint64_t > > fField
RNTupleView< T > GetView(std::string_view fieldName)
Raises an exception if there is no field with the given name.
std::uint64_t operator()(RClusterIndex clusterIndex)
DescriptorId_t GetFieldId(std::string_view fieldName)
RNTupleDirectAccessView< T > GetDirectAccessView(std::string_view fieldName)
Raises an exception if there is no field with the given name.
RNTupleCollectionView(DescriptorId_t fieldId, const std::string &fieldName, Internal::RPageSource *source)
RNTupleClusterRange GetCollectionRange(NTupleSize_t globalIndex)
RNTupleCollectionView(const RNTupleCollectionView &other)=delete
std::uint64_t operator()(NTupleSize_t globalIndex)
static RNTupleCollectionView Create(DescriptorId_t fieldId, Internal::RPageSource *source)
DescriptorId_t FindFieldId(std::string_view fieldName, DescriptorId_t parentId) const
const RFieldDescriptor & GetFieldDescriptor(DescriptorId_t fieldId) const
A view variant that provides direct access to the I/O buffers.
const T & operator()(NTupleSize_t globalIndex)
RNTupleDirectAccessView & operator=(const RNTupleDirectAccessView &other)=delete
RNTupleDirectAccessView(RField< T > field, RNTupleGlobalRange range)
static RField< T > CreateField(DescriptorId_t fieldId, Internal::RPageSource &pageSource)
RNTupleDirectAccessView(const RNTupleDirectAccessView &other)=delete
RNTupleDirectAccessView(RNTupleDirectAccessView &&other)=default
RNTupleDirectAccessView & operator=(RNTupleDirectAccessView &&other)=default
const T & operator()(RClusterIndex clusterIndex)
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.
An RNTupleView provides read-only access to a single field of the ntuple.
const RFieldBase & GetField() const
RNTupleViewBase(const RNTupleViewBase &other)=delete
RNTupleViewBase & operator=(const RNTupleViewBase &other)=delete
RNTupleViewBase(RNTupleViewBase &&other)=default
std::unique_ptr< RFieldBase > fField
const RFieldBase::RValue & GetValue() const
RNTupleViewBase(std::unique_ptr< RFieldBase > field, RNTupleGlobalRange range, std::shared_ptr< T > objPtr)
RNTupleViewBase(std::unique_ptr< RFieldBase > field, RNTupleGlobalRange range)
void Bind(std::shared_ptr< T > objPtr)
RNTupleViewBase & operator=(RNTupleViewBase &&other)=default
RNTupleViewBase(std::unique_ptr< RFieldBase > field, RNTupleGlobalRange range, T *rawPtr)
RNTupleGlobalRange GetFieldRange() const
static std::unique_ptr< RFieldBase > CreateField(DescriptorId_t fieldId, Internal::RPageSource &pageSource)
void operator()(NTupleSize_t globalIndex)
RNTupleView(RNTupleView &&other)=default
RNTupleView(const RNTupleView &other)=delete
RNTupleView(std::unique_ptr< RFieldBase > field, RNTupleGlobalRange range)
RNTupleView & operator=(RNTupleView &&other)=default
void operator()(RClusterIndex clusterIndex)
RNTupleView(std::unique_ptr< RFieldBase > field, RNTupleGlobalRange range, void *rawPtr)
RNTupleView & operator=(const RNTupleView &other)=delete
RNTupleView(std::unique_ptr< RFieldBase > field, RNTupleGlobalRange range, std::shared_ptr< void > objPtr)
An RNTupleView for a known type.
RNTupleView & operator=(RNTupleView &&other)=default
const T & operator()(RClusterIndex clusterIndex)
RNTupleView(std::unique_ptr< RFieldBase > field, RNTupleGlobalRange range)
RNTupleView & operator=(const RNTupleView &other)=delete
RNTupleView(RNTupleView &&other)=default
RNTupleView(const RNTupleView &other)=delete
RNTupleView(std::unique_ptr< RFieldBase > field, RNTupleGlobalRange range, std::shared_ptr< T > objPtr)
const T & operator()(NTupleSize_t globalIndex)
RNTupleView(std::unique_ptr< RFieldBase > field, RNTupleGlobalRange range, T *rawPtr)
RNTupleGlobalRange GetFieldRange(const RFieldBase &field, const RPageSource &pageSource)
Helper to get the iteration space of the given field that needs to be connected to the given page sou...
void CallConnectPageSourceOnField(RFieldBase &, RPageSource &)
Definition RField.cxx:411
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
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Wrap the integer in a struct in order to avoid template specialization clash with std::uint64_t.