|
|
|||
File indexing completed on 2026-09-07 09:25:39
0001 /// \file ROOT/RNTupleReader.hxx 0002 /// \ingroup NTuple 0003 /// \author Jakob Blomer <jblomer@cern.ch> 0004 /// \date 2024-02-20 0005 0006 /************************************************************************* 0007 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. * 0008 * All rights reserved. * 0009 * * 0010 * For the licensing terms see $ROOTSYS/LICENSE. * 0011 * For the list of contributors see $ROOTSYS/README/CREDITS. * 0012 *************************************************************************/ 0013 0014 #ifndef ROOT_RNTupleReader 0015 #define ROOT_RNTupleReader 0016 0017 #include <ROOT/RConfig.hxx> // for R__unlikely 0018 #include <ROOT/REntry.hxx> 0019 #include <ROOT/RError.hxx> 0020 #include <ROOT/RNTupleDescriptor.hxx> 0021 #include <ROOT/RNTupleMetrics.hxx> 0022 #include <ROOT/RNTupleModel.hxx> 0023 #include <ROOT/RNTupleReadOptions.hxx> 0024 #include <ROOT/RNTupleTypes.hxx> 0025 #include <ROOT/RNTupleView.hxx> 0026 #include <ROOT/RPageStorage.hxx> 0027 #include <ROOT/RSpan.hxx> 0028 0029 #include <iostream> 0030 #include <iterator> 0031 #include <memory> 0032 #include <mutex> 0033 #include <string> 0034 #include <string_view> 0035 #include <unordered_map> 0036 0037 namespace ROOT { 0038 class RNTuple; 0039 0040 /// Listing of the different options that can be printed by RNTupleReader::GetInfo() 0041 enum class ENTupleInfo { 0042 kSummary, // The RNTuple name, description, number of entries 0043 kStorageDetails, // size on storage, page sizes, compression factor, etc. 0044 kMetrics, // internals performance counters, requires that EnableMetrics() was called 0045 }; 0046 0047 // clang-format off 0048 /** 0049 \class ROOT::RNTupleReader 0050 \ingroup NTuple 0051 \brief Reads RNTuple data from storage 0052 0053 The RNTupleReader provides access to data stored in the RNTuple binary format as C++ objects, using an RNTupleModel. 0054 It infers this model from the RNTuple's on-disk metadata, or uses a model imposed by the user. 0055 The latter case allows users to read into a specialized RNTuple model that covers 0056 only a subset of the fields in the RNTuple. The RNTuple model is used when reading complete entries through LoadEntry(). 0057 Individual fields can be read as well by instantiating a tree view. 0058 0059 ~~~ {.cpp} 0060 #include <ROOT/RNTupleReader.hxx> 0061 #include <iostream> 0062 0063 auto reader = ROOT::RNTupleReader::Open("myNTuple", "some/file.root"); 0064 std::cout << "myNTuple has " << reader->GetNEntries() << " entries\n"; 0065 ~~~ 0066 */ 0067 // clang-format on 0068 class RNTupleReader { 0069 private: 0070 /// Shared data structure between the reader and all the issued active entry tokens. 0071 struct RActiveEntriesControlBlock { 0072 /// Points to the page source backing the associated RNTupleReader. When the reader is destructed, the 0073 /// page source is reset to nullptr. At that point, operations on remaining active entry tokens become noops. 0074 Internal::RPageSource *fPageSource = nullptr; 0075 /// Reference counter of clusters pinned in the page source due to entries being marked as active. 0076 std::unordered_map<ROOT::DescriptorId_t, std::uint64_t> fActiveClusters; 0077 std::mutex fLock; 0078 0079 explicit RActiveEntriesControlBlock(Internal::RPageSource *pageSource) : fPageSource(pageSource) {} 0080 }; 0081 0082 /// Set as the page source's scheduler for parallel page decompression if implicit multi-threading (IMT) is on. 0083 /// Needs to be destructed after the page source is destructed (and thus be declared before) 0084 std::unique_ptr<Internal::RPageStorage::RTaskScheduler> fUnzipTasks; 0085 0086 std::unique_ptr<Internal::RPageSource> fSource; 0087 /// Needs to be destructed before fSource 0088 std::unique_ptr<ROOT::RNTupleModel> fModel; 0089 /// We use a dedicated on-demand reader for Show(). Printing data uses all the fields 0090 /// from the full model even if the analysis code uses only a subset of fields. The display reader 0091 /// is a clone of the original reader. 0092 std::unique_ptr<RNTupleReader> fDisplayReader; 0093 /// The RNTuple descriptor in the page source is protected by a read-write lock. We don't expose that to the 0094 /// users of RNTupleReader::GetDescriptor(). Instead, if descriptor information is needed, we clone the 0095 /// descriptor. Using the descriptor's generation number, we know if the cached descriptor is stale. 0096 /// Retrieving descriptor data from an RNTupleReader is supposed to be for testing and information purposes, 0097 /// not on a hot code path. 0098 std::optional<ROOT::RNTupleDescriptor> fCachedDescriptor; 0099 /// We know that the RNTupleReader is always reading a single RNTuple, so the number of entries is fixed. 0100 ROOT::NTupleSize_t fNEntries = 0; 0101 Experimental::Detail::RNTupleMetrics fMetrics; 0102 /// If not nullopt, these will be used when creating the model 0103 std::optional<ROOT::RNTupleDescriptor::RCreateModelOptions> fCreateModelOptions; 0104 /// Initialized when the page source is connected. It is then shared between the reader instance and all 0105 /// active entry tokens. When the reader destructs, it resets the page source pointer in the control block. 0106 std::shared_ptr<RActiveEntriesControlBlock> fActiveEntriesControlBlock; 0107 0108 RNTupleReader(std::unique_ptr<ROOT::RNTupleModel> model, std::unique_ptr<Internal::RPageSource> source, 0109 const ROOT::RNTupleReadOptions &options); 0110 /// The model is generated from the RNTuple metadata on storage. 0111 explicit RNTupleReader(std::unique_ptr<Internal::RPageSource> source, const ROOT::RNTupleReadOptions &options); 0112 0113 void ConnectModel(ROOT::RNTupleModel &model, bool allowFieldSubstitutions); 0114 RNTupleReader *GetDisplayReader(); 0115 void InitPageSource(bool enableMetrics); 0116 0117 ROOT::DescriptorId_t RetrieveFieldId(std::string_view fieldName) const; 0118 0119 public: 0120 // Browse through the entries 0121 class RIterator { 0122 private: 0123 ROOT::NTupleSize_t fIndex = ROOT::kInvalidNTupleIndex; 0124 0125 public: 0126 using iterator = RIterator; 0127 using iterator_category = std::input_iterator_tag; 0128 using value_type = ROOT::NTupleSize_t; 0129 using difference_type = std::ptrdiff_t; 0130 using pointer = const ROOT::NTupleSize_t *; 0131 using reference = const ROOT::NTupleSize_t &; 0132 0133 RIterator() = default; 0134 explicit RIterator(ROOT::NTupleSize_t index) : fIndex(index) {} 0135 ~RIterator() = default; 0136 0137 iterator operator++(int) /* postfix */ 0138 { 0139 auto r = *this; 0140 fIndex++; 0141 return r; 0142 } 0143 iterator &operator++() /* prefix */ 0144 { 0145 ++fIndex; 0146 return *this; 0147 } 0148 reference operator*() const { return fIndex; } 0149 pointer operator->() const { return &fIndex; } 0150 bool operator==(const iterator &rh) const { return fIndex == rh.fIndex; } 0151 bool operator!=(const iterator &rh) const { return fIndex != rh.fIndex; } 0152 }; 0153 0154 /// An active entry token is a pledge for the data of a certain entry number not to be evicted from the 0155 /// page cache or cluster cache. An active entry token is linked to a specific reader through a control block 0156 /// shared by the reader and all tokens of that reader. Active entry tokens can be destructed before or after 0157 /// their reader is destructed. Once the corresponding reader is destructed, changing the entry number has no 0158 /// effect. 0159 /// Only the RNTuple reader can create an active entry token. 0160 class RActiveEntryToken { 0161 friend class RNTupleReader; 0162 0163 std::shared_ptr<RActiveEntriesControlBlock> fPtrControlBlock; 0164 NTupleSize_t fEntryNumber = kInvalidNTupleIndex; 0165 0166 void ActivateEntry(NTupleSize_t entryNumber); 0167 void DeactivateEntry(NTupleSize_t entryNumber); 0168 0169 explicit RActiveEntryToken(std::shared_ptr<RActiveEntriesControlBlock> ptrControlBlock) 0170 : fPtrControlBlock(ptrControlBlock) 0171 { 0172 } 0173 0174 public: 0175 ~RActiveEntryToken() { Reset(); } 0176 RActiveEntryToken(const RActiveEntryToken &other); 0177 RActiveEntryToken(RActiveEntryToken &&other); 0178 RActiveEntryToken &operator=(const RActiveEntryToken &other); 0179 RActiveEntryToken &operator=(RActiveEntryToken &&other); 0180 0181 NTupleSize_t GetEntryNumber() const { return fEntryNumber; } 0182 /// Set or replace the entry number. If the entry number is replaced, the cluster corresponding to the new 0183 /// entry is pinned _before_ the cluster of the old entry number is unpinned. 0184 /// SetEntryNumber() should be called before the corresponding entry is used (through LoadEntry() or views). 0185 void SetEntryNumber(NTupleSize_t entryNumber); 0186 /// Release the entry number, i.e. allow the corresponding data to be evicted from caches. 0187 /// Called implicitly on destruction. 0188 void Reset(); 0189 }; 0190 0191 /// Open an RNTuple for reading. 0192 /// 0193 /// Throws an RException if there is no RNTuple with the given name. 0194 /// 0195 /// **Example: open an RNTuple and print the number of entries** 0196 /// ~~~ {.cpp} 0197 /// #include <ROOT/RNTupleReader.hxx> 0198 /// #include <iostream> 0199 /// 0200 /// auto reader = ROOT::RNTupleReader::Open("myNTuple", "some/file.root"); 0201 /// std::cout << "myNTuple has " << reader->GetNEntries() << " entries\n"; 0202 /// ~~~ 0203 static std::unique_ptr<RNTupleReader> Open(std::string_view ntupleName, std::string_view storage, 0204 const ROOT::RNTupleReadOptions &options = ROOT::RNTupleReadOptions()); 0205 static std::unique_ptr<RNTupleReader> 0206 Open(const RNTuple &ntuple, const ROOT::RNTupleReadOptions &options = ROOT::RNTupleReadOptions()); 0207 0208 /// The caller imposes a model, which must be compatible with the model found in the data on storage. 0209 static std::unique_ptr<RNTupleReader> Open(std::unique_ptr<ROOT::RNTupleModel> model, std::string_view ntupleName, 0210 std::string_view storage, 0211 const ROOT::RNTupleReadOptions &options = ROOT::RNTupleReadOptions()); 0212 static std::unique_ptr<RNTupleReader> Open(std::unique_ptr<ROOT::RNTupleModel> model, const RNTuple &ntuple, 0213 const ROOT::RNTupleReadOptions &options = ROOT::RNTupleReadOptions()); 0214 0215 /// The caller imposes the way the model is reconstructed 0216 static std::unique_ptr<RNTupleReader> Open(const ROOT::RNTupleDescriptor::RCreateModelOptions &createModelOpts, 0217 std::string_view ntupleName, std::string_view storage, 0218 const ROOT::RNTupleReadOptions &options = ROOT::RNTupleReadOptions()); 0219 static std::unique_ptr<RNTupleReader> Open(const ROOT::RNTupleDescriptor::RCreateModelOptions &createModelOpts, 0220 const RNTuple &ntuple, 0221 const ROOT::RNTupleReadOptions &options = ROOT::RNTupleReadOptions()); 0222 std::unique_ptr<RNTupleReader> Clone() 0223 { 0224 auto options = ROOT::RNTupleReadOptions{}; 0225 options.SetEnableMetrics(fMetrics.IsEnabled()); 0226 return std::unique_ptr<RNTupleReader>(new RNTupleReader(fSource->Clone(), options)); 0227 } 0228 0229 RNTupleReader(const ROOT::RNTupleReader &) = delete; 0230 RNTupleReader &operator=(const ROOT::RNTupleReader &) = delete; 0231 RNTupleReader(ROOT::RNTupleReader &&) = delete; 0232 RNTupleReader &operator=(ROOT::RNTupleReader &&) = delete; 0233 ~RNTupleReader(); 0234 0235 /// Returns the number of entries in this RNTuple. 0236 /// Note that the recommended way to iterate the RNTuple is using 0237 /// ~~~ {.cpp} 0238 /// // RECOMMENDED way to iterate an ntuple 0239 /// for (auto i : reader->GetEntryRange()) { ... } 0240 /// ~~~ 0241 /// instead of 0242 /// ~~~ {.cpp} 0243 /// // DISCOURAGED way to iterate an ntuple 0244 /// for (auto i = 0u; i < reader->GetNEntries(); ++i) { ... } 0245 /// ~~~ 0246 /// The reason is that determining the number of entries, while currently cheap, may in the future be 0247 /// an expensive operation. 0248 ROOT::NTupleSize_t GetNEntries() const { return fNEntries; } 0249 const ROOT::RNTupleModel &GetModel(); 0250 std::unique_ptr<ROOT::REntry> CreateEntry(); 0251 0252 /// Returns a cached copy of the page source descriptor. The returned pointer remains valid until the next call 0253 /// to LoadEntry() or to any of the views returned from the reader. 0254 const ROOT::RNTupleDescriptor &GetDescriptor(); 0255 0256 /// Prints a detailed summary of the RNTuple, including a list of fields. 0257 /// 0258 /// **Example: print summary information to stdout** 0259 /// ~~~ {.cpp} 0260 /// #include <ROOT/RNTupleReader.hxx> 0261 /// #include <iostream> 0262 /// 0263 /// auto reader = ROOT::RNTupleReader::Open("myNTuple", "some/file.root"); 0264 /// reader->PrintInfo(); 0265 /// // or, equivalently: 0266 /// reader->PrintInfo(ROOT::ENTupleInfo::kSummary, std::cout); 0267 /// ~~~ 0268 /// **Example: print detailed column storage data to stderr** 0269 /// ~~~ {.cpp} 0270 /// #include <ROOT/RNTupleReader.hxx> 0271 /// #include <iostream> 0272 /// 0273 /// auto reader = ROOT::RNTupleReader::Open("myNTuple", "some/file.root"); 0274 /// reader->PrintInfo(ROOT::ENTupleInfo::kStorageDetails, std::cerr); 0275 /// ~~~ 0276 /// 0277 /// For use of ENTupleInfo::kMetrics, see #EnableMetrics. 0278 void PrintInfo(const ENTupleInfo what = ENTupleInfo::kSummary, std::ostream &output = std::cout) const; 0279 0280 /// Shows the values of the i-th entry/row, starting with 0 for the first entry. By default, 0281 /// prints the output in JSON format. 0282 /// Uses the visitor pattern to traverse through each field of the given entry. 0283 void Show(ROOT::NTupleSize_t index, std::ostream &output = std::cout); 0284 0285 /// Fills the default entry of the model. 0286 /// Raises an exception when `index` is greater than the number of entries present in the RNTuple 0287 void LoadEntry(ROOT::NTupleSize_t index) 0288 { 0289 // TODO(jblomer): can be templated depending on the factory method / constructor 0290 if (R__unlikely(!fModel)) { 0291 // Will create the fModel. 0292 GetModel(); 0293 } 0294 LoadEntry(index, fModel->GetDefaultEntry()); 0295 } 0296 /// Fills a user provided entry after checking that the entry has been instantiated from the RNTuple model 0297 void LoadEntry(ROOT::NTupleSize_t index, ROOT::REntry &entry) 0298 { 0299 if (R__unlikely(entry.GetModelId() != fModel->GetModelId())) 0300 throw RException(R__FAIL("mismatch between entry and model")); 0301 0302 entry.Read(index); 0303 } 0304 0305 /// Create a new active entry token, which will not be bound to any entry number initially. 0306 /// In order to bind the new token, its `SetEntryNumber()` must be called subsequently. 0307 RActiveEntryToken CreateActiveEntryToken() { return RActiveEntryToken(fActiveEntriesControlBlock); } 0308 0309 /// Returns an iterator over the entry indices of the RNTuple. 0310 /// 0311 /// **Example: iterate over all entries and print each entry in JSON format** 0312 /// ~~~ {.cpp} 0313 /// #include <ROOT/RNTupleReader.hxx> 0314 /// #include <iostream> 0315 /// 0316 /// auto reader = ROOT::RNTupleReader::Open("myNTuple", "some/file.root"); 0317 /// for (auto i : ntuple->GetEntryRange()) { 0318 /// reader->Show(i); 0319 /// } 0320 /// ~~~ 0321 ROOT::RNTupleGlobalRange GetEntryRange() { return ROOT::RNTupleGlobalRange(0, GetNEntries()); } 0322 0323 /// Provides access to an individual (sub)field, 0324 /// e.g. `GetView<Particle>("particle")`, `GetView<double>("particle.pt")` or 0325 /// `GetView<std::vector<Particle>>("particles")`. It is possible to directly get the size of a collection (without 0326 /// reading the collection itself) using RNTupleCardinality: 0327 /// `GetView<ROOT::RNTupleCardinality<std::uint64_t>>("particles")`. 0328 /// 0329 /// Raises an exception if there is no field with the given name. 0330 /// 0331 /// **Example: iterate over a field named "pt" of type `float`** 0332 /// ~~~ {.cpp} 0333 /// #include <ROOT/RNTupleReader.hxx> 0334 /// #include <iostream> 0335 /// 0336 /// auto reader = ROOT::RNTupleReader::Open("myNTuple", "some/file.root"); 0337 /// auto pt = reader->GetView<float>("pt"); 0338 /// 0339 /// for (auto i : reader->GetEntryRange()) { 0340 /// std::cout << i << ": " << pt(i) << "\n"; 0341 /// } 0342 /// ~~~ 0343 /// 0344 /// **Note**: if `T = void`, type checks are disabled. This is not really useful for this overload because 0345 /// RNTupleView<void> does not give access to the pointer. If required, it is possible to provide an `objPtr` of a 0346 /// dynamic type, for example via GetView(std::string_view, void *, std::string_view). 0347 template <typename T> 0348 ROOT::RNTupleView<T> GetView(std::string_view fieldName) 0349 { 0350 return GetView<T>(RetrieveFieldId(fieldName)); 0351 } 0352 0353 /// Provides access to an individual (sub)field, reading its values into `objPtr`. 0354 /// 0355 /// Raises an exception if there is no field with the given name. 0356 /// 0357 /// **Example: iterate over a field named "pt" of type `float`** 0358 /// ~~~ {.cpp} 0359 /// #include <ROOT/RNTupleReader.hxx> 0360 /// #include <iostream> 0361 /// 0362 /// auto reader = ROOT::RNTupleReader::Open("myNTuple", "some/file.root"); 0363 /// auto pt = std::make_shared<float>(); 0364 /// auto ptView = reader->GetView("pt", pt); 0365 /// 0366 /// for (auto i : reader->GetEntryRange()) { 0367 /// ptView(i); 0368 /// std::cout << i << ": " << *pt << "\n"; 0369 /// } 0370 /// ~~~ 0371 /// 0372 /// **Note**: if `T = void`, type checks are disabled. It is the caller's responsibility to match the field and 0373 /// object types. It is strongly recommended to use an overload that allows passing the `typeName`, such as 0374 /// GetView(std::string_view, void *, std::string_view). This allows type checks with the on-disk metadata and 0375 /// enables automatic schema evolution and conversion rules. 0376 template <typename T> 0377 ROOT::RNTupleView<T> GetView(std::string_view fieldName, std::shared_ptr<T> objPtr) 0378 { 0379 return GetView<T>(RetrieveFieldId(fieldName), objPtr); 0380 } 0381 0382 /// Provides access to an individual (sub)field, reading its values into `rawPtr`. 0383 /// 0384 /// \sa GetView(std::string_view, std::shared_ptr<T>) 0385 template <typename T> 0386 ROOT::RNTupleView<T> GetView(std::string_view fieldName, T *rawPtr) 0387 { 0388 return GetView<T>(RetrieveFieldId(fieldName), rawPtr); 0389 } 0390 0391 /// Provides access to an individual (sub)field, reading its values into `rawPtr` as the type provided by `typeName`. 0392 /// 0393 /// \sa GetView(std::string_view, std::shared_ptr<T>) 0394 ROOT::RNTupleView<void> GetView(std::string_view fieldName, void *rawPtr, std::string_view typeName) 0395 { 0396 return GetView(RetrieveFieldId(fieldName), rawPtr, typeName); 0397 } 0398 0399 /// Provides access to an individual (sub)field, reading its values into `rawPtr` as the type provided by `ti`. 0400 /// 0401 /// \sa GetView(std::string_view, std::shared_ptr<T>) 0402 ROOT::RNTupleView<void> GetView(std::string_view fieldName, void *rawPtr, const std::type_info &ti) 0403 { 0404 return GetView(RetrieveFieldId(fieldName), rawPtr, ROOT::Internal::GetRenormalizedTypeName(ti)); 0405 } 0406 0407 /// Provides access to an individual (sub)field from its on-disk ID. 0408 /// 0409 /// \sa GetView(std::string_view) 0410 template <typename T> 0411 ROOT::RNTupleView<T> GetView(ROOT::DescriptorId_t fieldId) 0412 { 0413 auto field = ROOT::RNTupleView<T>::CreateField(fieldId, *fSource); 0414 auto range = ROOT::Internal::GetFieldRange(*field, *fSource); 0415 return ROOT::RNTupleView<T>(std::move(field), range); 0416 } 0417 0418 /// Provides access to an individual (sub)field from its on-disk ID, reading its values into `objPtr`. 0419 /// 0420 /// \sa GetView(std::string_view, std::shared_ptr<T>) 0421 template <typename T> 0422 ROOT::RNTupleView<T> GetView(ROOT::DescriptorId_t fieldId, std::shared_ptr<T> objPtr) 0423 { 0424 auto field = ROOT::RNTupleView<T>::CreateField(fieldId, *fSource); 0425 auto range = ROOT::Internal::GetFieldRange(*field, *fSource); 0426 return ROOT::RNTupleView<T>(std::move(field), range, objPtr); 0427 } 0428 0429 /// Provides access to an individual (sub)field from its on-disk ID, reading its values into `rawPtr`. 0430 /// 0431 /// \sa GetView(std::string_view, std::shared_ptr<T>) 0432 template <typename T> 0433 ROOT::RNTupleView<T> GetView(ROOT::DescriptorId_t fieldId, T *rawPtr) 0434 { 0435 auto field = ROOT::RNTupleView<T>::CreateField(fieldId, *fSource); 0436 auto range = ROOT::Internal::GetFieldRange(*field, *fSource); 0437 return ROOT::RNTupleView<T>(std::move(field), range, rawPtr); 0438 } 0439 0440 /// Provides access to an individual (sub)field from its on-disk ID, reading its values into `rawPtr` as the type 0441 /// provided by `typeName`. 0442 /// 0443 /// \sa GetView(std::string_view, std::shared_ptr<T>) 0444 ROOT::RNTupleView<void> GetView(ROOT::DescriptorId_t fieldId, void *rawPtr, std::string_view typeName) 0445 { 0446 auto field = RNTupleView<void>::CreateField(fieldId, *fSource, typeName); 0447 auto range = ROOT::Internal::GetFieldRange(*field, *fSource); 0448 return RNTupleView<void>(std::move(field), range, rawPtr); 0449 } 0450 0451 /// Provides access to an individual (sub)field from its on-disk ID, reading its values into `objPtr` as the type 0452 /// provided by `ti`. 0453 /// 0454 /// \sa GetView(std::string_view, std::shared_ptr<T>) 0455 ROOT::RNTupleView<void> GetView(ROOT::DescriptorId_t fieldId, void *rawPtr, const std::type_info &ti) 0456 { 0457 return GetView(fieldId, rawPtr, ROOT::Internal::GetRenormalizedTypeName(ti)); 0458 } 0459 0460 /// Provides direct access to the I/O buffers of a **mappable** (sub)field. 0461 /// 0462 /// Raises an exception if there is no field with the given name. 0463 /// Attempting to access the values of a direct-access view for non-mappable fields will yield compilation errors. 0464 /// 0465 /// \sa GetView(std::string_view) 0466 template <typename T> 0467 ROOT::RNTupleDirectAccessView<T> GetDirectAccessView(std::string_view fieldName) 0468 { 0469 return GetDirectAccessView<T>(RetrieveFieldId(fieldName)); 0470 } 0471 0472 /// Provides direct access to the I/O buffers of a **mappable** (sub)field from its on-disk ID. 0473 /// 0474 /// \sa GetDirectAccessView(std::string_view) 0475 template <typename T> 0476 ROOT::RNTupleDirectAccessView<T> GetDirectAccessView(ROOT::DescriptorId_t fieldId) 0477 { 0478 auto field = ROOT::RNTupleDirectAccessView<T>::CreateField(fieldId, *fSource); 0479 auto range = ROOT::Internal::GetFieldRange(field, *fSource); 0480 return ROOT::RNTupleDirectAccessView<T>(std::move(field), range); 0481 } 0482 0483 /// Provides access to a collection field, that can itself generate new RNTupleViews for its nested fields. 0484 /// 0485 /// Raises an exception if: 0486 /// * there is no field with the given name or, 0487 /// * the field is not a collection 0488 /// 0489 /// \sa GetView(std::string_view) 0490 ROOT::RNTupleCollectionView GetCollectionView(std::string_view fieldName) 0491 { 0492 auto fieldId = fSource->GetSharedDescriptorGuard()->FindFieldId(fieldName); 0493 if (fieldId == ROOT::kInvalidDescriptorId) { 0494 throw RException(R__FAIL("no field named '" + std::string(fieldName) + "' in RNTuple '" + 0495 fSource->GetSharedDescriptorGuard()->GetName() + "'")); 0496 } 0497 return GetCollectionView(fieldId); 0498 } 0499 0500 /// Provides access to a collection field from its on-disk ID, that can itself generate new RNTupleViews for its 0501 /// nested fields. 0502 /// 0503 /// \sa GetCollectionView(std::string_view) 0504 ROOT::RNTupleCollectionView GetCollectionView(ROOT::DescriptorId_t fieldId) 0505 { 0506 return ROOT::RNTupleCollectionView::Create(fieldId, fSource.get()); 0507 } 0508 0509 RIterator begin() { return RIterator(0); } 0510 RIterator end() { return RIterator(GetNEntries()); } 0511 0512 /// Enable performance measurements (decompression time, bytes read from storage, etc.) 0513 /// 0514 /// **Example: inspect the reader metrics after loading every entry** 0515 /// ~~~ {.cpp} 0516 /// #include <ROOT/RNTupleReader.hxx> 0517 /// #include <iostream> 0518 /// 0519 /// auto ntuple = ROOT::RNTupleReader::Open("myNTuple", "some/file.root"); 0520 /// // metrics must be turned on beforehand 0521 /// reader->EnableMetrics(); 0522 /// 0523 /// for (auto i : ntuple->GetEntryRange()) { 0524 /// reader->LoadEntry(i); 0525 /// } 0526 /// reader->PrintInfo(ROOT::ENTupleInfo::kMetrics); 0527 /// ~~~ 0528 void EnableMetrics() { fMetrics.Enable(); } 0529 const Experimental::Detail::RNTupleMetrics &GetMetrics() const { return fMetrics; } 0530 0531 /// Looks for an attribute set with the given name and creates an RNTupleAttrSetReader for it, with the provided 0532 /// read options. 0533 /// The returned reader has an independent lifetime from this RNTupleReader. 0534 std::unique_ptr<Experimental::RNTupleAttrSetReader> 0535 OpenAttributeSet(std::string_view attrSetName, const ROOT::RNTupleReadOptions &options = {}); 0536 }; // class RNTupleReader 0537 0538 } // namespace ROOT 0539 0540 #endif // ROOT_RNTupleReader
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|