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
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:
165 : fField(pageSource->GetSharedDescriptorGuard()->GetFieldDescriptor(fieldId).GetFieldName()),
166 fValue(fField.GenerateValue())
167 {
168 if ((fField.GetTraits() & Detail::RFieldBase::kTraitMappable) && fField.HasReadCallbacks())
169 throw RException(R__FAIL("view disallowed on field with mappable type and read callback"));
170 fField.SetOnDiskId(fieldId);
171 fField.ConnectPageSource(*pageSource);
172 for (auto &f : fField) {
173 auto subFieldId =
174 pageSource->GetSharedDescriptorGuard()->FindFieldId(f.GetName(), f.GetParent()->GetOnDiskId());
175 f.SetOnDiskId(subFieldId);
176 f.ConnectPageSource(*pageSource);
177 }
178 }
179
180 RNTupleView(const RNTupleView& other) = delete;
181 RNTupleView(RNTupleView&& other) = default;
182 RNTupleView& operator=(const RNTupleView& other) = delete;
183 RNTupleView& operator=(RNTupleView&& other) = default;
184 ~RNTupleView() { fField.DestroyValue(fValue); }
185
186 RNTupleGlobalRange GetFieldRange() const { return RNTupleGlobalRange(0, fField.GetNElements()); }
187
188 template <typename C = T>
189 typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C&>
190 operator()(NTupleSize_t globalIndex) { return *fField.Map(globalIndex); }
191
192 template <typename C = T>
193 typename std::enable_if_t<!Internal::IsMappable<FieldT>::value, const C&>
195 fField.Read(globalIndex, &fValue);
196 return *fValue.Get<T>();
197 }
198
199 template <typename C = T>
200 typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C&>
201 operator()(const RClusterIndex &clusterIndex) { return *fField.Map(clusterIndex); }
202
203 template <typename C = T>
204 typename std::enable_if_t<!Internal::IsMappable<FieldT>::value, const C&>
205 operator()(const RClusterIndex &clusterIndex) {
206 fField.Read(clusterIndex, &fValue);
207 return *fValue.Get<T>();
208 }
209
210 template <typename C = T>
211 typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C*>
212 MapV(NTupleSize_t globalIndex, NTupleSize_t &nItems) {
213 return fField.MapV(globalIndex, nItems);
214 }
215
216 template <typename C = T>
217 typename std::enable_if_t<Internal::IsMappable<FieldT>::value, const C*>
218 MapV(const RClusterIndex &clusterIndex, NTupleSize_t &nItems) {
219 return fField.MapV(clusterIndex, nItems);
220 }
221};
222
223
224// clang-format off
225/**
226\class ROOT::Experimental::RNTupleViewCollection
227\ingroup NTuple
228\brief A view for a collection, that can itself generate new ntuple views for its nested fields.
229*/
230// clang-format on
231class RNTupleViewCollection : public RNTupleView<ClusterSize_t> {
232 friend class RNTupleReader;
233
234private:
237
239 : RNTupleView<ClusterSize_t>(fieldId, source)
240 , fSource(source)
241 , fCollectionFieldId(fieldId)
242 {}
243
244public:
250
253 RClusterIndex collectionStart;
254 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
255 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
256 collectionStart.GetIndex() + size);
257 }
260 RClusterIndex collectionStart;
261 fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
262 return RNTupleClusterRange(collectionStart.GetClusterId(), collectionStart.GetIndex(),
263 collectionStart.GetIndex() + size);
264 }
265
266 /// Raises an exception if there is no field with the given name.
267 template <typename T>
268 RNTupleView<T> GetView(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 RNTupleView<T>(fieldId, fSource);
275 }
276 /// Raises an exception if there is no field with the given name.
277 RNTupleViewCollection GetViewCollection(std::string_view fieldName) {
278 auto fieldId = fSource->GetSharedDescriptorGuard()->FindFieldId(fieldName, fCollectionFieldId);
279 if (fieldId == kInvalidDescriptorId) {
280 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in RNTuple '" +
282 }
283 return RNTupleViewCollection(fieldId, fSource);
284 }
285
288 RClusterIndex collectionStart;
289 fField.GetCollectionInfo(globalIndex, &collectionStart, &size);
290 return size;
291 }
294 RClusterIndex collectionStart;
295 fField.GetCollectionInfo(clusterIndex, &collectionStart, &size);
296 return size;
297 }
298};
299
300} // namespace Experimental
301} // namespace ROOT
302
303#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
static constexpr int kTraitMappable
A field of a fundamental type that can be directly mapped via RField<T>::Map(), i....
Definition RField.hxx:90
Abstract interface to read data from an ntuple.
const RSharedDescriptorGuard GetSharedDescriptorGuard() const
Takes the read lock for the descriptor.
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:78
void GetCollectionInfo(NTupleSize_t globalIndex, RClusterIndex *collectionStart, ClusterSize_t *size)
Special help for offset fields.
Definition RField.hxx:876
Classes with dictionaries that can be inspected by TClass.
Definition RField.hxx:640
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:110
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
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 32bit integer in a struct in order to avoid template specialization clash with std::uint32_t...