Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleProcessor.hxx
Go to the documentation of this file.
1/// \file ROOT/RNTupleProcessor.hxx
2/// \author Florine de Geus <florine.de.geus@cern.ch>
3/// \date 2024-03-26
4/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
5/// is welcome!
6
7/*************************************************************************
8 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. *
9 * All rights reserved. *
10 * *
11 * For the licensing terms see $ROOTSYS/LICENSE. *
12 * For the list of contributors see $ROOTSYS/README/CREDITS. *
13 *************************************************************************/
14
15#ifndef ROOT_RNTupleProcessor
16#define ROOT_RNTupleProcessor
17
18#include <ROOT/REntry.hxx>
19#include <ROOT/RError.hxx>
22#include <ROOT/RNTupleModel.hxx>
23#include <ROOT/RNTupleTypes.hxx>
25#include <ROOT/RPageStorage.hxx>
26
27#include <memory>
28#include <string>
29#include <string_view>
30#include <vector>
31
32namespace ROOT {
33class RNTupleProcessor;
34
35namespace Experimental {
36class RNTupleJoinProcessor;
37
38namespace Internal {
39namespace RDF {
40class RNTupleProcessorColumnReader;
42} // namespace RDF
43} // namespace Internal
44} // namespace Experimental
45
46namespace Internal {
47struct RNTupleProcessorEntryLoader; // for unit tests
48const RNTupleProcessorEntry *
49LoadFullRNTupleProcessorEntry(ROOT::RNTupleProcessor &processor, bool includeSubfields); // for unit tests
50} // namespace Internal
51
53private:
54 /// By default, the processor name is the name of the underlying RNTuple for RNTupleSingleProcessor, the name of the
55 /// first processor for RNTupleChainProcessor, or the name of the primary RNTuple for RNTupleJoinProcessor.
56 std::string fProcessorName = "";
57
58public:
59 /////////////////////////////////////////////////////////////////////////////
60 /// \brief Get the processor's name.
61 const std::string &GetProcessorName() const { return fProcessorName; }
62
63 /////////////////////////////////////////////////////////////////////////////
64 /// \brief Set the processor's name.
65 ///
66 /// \param[in] name Name to assign to the processor.
67 ///
68 /// By default, the processor name is the name of the underlying RNTuple for RNTupleSingleProcessor, the name of the
69 /// first processor for RNTupleChainProcessor, or the name of the primary RNTuple for RNTupleJoinProcessor.
70 void SetProcessorName(std::string_view name) { fProcessorName = name; }
71};
72
73// clang-format off
74/**
75\class ROOT::RNTupleProcessorValuePtr<T>
76\ingroup NTuple
77\brief The RNTupleProcessorValuePtr provides access to values from fields present in an RNTupleProcessor, with support
78and checks for missing values.
79*/
80// clang-format on
81template <typename T>
83 friend class RNTupleProcessor;
84
85private:
88
94
95 /////////////////////////////////////////////////////////////////////////////
96 /// \brief Get a non-owning pointer to the field value managed by the processor's entry.
97 ///
98 /// \return A `T*` if the field is valid in the current entry, or a `nullptr` otherwise.
99 T *GetRawPtr() const { return GetPtr().get(); }
100
101 /////////////////////////////////////////////////////////////////////////////
102 /// \brief Bind the value to `valuePtr`.
103 ///
104 /// \param[in] valuePtr Pointer to bind the value to.
105 ///
106 /// \warning Use this function with care! Values may not always be valid for every entry during processing, for
107 /// example when a field is not present in one of the chained processors or when during a join operation, no matching
108 /// entry in the auxiliary processor can be found. Reading `valuePtr` as-is therefore comes with the risk of reading
109 /// invalid data. After binding a pointer to an `RNTupleProcessorValuePtr`, we *strongly* recommend only accessing
110 /// its data through this interface, to ensure that only valid data can be read.
111 void BindRawPtr(T *valuePtr) { fProcessorEntry->BindRawPtr(fFieldIndex, valuePtr); }
112
113public:
114 /////////////////////////////////////////////////////////////////////////////
115 /// \brief Check if the pointer currently holds a valid value.
117
118 /////////////////////////////////////////////////////////////////////////////
119 /// \brief Get a shared pointer to the field value managed by the processor's entry.
120 ///
121 /// \return A `std::shared_ptr<T>` if the field is valid in the current entry, or a `nullptr` otherwise.
122 std::shared_ptr<T> GetPtr() const
123 {
126 return value.template GetPtr<T>();
127 }
128
129 return nullptr;
130 }
131
132 /////////////////////////////////////////////////////////////////////////////
133 /// \brief Bind the value to `valuePtr`.
134 ///
135 /// \param[in] valuePtr Pointer to bind the value to.
136 ///
137 /// \warning Use this function with care! Values may not always be valid for every entry during processing, for
138 /// example when a field is not present in one of the chained processors or when during a join operation, no matching
139 /// entry in the auxiliary processor can be found. Reading `valuePtr` as-is therefore comes with the risk of reading
140 /// invalid data. After binding a pointer to an `RNTupleProcessorValuePtr`, we *strongly* recommend only accessing
141 /// its data through this interface, to ensure that only valid data can be read.
142 void Bind(std::shared_ptr<T> valuePtr) { fProcessorEntry->Bind(fFieldIndex, std::move(valuePtr)); }
143
144 /////////////////////////////////////////////////////////////////////////////
145 /// \brief Get a reference to the field value managed by the processor's entry.
146 ///
147 /// Throws an exception if the field is invalid in the processor's current entry.
148 const T &operator*() const
149 {
150 if (auto ptr = GetPtr())
151 return *ptr;
152 else
153 throw RException(R__FAIL("cannot read \"" + fProcessorEntry->FindFieldName(fFieldIndex) +
154 "\" because it has no value for the current entry"));
155 }
156
157 /////////////////////////////////////////////////////////////////////////////
158 /// \brief Access the field value managed by the processor's entry.
159 ///
160 /// Throws an exception if the field is invalid in the processor's current entry.
161 const T *operator->() const
162 {
163 if (auto ptr = GetPtr())
164 return ptr.get();
165 else
166 throw RException(R__FAIL("cannot read \"" + fProcessorEntry->FindFieldName(fFieldIndex) +
167 "\" because it has no value for the current entry"));
168 }
169
171 {
172 return lhs.fProcessorEntry == rhs.fProcessorEntry && lhs.fFieldIndex == rhs.fFieldIndex;
173 }
174};
175
176// clang-format off
177/**
178\class ROOT::RNTupleProcessorValuePtr<void>
179\ingroup NTuple
180\brief Specialization of RNTupleProcessorValuePtr<T> for `void`-type pointers.
181*/
182// clang-format on
183template <>
185 friend class RNTupleProcessor;
186
187private:
190
196
197 /////////////////////////////////////////////////////////////////////////////
198 /// \brief Get a non-owning pointer to the field value managed by the processor's entry.
199 ///
200 /// \return A `void*` if the field is valid in the current entry, or a `nullptr` otherwise.
201 void *GetRawPtr() const { return GetPtr().get(); }
202
203 /////////////////////////////////////////////////////////////////////////////
204 /// \brief Bind the value to `valuePtr`.
205 ///
206 /// \param[in] valuePtr Pointer to bind the value to.
207 ///
208 /// \warning Use this function with care! Values may not always be valid for every entry during processing, for
209 /// example when a field is not present in one of the chained processors or when during a join operation, no matching
210 /// entry in the auxiliary processor can be found. Reading `valuePtr` as-is therefore comes with the risk of reading
211 /// invalid data. After binding a pointer to an `RNTupleProcessorValuePtr`, we *strongly* recommend only accessing
212 /// its data through this interface, to ensure that only valid data can be read.
213 void BindRawPtr(void *valuePtr) { fProcessorEntry->BindRawPtr(fFieldIndex, valuePtr); }
214
215public:
216 /////////////////////////////////////////////////////////////////////////////
217 /// \brief Check if the pointer currently holds a valid value.
219
220 /////////////////////////////////////////////////////////////////////////////
221 /// \brief Get the pointer to the field value managed by the processor's entry.
222 ///
223 /// \return A `std::shared_ptr<void>` if the field is valid in the current entry, or a `nullptr` otherwise.
224 std::shared_ptr<void> GetPtr() const
225 {
228 return value.template GetPtr<void>();
229 }
230
231 return nullptr;
232 }
233
234 /////////////////////////////////////////////////////////////////////////////
235 /// \brief Bind the value to `valuePtr`.
236 ///
237 /// \param[in] valuePtr Pointer to bind the value to.
238 ///
239 /// \warning Use this function with care! Values may not always be valid for every entry during processing, for
240 /// example when a field is not present in one of the chained processors or when during a join operation, no matching
241 /// entry in the auxiliary processor can be found. Reading `valuePtr` as-is therefore comes with the risk of reading
242 /// invalid data. After binding a pointer to an `RNTupleProcessorValuePtr`, we *strongly* recommend only accessing
243 /// its data through this interface, to ensure that only valid data can be read.
244 void Bind(std::shared_ptr<void> valuePtr) { fProcessorEntry->Bind(fFieldIndex, std::move(valuePtr)); }
245
247 {
248 return lhs.fProcessorEntry == rhs.fProcessorEntry && lhs.fFieldIndex == rhs.fFieldIndex;
249 }
250};
251
252// clang-format off
253/**
254\class ROOT::RNTupleProcessor
255\ingroup NTuple
256\brief Interface for iterating over entries of vertically ("chained") and/or horizontally ("joined") combined RNTuples.
257
258Example usage (see ntpl012_processor_chain.C and ntpl015_processor_join.C for bigger examples):
259
260~~~{.cpp}
261#include <ROOT/RNTupleProcessor.hxx>
262
263std::vector<ROOT::RNTupleInputSpec> ntuples = {{"ntuple1", "ntuple1.root"}, {"ntuple2", "ntuple2.root"}};
264auto processor = ROOT::RNTupleProcessor::CreateChain(ntuples);
265
266auto pt = processor->RequestField<float>("pt");
267
268for (const auto &idx : *processor) {
269 processor->LoadEntry(idx);
270 std::cout << "event = " << idx.GetEntryNumber() << ", pt = " << *pt << std::endl;
271}
272~~~
273
274An RNTupleProcessor is created either:
2751. By providing one or more RNTupleInputSpecs, each of which contains the name and storage location of a single RNTuple;
2762. By providing a previously created RNTupleProcessor.
277
278The RNTupleProcessor provides an iterator which gives access to the index of the current *global* entry of the
279processor, i.e. taking into account previously processed RNTuples.
280
281Because the schemas of each RNTuple that are part of an RNTupleProcessor may not necessarily be identical, or because
282it can occur that entries are only partially complete in a join-based processor, field values may be marked as
283"invalid", at which point their data should not be read. This is handled by the RNTupleProcessorValuePtr
284that is returned by RequestField().
285*/
286// clang-format on
288 friend struct ROOT::Internal::RNTupleProcessorEntryLoader; // for unit tests
291 bool includeSubfields); // For unit tests
296
297protected:
298 /////////////////////////////////////////////////////////////////////////////
299 /// \brief Maps a processor's global (outer) entry index to its inner ones
304
305 private:
307
308 // Used by chain processors
309 std::size_t fInnerProcessorIdx = 0;
310 std::unique_ptr<REntryMapping> fInnerMapping = nullptr;
311
312 // Used by join processors
313 std::unique_ptr<REntryMapping> fPrimaryMapping = nullptr;
314 std::unique_ptr<REntryMapping> fAuxiliaryMapping = nullptr;
315
316 void SetEntryNumber(ROOT::NTupleSize_t entryNumber) { fEntryNumber = entryNumber; }
317
318 std::size_t GetInnerProcessorIdx() const { return fInnerProcessorIdx; }
319 void SetInnerProcessorIdx(std::size_t idx) { fInnerProcessorIdx = idx; }
320
322 {
323 if (!fInnerMapping)
324 fInnerMapping = std::make_unique<REntryMapping>();
325 return *fInnerMapping;
326 }
327
329 {
330 assert(fInnerMapping);
331 return *fInnerMapping;
332 }
333
335 {
336 if (!fPrimaryMapping)
337 fPrimaryMapping = std::make_unique<REntryMapping>();
338 return *fPrimaryMapping;
339 }
340
342 {
343 assert(fPrimaryMapping);
344 return *fPrimaryMapping;
345 }
346
348 {
350 fAuxiliaryMapping = std::make_unique<REntryMapping>();
351 return *fAuxiliaryMapping;
352 }
353
355 {
356 assert(fAuxiliaryMapping);
357 return *fAuxiliaryMapping;
358 }
359
360 friend bool operator==(const REntryMapping &lhs, const REntryMapping &rhs)
361 {
362 return lhs.fEntryNumber == rhs.fEntryNumber && lhs.fInnerProcessorIdx == rhs.fInnerProcessorIdx &&
363 ((lhs.fInnerMapping == nullptr && rhs.fInnerMapping == nullptr) ||
364 *lhs.fInnerMapping == *rhs.fInnerMapping) &&
365 ((lhs.fPrimaryMapping == nullptr && rhs.fPrimaryMapping == nullptr) ||
366 *lhs.fPrimaryMapping == *rhs.fPrimaryMapping) &&
367 ((lhs.fAuxiliaryMapping == nullptr && rhs.fAuxiliaryMapping == nullptr) ||
369 }
370
371 friend bool operator!=(const REntryMapping &lhs, const REntryMapping &rhs) { return !(lhs == rhs); }
372
373 public:
374 REntryMapping() = default;
376 {
379 fInnerMapping = other.fInnerMapping ? std::make_unique<REntryMapping>(*other.fInnerMapping) : nullptr;
380 fPrimaryMapping = other.fPrimaryMapping ? std::make_unique<REntryMapping>(*other.fPrimaryMapping) : nullptr;
382 other.fAuxiliaryMapping ? std::make_unique<REntryMapping>(*other.fAuxiliaryMapping) : nullptr;
383 }
384 REntryMapping(REntryMapping &&other) = default;
386 {
389 fInnerMapping = other.fInnerMapping ? std::make_unique<REntryMapping>(*other.fInnerMapping) : nullptr;
390 fPrimaryMapping = other.fPrimaryMapping ? std::make_unique<REntryMapping>(*other.fPrimaryMapping) : nullptr;
392 other.fAuxiliaryMapping ? std::make_unique<REntryMapping>(*other.fAuxiliaryMapping) : nullptr;
393 return *this;
394 }
396 ~REntryMapping() = default;
397
399
401 };
402
404
405 std::shared_ptr<ROOT::Internal::RNTupleProcessorEntry> fEntry = nullptr;
406 std::unordered_set<Internal::RNTupleProcessorEntry::FieldIndex_t> fFieldIdxs;
407
408 /// Total number of entries. Only to be used internally by the processor, not meant to be exposed in the public
409 /// interface.
411
412 ROOT::NTupleSize_t fNEntriesProcessed = 0; //< Total number of entries processed so far
413
414 /////////////////////////////////////////////////////////////////////////////
415 /// \brief Initialize the processor by creating an (initially empty) `fEntry`, or setting an existing one.
416 virtual void Initialize(std::shared_ptr<ROOT::Internal::RNTupleProcessorEntry> entry) = 0;
417
418 /////////////////////////////////////////////////////////////////////////////
419 /// \brief Check if the processor already has been initialized.
420 bool IsInitialized() const { return fEntry != nullptr; }
421
422 /////////////////////////////////////////////////////////////////////////////
423 /// \brief Connect fields to the page source of the processor's underlying RNTuple(s).
424 ///
425 /// \param[in] fieldIdxs Indices of the fields to connect.
426 /// \param[in] provenance Provenance of the processor.
427 /// \param[in] updateFields Whether the fields in the entry need to be updated, because the current underlying
428 /// RNTuple source changed.
429 virtual void Connect(const std::unordered_set<Internal::RNTupleProcessorEntry::FieldIndex_t> &fieldIdxs,
430 const Internal::RNTupleProcessorProvenance &provenance, bool updateFields) = 0;
431
432 /////////////////////////////////////////////////////////////////////////////
433 /// \brief Disconnect the processor from associated physical storage.
434 virtual void Disconnect() = 0;
435
436 /////////////////////////////////////////////////////////////////////////////
437 /// \brief Set the local entry mapping (for nested processors), according to a global entry number.
438 ///
439 /// \param[in] entryNumber Global entry number to map to
440 /// \param[in] mapping Entry mapping to update
441 virtual void SetEntryMapping(ROOT::NTupleSize_t globalEntryNumber, REntryMapping &mapping) = 0;
442
443 /////////////////////////////////////////////////////////////////////////////
444 /// \brief Increment the local entry mapping by one.
445 ///
446 /// \param[in] mapping Entry mapping to increment
447 void IncrementEntryMapping(REntryMapping &mapping) { SetEntryMapping(mapping.GetEntryNumber() + 1, mapping); }
448
449 /////////////////////////////////////////////////////////////////////////////
450 /// \brief Load the entry identified by the entry mapping.
451 ///
452 /// \param[in] mapping Mapping to the entry to load
453 virtual void LoadEntryImpl(const REntryMapping &mapping) = 0;
454
455 /////////////////////////////////////////////////////////////////////////////
456 /// \brief Get a reference to the processor's internal entry.
458
459 /////////////////////////////////////////////////////////////////////////////
460 /// \brief Get a reference to the processor's internal entry.
462
463 /////////////////////////////////////////////////////////////////////////////
464 /// \brief Get the total number of entries in this processor
466
467 /////////////////////////////////////////////////////////////////////////////
468 /// \brief Check if a field exists on-disk and can be read by the processor.
469 ///
470 /// \param[in] fieldName Name of the field to check.
471 virtual bool CanReadFieldFromDisk(std::string_view fieldName) = 0;
472
473 /////////////////////////////////////////////////////////////////////////////
474 /// \brief Add a field to the entry.
475 ///
476 ///
477 /// \param[in] canonicalFieldName Canonical name of the field to add. This includes the prefix of any parent fields,
478 /// as well as the auxiliary processor name prefix, if present.
479 /// \param[in] typeName Type of the field to add.
480 /// \param[in] valuePtr Pointer to bind to the field's value in the entry. If this is a `nullptr`, a pointer will be
481 /// created.
482 /// \param[in] provenance Provenance of the processor.
483 ///
484 /// \return The index of the newly added field in the entry.
485 ///
486 /// In case the field was already present in the entry, the index of the existing field is returned.
488 AddFieldToEntry(const std::string &canonicalFieldName, const std::string &typeName, void *valuePtr,
489 const Internal::RNTupleProcessorProvenance &provenance) = 0;
490
491 /////////////////////////////////////////////////////////////////////////////
492 /// \brief Add a field to the entry.
493 ///
494 ///
495 /// \param[in] field The field to add.
496 /// \param[in] canonicalFieldName Canonical name of the field to add. This includes the prefix of any parent fields,
497 /// as well as the auxiliary processor name prefix, if present. This is different from the field name stored in
498 /// `field`.
499 /// \param[in] valuePtr Pointer to bind to the field's value in the entry. If this is a `nullptr`, a pointer will be
500 /// created.
501 /// \param[in] provenance Provenance of the processor.
502 ///
503 /// \return The index of the newly added field in the entry.
504 ///
505 /// In case the field was already present in the entry, the index of the existing field is returned.
507 AddFieldToEntry(std::unique_ptr<ROOT::RFieldBase> field, const std::string &canonicalFieldName, void *valuePtr,
508 const Internal::RNTupleProcessorProvenance &provenance) = 0;
509
510 /////////////////////////////////////////////////////////////////////////////
511 /// \brief Add all known fields (from on-disk information) to the entry.
512 ///
513 /// \param[in] provenance Provenance of the processor.
514 /// \param[in] addFieldMode Bitfield indicating how the fields should be added.
515 virtual void AddAllFieldsToEntry(const Internal::RNTupleProcessorProvenance &provenance, bool includeSubfields) = 0;
516
517 /////////////////////////////////////////////////////////////////////////////
518 /// \brief Add the entry mappings for this processor to the provided join table.
519 ///
520 /// \param[in] joinTable the join table to map the entries to.
521 /// \param[in] entryOffset In case the entry mapping is added from a chain, the offset of the entry indexes to use
522 /// with respect to the processor's position in the chain.
523 virtual void
525
526 /////////////////////////////////////////////////////////////////////////////
527 /// \brief Processor-specific implementation for printing its structure, called by PrintStructure().
528 ///
529 /// \param[in,out] output Output stream to print to.
530 virtual void PrintStructureImpl(std::ostream &output) const = 0;
531
532 /////////////////////////////////////////////////////////////////////////////
533 /// \brief Create a new base RNTupleProcessor.
534 ///
535 /// \param[in] processorName Name of the processor. By default, this is the name of the underlying RNTuple for
536 /// RNTupleSingleProcessor, the name of the first processor for RNTupleChainProcessor, or the name of the primary
537 /// RNTuple for RNTupleJoinProcessor.
539
540public:
545 virtual ~RNTupleProcessor() = default;
546
547 /////////////////////////////////////////////////////////////////////////////
548 /// \brief Get the options used for this processor.
549 const RNTupleProcessorOptions &GetOptions() const { return fOptions; }
550
551 /////////////////////////////////////////////////////////////////////////////
552 /// \brief Get the total number of entries processed so far.
554
555 /////////////////////////////////////////////////////////////////////////////
556 /// \brief Request access to a field for reading during processing.
557 ///
558 /// \tparam T Type of the requested field.
559 ///
560 /// \param[in] fieldName Name of the requested field.
561 /// \param[in] valuePtr Pointer to bind to the field's value in the entry. If this is a `nullptr`, a pointer will be
562 /// created.
563 ///
564 /// \return An RNTupleProcessorValuePtr of type `T`, which provides access to the field's value.
565 ///
566 /// \warning Provide a `valuePtr` with care! Values may not always be valid for every entry during processing, for
567 /// example when a field is not present in one of the chained processors or when during a join operation, no matching
568 /// entry in the auxiliary processor can be found. Reading `valuePtr` as-is therefore comes with the risk of reading
569 /// invalid data. After passing a pointer to `RequestField`, we *strongly* recommend only accessing its data through
570 /// the interface of the returned `RNTupleProcessorValuePtr`, to ensure that only valid data can be read.
571 template <typename T>
572 RNTupleProcessorValuePtr<T> RequestField(const std::string &fieldName, void *valuePtr = nullptr)
573 {
575 std::string typeName{};
576 if constexpr (!std::is_void_v<T>) {
577 typeName = ROOT::Internal::GetRenormalizedTypeName(typeid(T));
578 }
579
580 // The field already exists, so return the existing one.
581 if (auto fieldIdx = fEntry->FindFieldIndex(fieldName, typeName)) {
582 auto value = fEntry->GetValue(*fieldIdx);
583 // Need to check that the provided pointer is not conflicting with the existing one
584
585 if (valuePtr != nullptr && valuePtr != value.GetPtr<void>().get()) {
586 throw RException(R__FAIL("attempted to request a field with user-provided value pointer to field \"" +
587 fieldName +
588 "\", which already exists in the entry. To change the underlying value pointer, "
589 "use RNTupleProcessorValuePtr::Bind instead."));
590 }
591 return RNTupleProcessorValuePtr<T>(fEntry.get(), *fieldIdx);
592 }
593
594 auto fieldIdx = AddFieldToEntry(fieldName, typeName, valuePtr, Internal::RNTupleProcessorProvenance());
595 return RNTupleProcessorValuePtr<T>(fEntry.get(), fieldIdx);
596 }
597
598 /////////////////////////////////////////////////////////////////////////////
599 /// \brief Request access to a field for reading during processing.
600 ///
601 /// \param[in] fieldName Name of the requested field.
602 /// \param[in] typeName Type of the requested field.
603 /// \param[in] valuePtr Pointer to bind to the field's value in the entry. If this is a `nullptr`, a pointer will be
604 /// created.
605 ///
606 /// \return An void-type RNTupleProcessorValuePtr, which provides access to the field's value.
607 ///
608 /// \warning Provide a `valuePtr` with care! Values may not always be valid for every entry during processing, for
609 /// example when a field is not present in one of the chained processors or when during a join operation, no matching
610 /// entry in the auxiliary processor can be found. Reading `valuePtr` as-is therefore comes with the risk of reading
611 /// invalid data. After passing a pointer to `RequestField`, we *strongly* recommend only accessing its data through
612 /// the interface of the returned `RNTupleProcessorValuePtr`, to ensure that only valid data can be read.
614 RequestField(const std::string &fieldName, const std::string &typeName, void *valuePtr = nullptr)
615 {
617 auto fieldIdx = AddFieldToEntry(fieldName, typeName, valuePtr, Internal::RNTupleProcessorProvenance());
618 return RNTupleProcessorValuePtr<void>(fEntry.get(), fieldIdx);
619 }
620
621 /////////////////////////////////////////////////////////////////////////////
622 /// \brief Load the entry identified by the entry mapping.
623 ///
624 /// \param[in] mapping Mapping to the entry to load
625 void LoadEntry(const REntryMapping &mapping) { LoadEntryImpl(mapping); }
626
627 /////////////////////////////////////////////////////////////////////////////
628 /// \brief Print a graphical representation of the processor composition.
629 ///
630 /// \param[in,out] output Stream to print to (default is stdout).
631 ///
632 /// ### Example:
633 /// The structure of a processor representing a join between a single primary RNTuple and a chain of two auxiliary
634 /// RNTuples will be printed as follows:
635 /// ~~~
636 /// +-----------------------------+ +-----------------------------+
637 /// | ntuple | | ntuple_aux |
638 /// | ntuple.root | | ntuple_aux1.root |
639 /// +-----------------------------+ +-----------------------------+
640 /// +-----------------------------+
641 /// | ntuple_aux |
642 /// | ntuple_aux2.root |
643 /// +-----------------------------+
644 /// ~~~
645 void PrintStructure(std::ostream &output = std::cout) { PrintStructureImpl(output); }
646
647 // clang-format off
648 /**
649 \class ROOT::RNTupleProcessor::RIterator
650 \ingroup NTuple
651 \brief Iterator over the entries of an RNTuple, or vertical concatenation thereof.
652 */
653 // clang-format on
654 class RIterator {
655 private:
658
659 public:
660 using iterator_category = std::forward_iterator_tag;
664
665 RIterator(RNTupleProcessor &processor, ROOT::NTupleSize_t firstEntryIdx) : fProcessor(processor)
666 {
667 if (fProcessor.fEntry && firstEntryIdx != ROOT::kInvalidNTupleIndex) {
669 /*updateFields=*/false);
671 }
672 }
673
675 {
677
678 return *this;
679 }
680
682 {
683 auto obj = *this;
684 ++(*this);
685 return obj;
686 }
687
689
690 const value_type *operator->() const { return &fEntryMapping; }
691
692 friend bool operator!=(const iterator &lh, const iterator &rh)
693 {
695 }
696 friend bool operator==(const iterator &lh, const iterator &rh)
697 {
699 }
700 };
701
702 RIterator begin() { return RIterator(*this, 0); }
704
705 /////////////////////////////////////////////////////////////////////////////
706 /// \brief Create an RNTupleProcessor for a single RNTuple.
707 ///
708 /// \param[in] ntuple The name and storage location of the RNTuple to process.
709 /// \param[in] opts Options for the processor.
710 ///
711 /// \return A pointer to the newly created RNTupleProcessor.
712 static std::unique_ptr<RNTupleProcessor>
714
715 /////////////////////////////////////////////////////////////////////////////
716 /// \brief Create an RNTupleProcessor for a *chain* (i.e., a vertical combination) of RNTuples.
717 ///
718 /// \param[in] ntuples A list specifying the names and locations of the RNTuples to process.
719 /// \param[in] opts Options for the processor.
720 ///
721 /// \return A pointer to the newly created RNTupleProcessor.
722 static std::unique_ptr<RNTupleProcessor>
723 CreateChain(std::vector<RNTupleInputSpec> ntuples, const RNTupleProcessorOptions &opts = RNTupleProcessorOptions());
724
725 /////////////////////////////////////////////////////////////////////////////
726 /// \brief Create an RNTupleProcessor for a *chain* (i.e., a vertical combination) of other RNTupleProcessors.
727 ///
728 /// \param[in] innerProcessors A list with the processors to chain.
729 /// \param[in] opts Options for the processor.
730 ///
731 /// \return A pointer to the newly created RNTupleProcessor.
732 static std::unique_ptr<RNTupleProcessor>
733 CreateChain(std::vector<std::unique_ptr<RNTupleProcessor>> innerProcessors,
735};
736
737// clang-format off
738/**
739\class ROOT::RNTupleSingleProcessor
740\ingroup NTuple
741\brief Processor specialization for processing a single RNTuple.
742*/
743// clang-format on
745 friend class RNTupleProcessor;
746
747private:
749 std::unique_ptr<ROOT::Internal::RPageSource> fPageSource;
750
751 /////////////////////////////////////////////////////////////////////////////
752 /// \brief Create a new field and connect it to the processor's page source.
753 ///
754 /// \param[in] qualifiedFieldName Name of the field to add, prefixed with its parent fields, if applicable.
755 /// \param[in] typeName Type of the field to add.
756 ///
757 /// \return The newly created field.
758 /// \throws ROOT::RException In case the requested field cannot be found on disk.
759 std::unique_ptr<ROOT::RFieldBase>
760 CreateAndConnectField(const std::string &qualifiedFieldName, const std::string &typeName);
761
762 /////////////////////////////////////////////////////////////////////////////
763 /// \brief Connect an existing field to the processor's page source.
764 ///
765 /// \param[in] field Pointer to the field to add
766 ///
767 /// \return The same field, but wrapped in a new unique pointer. This is needed, because in order to add the field to
768 /// the page source it first needs to be attached to its zero field, in order to correctly handle field
769 /// substitutions. Afterwards, we release the field again from the zero field.
770 std::unique_ptr<ROOT::RFieldBase> ConnectField(std::unique_ptr<ROOT::RFieldBase> field);
771
772 /////////////////////////////////////////////////////////////////////////////
773 /// \brief Initialize the processor by creating an (initially empty) `fEntry`, or setting an existing one.
774 ///
775 /// At this point, the page source for the underlying RNTuple of the processor will be created and opened.
776 void Initialize(std::shared_ptr<ROOT::Internal::RNTupleProcessorEntry> entry = nullptr) final;
777
778 /////////////////////////////////////////////////////////////////////////////
779 /// \brief Connect the provided fields indices in the entry to their on-disk fields.
780 void Connect(const std::unordered_set<Internal::RNTupleProcessorEntry::FieldIndex_t> &fieldIdxs,
781 const Internal::RNTupleProcessorProvenance &provenance = Internal::RNTupleProcessorProvenance(),
782 bool updateFields = false) final;
783
784 /////////////////////////////////////////////////////////////////////////////
785 /// \brief Disconnect the processor from associated physical storage.
786 void Disconnect() final;
787
788 /////////////////////////////////////////////////////////////////////////////
789 /// \brief Set the local entry mapping (for nested processors), according to a global entry number.
790 ///
791 /// \sa ROOT::RNTupleProcessor::SetEntryMapping
792 void SetEntryMapping(ROOT::NTupleSize_t globalEntryNumber, REntryMapping &mapping) final;
793
794 /////////////////////////////////////////////////////////////////////////////
795 /// \brief Load the entry identified by the entry mapping.
796 ///
797 /// \sa ROOT::RNTupleProcessor::LoadEntryImpl
798 void LoadEntryImpl(const REntryMapping &mapping) final;
799
800 /////////////////////////////////////////////////////////////////////////////
801 /// \brief Get the total number of entries in this processor.
803
804 /////////////////////////////////////////////////////////////////////////////
805 /// \brief Check if a field exists on-disk and can be read by the processor.
806 ///
807 /// \sa RNTupleProcessor::CanReadFieldFromDisk()
808 bool CanReadFieldFromDisk(std::string_view fieldName) final;
809
810 /////////////////////////////////////////////////////////////////////////////
811 /// \brief Add a field to the entry.
812 ///
813 /// \sa RNTupleProcessor::AddFieldToEntry()
814 Internal::RNTupleProcessorEntry::FieldIndex_t AddFieldToEntry(
815 const std::string &fieldName, const std::string &typeName, void *valuePtr = nullptr,
816 const Internal::RNTupleProcessorProvenance &provenance = Internal::RNTupleProcessorProvenance()) final;
817
818 /////////////////////////////////////////////////////////////////////////////
819 /// \brief Add a field to the entry.
820 ///
821 /// \sa RNTupleProcessor::AddFieldToEntry()
822 Internal::RNTupleProcessorEntry::FieldIndex_t
823 AddFieldToEntry(std::unique_ptr<ROOT::RFieldBase> field, const std::string &fieldName, void *valuePtr,
824 const Internal::RNTupleProcessorProvenance &provenance) final;
825
826 /////////////////////////////////////////////////////////////////////////////
827 /// \brief Add all known fields (from on-disk information) to the entry.
828 ///
829 /// \sa RNTupleProcessor::AddAllFieldsToEntry()
830 void AddAllFieldsToEntry(const Internal::RNTupleProcessorProvenance &provenance, bool includeSubfields) final;
831
832 /////////////////////////////////////////////////////////////////////////////
833 /// \brief Add the entry mappings for this processor to the provided join table.
834 ///
835 /// \sa ROOT::RNTupleProcessor::AddEntriesToJoinTable
836 void
837 AddEntriesToJoinTable(Experimental::Internal::RNTupleJoinTable &joinTable, ROOT::NTupleSize_t entryOffset = 0) final;
838
839 /////////////////////////////////////////////////////////////////////////////
840 /// \brief Processor-specific implementation for printing its structure, called by PrintStructure().
841 ///
842 /// \sa ROOT::RNTupleProcessor::PrintStructureImpl
843 void PrintStructureImpl(std::ostream &output) const final;
844
845 /////////////////////////////////////////////////////////////////////////////
846 /// \brief Construct a new RNTupleProcessor for processing a single RNTuple.
847 ///
848 /// \param[in] ntuple The source specification (name and storage location) for the RNTuple to process.
849 /// \param[in] opts Options for the processor.
851
852public:
855 RNTupleSingleProcessor &operator=(const RNTupleSingleProcessor &) = delete;
858 {
859 // The entry's fields need to be deleted before fPageSource.
860 if (fEntry)
861 fEntry->Clear();
862 };
863};
864
865// clang-format off
866/**
867\class ROOT::RNTupleChainProcessor
868\ingroup NTuple
869\brief Processor specialization for vertically combined (*chained*) RNTupleProcessors.
870*/
871// clang-format on
873 friend class RNTupleProcessor;
874
875private:
876 std::vector<std::unique_ptr<RNTupleProcessor>> fInnerProcessors;
877 std::vector<ROOT::NTupleSize_t> fInnerNEntries;
878
879 ROOT::NTupleSize_t fLastLoadedEntry = 0; //< Last (global) entry number that was loaded
880 std::size_t fCurrentProcessorNumber = 0; //< Number of the currently open inner processor
881
883
884 /////////////////////////////////////////////////////////////////////////////
885 /// \brief Initialize the processor by creating an (initially empty) `fEntry`, or setting an existing one.
886 void Initialize(std::shared_ptr<ROOT::Internal::RNTupleProcessorEntry> entry = nullptr) final;
887
888 /////////////////////////////////////////////////////////////////////////////
889 /// \brief Connect the provided fields indices in the entry to their on-disk fields.
890 ///
891 /// \sa RNTupleProcessor::Connect()
892 void Connect(const std::unordered_set<Internal::RNTupleProcessorEntry::FieldIndex_t> &fieldIdxs,
893 const Internal::RNTupleProcessorProvenance &provenance = Internal::RNTupleProcessorProvenance(),
894 bool updateFields = false) final;
895
896 /////////////////////////////////////////////////////////////////////////////
897 /// \brief Update the entry to reflect any missing fields in the current inner processor.
898 void ConnectInnerProcessor(std::size_t processorNumber);
899
900 /////////////////////////////////////////////////////////////////////////////
901 /// \brief Disconnect the processor from associated physical storage.
902 void Disconnect() final;
903
904 /////////////////////////////////////////////////////////////////////////////
905 /// \brief Set the local entry mapping (for nested processors), according to a global entry number.
906 ///
907 /// \sa ROOT::RNTupleProcessor::SetEntryMapping
908 void SetEntryMapping(ROOT::NTupleSize_t globalEntryNumber, REntryMapping &mapping) final;
909
910 /////////////////////////////////////////////////////////////////////////////
911 /// \brief Load the entry identified by the entry mapping.
912 ///
913 /// \sa ROOT::RNTupleProcessor::LoadEntryImpl
914 void LoadEntryImpl(const REntryMapping &mapping) final;
915
916 /////////////////////////////////////////////////////////////////////////////
917 /// \brief Get the total number of entries in this processor.
918 ///
919 /// \note This requires opening all underlying RNTuples being processed in the chain, and could become costly!
921
922 /////////////////////////////////////////////////////////////////////////////
923 /// \brief Check if a field exists on-disk and can be read by the processor.
924 ///
925 /// \sa RNTupleProcessor::CanReadFieldFromDisk()
926 bool CanReadFieldFromDisk(std::string_view fieldName) final
927 {
928 return fInnerProcessors[fCurrentProcessorNumber]->CanReadFieldFromDisk(fieldName);
929 }
930
931 /////////////////////////////////////////////////////////////////////////////
932 /// \brief Add a field to the entry.
933 ///
934 /// \sa RNTupleProcessor::AddFieldToEntry()
936 const std::string &fieldName, const std::string &typeName, void *valuePtr = nullptr,
938
939 /////////////////////////////////////////////////////////////////////////////
940 /// \brief Add a field to the entry.
941 ///
942 /// \sa RNTupleProcessor::AddFieldToEntry()
943 Internal::RNTupleProcessorEntry::FieldIndex_t
944 AddFieldToEntry(std::unique_ptr<ROOT::RFieldBase> field, const std::string &fieldName, void *valuePtr,
945 const Internal::RNTupleProcessorProvenance &provenance) final;
946
947 /////////////////////////////////////////////////////////////////////////////
948 /// \brief Add all known fields (from on-disk information) to the entry.
949 ///
950 /// \sa RNTupleProcessor::AddAllFieldsToEntry()
951 void AddAllFieldsToEntry(const Internal::RNTupleProcessorProvenance &provenance, bool includeSubfields) final;
952
953 /////////////////////////////////////////////////////////////////////////////
954 /// \brief Add the entry mappings for this processor to the provided join table.
955 ///
956 /// \sa ROOT::RNTupleProcessor::AddEntriesToJoinTable
957 void
958 AddEntriesToJoinTable(Experimental::Internal::RNTupleJoinTable &joinTable, ROOT::NTupleSize_t entryOffset = 0) final;
959
960 /////////////////////////////////////////////////////////////////////////////
961 /// \brief Processor-specific implementation for printing its structure, called by PrintStructure().
962 ///
963 /// \sa ROOT::RNTupleProcessor::PrintStructureImpl
964 void PrintStructureImpl(std::ostream &output) const final;
965
966 /////////////////////////////////////////////////////////////////////////////
967 /// \brief Construct a new RNTupleChainProcessor.
968 ///
969 /// \param[in] ntuples The source specification (name and storage location) for each RNTuple to process.
970 /// \param[in] opts Options for the processor.
971 ///
972 /// RNTuples are processed in the order in which they are specified.
973 RNTupleChainProcessor(std::vector<std::unique_ptr<RNTupleProcessor>> processors,
974 const RNTupleProcessorOptions &opts);
975
976public:
979 RNTupleChainProcessor &operator=(const RNTupleChainProcessor &) = delete;
981 ~RNTupleChainProcessor() override = default;
982};
983
984namespace Experimental {
985/////////////////////////////////////////////////////////////////////////////
986/// \brief Create an RNTupleProcessor for a *join* (i.e., a horizontal combination) of RNTuples.
987///
988/// \param[in] primaryNTuple The name and location of the primary RNTuple. Its entries are processed in sequential
989/// order.
990/// \param[in] auxNTuple The name and location of the RNTuple to join the primary RNTuple with. The order in which
991/// its entries are processed is determined by the primary RNTuple and doesn't necessarily have to be sequential.
992/// \param[in] joinFields The names of the fields on which to join, in case the specified RNTuples are unaligned.
993/// The join is made based on the combined join field values, and therefore each field has to be present in each
994/// specified RNTuple. If an empty list is provided, it is assumed that the specified ntuple are fully aligned.
995/// \param[in] opts Options for the processor.
996///
997/// \return A pointer to the newly created RNTupleProcessor.
998// TODO(fdegeus) Move back to RNTupleProcessor::CreateJoin once RNTupleProcessor moves out of Experimental.
999std::unique_ptr<RNTupleProcessor>
1000CreateRNTupleJoinProcessor(RNTupleInputSpec primaryNTuple, RNTupleInputSpec auxNTuple,
1001 const std::vector<std::string> &joinFields,
1003
1004/////////////////////////////////////////////////////////////////////////////
1005/// \brief Create an RNTupleProcessor for a *join* (i.e., a horizontal combination) of RNTuples.
1006///
1007/// \param[in] primaryProcessor The primary processor. Its entries are processed in sequential order.
1008/// \param[in] auxProcessor The processor to join the primary processor with. The order in which its entries are
1009/// processed is determined by the primary processor and doesn't necessarily have to be sequential.
1010/// \param[in] joinFields The names of the fields on which to join, in case the specified processors are unaligned.
1011/// The join is made based on the combined join field values, and therefore each field has to be present in each
1012/// specified processors. If an empty list is provided, it is assumed that the specified processors are fully
1013/// aligned.
1014/// \param[in] opts Options for the processor.
1015///
1016/// \return A pointer to the newly created RNTupleProcessor.
1017// TODO(fdegeus) Move back to RNTupleProcessor::CreateJoin once RNTupleProcessor moves out of Experimental.
1018std::unique_ptr<RNTupleProcessor>
1019CreateRNTupleJoinProcessor(std::unique_ptr<RNTupleProcessor> primaryProcessor,
1020 std::unique_ptr<RNTupleProcessor> auxProcessor, const std::vector<std::string> &joinFields,
1022
1023// clang-format off
1024/**
1025\class ROOT::Experimental::RNTupleJoinProcessor
1026\ingroup NTuple
1027\brief Processor specialization for horizontally combined (*joined*) RNTupleProcessors.
1028*/
1029// clang-format on
1031 friend class RNTupleProcessor;
1032 friend std::unique_ptr<RNTupleProcessor>
1033 CreateRNTupleJoinProcessor(std::unique_ptr<RNTupleProcessor> primaryProcessor,
1034 std::unique_ptr<RNTupleProcessor> auxProcessor,
1035 const std::vector<std::string> &joinFields, const RNTupleProcessorOptions &opts);
1036
1037private:
1038 std::unique_ptr<RNTupleProcessor> fPrimaryProcessor;
1039 std::unique_ptr<RNTupleProcessor> fAuxiliaryProcessor;
1040
1041 std::vector<std::string> fJoinFieldNames;
1042 std::set<ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t> fJoinFieldIdxs;
1043
1044 std::unique_ptr<Internal::RNTupleJoinTable> fJoinTable;
1045 bool fJoinTableIsBuilt = false;
1046
1047 std::unordered_set<ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t> fAuxiliaryFieldIdxs;
1048
1049 /// \brief Initialize the processor by creating an (initially empty) `fEntry`, or setting an existing one.
1050 void Initialize(std::shared_ptr<ROOT::Internal::RNTupleProcessorEntry> entry = nullptr) final;
1051
1052 /////////////////////////////////////////////////////////////////////////////
1053 /// \brief Connect the provided fields indices in the entry to their on-disk fields.
1054 ///
1055 /// \sa RNTupleProcessor::Connect()
1056 void
1057 Connect(const std::unordered_set<ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t> &fieldIdxs,
1058 const ROOT::Internal::RNTupleProcessorProvenance &provenance = ROOT::Internal::RNTupleProcessorProvenance(),
1059 bool updateFields = false) final;
1060
1061 /////////////////////////////////////////////////////////////////////////////
1062 /// \brief Disconnect the processor from associated physical storage.
1063 void Disconnect() final;
1064
1065 /////////////////////////////////////////////////////////////////////////////
1066 /// \brief Set the local entry mapping (for nested processors), according to a global entry number.
1067 ///
1068 /// \sa ROOT::RNTupleProcessor::SetEntryMapping
1069 void SetEntryMapping(ROOT::NTupleSize_t globalEntryNumber, REntryMapping &mapping) final;
1070
1071 /////////////////////////////////////////////////////////////////////////////
1072 /// \brief Load the entry identified by the entry mapping.
1073 ///
1074 /// \sa ROOT::RNTupleProcessor::LoadEntryImpl
1075 void LoadEntryImpl(const REntryMapping &mapping) final;
1076
1077 /////////////////////////////////////////////////////////////////////////////
1078 /// \brief Get the total number of entries in this processor.
1079 ROOT::NTupleSize_t GetNEntries() final;
1080
1081 /////////////////////////////////////////////////////////////////////////////
1082 /// \brief Set the validity for all fields in the auxiliary processor at once.
1083 void SetAuxiliaryFieldValidity(bool validity);
1084
1085 /////////////////////////////////////////////////////////////////////////////
1086 /// \brief Check if a field exists on-disk and can be read by the processor.
1087 ///
1088 /// \sa RNTupleProcessor::CanReadFieldFromDisk()
1089 bool CanReadFieldFromDisk(std::string_view fieldName) final
1090 {
1091 if (!fPrimaryProcessor->CanReadFieldFromDisk(fieldName)) {
1092 if (fieldName.find(fAuxiliaryProcessor->fOptions.GetProcessorName()) == 0)
1093 fieldName = fieldName.substr(fAuxiliaryProcessor->fOptions.GetProcessorName().size() + 1);
1094 return fAuxiliaryProcessor->CanReadFieldFromDisk(fieldName);
1095 }
1096
1097 return true;
1098 }
1099
1100 /////////////////////////////////////////////////////////////////////////////
1101 /// \brief Add a field to the entry.
1102 ///
1103 /// \sa RNTupleProcessor::AddFieldToEntry()
1105 AddFieldToEntry(const std::string &fieldName, const std::string &typeName, void *valuePtr = nullptr,
1108
1109 /////////////////////////////////////////////////////////////////////////////
1110 /// \brief Add a field to the entry.
1111 ///
1112 /// \sa RNTupleProcessor::AddFieldToEntry()
1113 ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t
1114 AddFieldToEntry(std::unique_ptr<ROOT::RFieldBase> field, const std::string &fieldName, void *valuePtr,
1115 const ROOT::Internal::RNTupleProcessorProvenance &provenance) final;
1116
1117 /////////////////////////////////////////////////////////////////////////////
1118 /// \brief Add all known fields (from on-disk information) to the entry.
1119 ///
1120 /// \sa RNTupleProcessor::AddAllFieldsToEntry()
1121 void AddAllFieldsToEntry(const ROOT::Internal::RNTupleProcessorProvenance &provenance, bool includeSubfields) final;
1122
1123 /////////////////////////////////////////////////////////////////////////////
1124 /// \brief Add the entry mappings for this processor to the provided join table.
1125 ///
1126 /// \sa ROOT::RNTupleProcessor::AddEntriesToJoinTable
1127 void AddEntriesToJoinTable(Internal::RNTupleJoinTable &joinTable, ROOT::NTupleSize_t entryOffset = 0) final;
1128
1129 /////////////////////////////////////////////////////////////////////////////
1130 /// \brief Processor-specific implementation for printing its structure, called by PrintStructure().
1131 ///
1132 /// \sa ROOT::RNTupleProcessor::PrintStructureImpl
1133 void PrintStructureImpl(std::ostream &output) const final;
1134
1135 /////////////////////////////////////////////////////////////////////////////
1136 /// \brief Construct a new RNTupleJoinProcessor.
1137 /// \param[in] primaryProcessor The primary processor. Its entries are processed in sequential order.
1138 /// \param[in] auxProcessor The processor to join the primary processor with. The order in which its entries are
1139 /// processed is determined by the primary processor and doesn't necessarily have to be sequential.
1140 /// \param[in] joinFields The names of the fields on which to join, in case the specified processors are unaligned.
1141 /// The join is made based on the combined join field values, and therefore each field has to be present in each
1142 /// specified processor. If an empty list is provided, it is assumed that the processors are fully aligned.
1143 /// \param[in] opts Options for the processor.
1144 RNTupleJoinProcessor(std::unique_ptr<RNTupleProcessor> primaryProcessor,
1145 std::unique_ptr<RNTupleProcessor> auxProcessor, const std::vector<std::string> &joinFields,
1146 const RNTupleProcessorOptions &opts);
1147
1148public:
1150 RNTupleJoinProcessor operator=(const RNTupleJoinProcessor &) = delete;
1153 ~RNTupleJoinProcessor() override = default;
1154};
1155} // namespace Experimental
1156} // namespace ROOT
1157
1158#endif // ROOT_RNTupleProcessor
#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:322
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
char name[80]
Definition TGX11.cxx:142
Builds a join table on one or several fields of an RNTuple so it can be joined onto other RNTuples.
The RDataSource implementation for the RNTupleProcessor.
Processor specialization for horizontally combined (joined) RNTupleProcessors.
std::unordered_set< ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t > fAuxiliaryFieldIdxs
std::set< ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t > fJoinFieldIdxs
std::unique_ptr< RNTupleProcessor > fPrimaryProcessor
std::unique_ptr< Internal::RNTupleJoinTable > fJoinTable
friend std::unique_ptr< RNTupleProcessor > CreateRNTupleJoinProcessor(std::unique_ptr< RNTupleProcessor > primaryProcessor, std::unique_ptr< RNTupleProcessor > auxProcessor, const std::vector< std::string > &joinFields, const RNTupleProcessorOptions &opts)
Create an RNTupleProcessor for a join (i.e., a horizontal combination) of RNTuples.
std::unique_ptr< RNTupleProcessor > fAuxiliaryProcessor
Collection of values in an RNTupleProcessor, analogous to REntry, with checks and support for missing...
const ROOT::RFieldBase::RValue & GetValue(FieldIndex_t fieldIdx) const
bool IsValidField(FieldIndex_t fieldIdx) const
Check whether a field is valid for reading.
const std::string & FindFieldName(FieldIndex_t fieldIdx) const
Find the name of a field from its field index.
void BindRawPtr(FieldIndex_t fieldIdx, void *valuePtr)
Bind a new value pointer to a field in the entry.
void Bind(FieldIndex_t fieldIdx, std::shared_ptr< void > valuePtr)
Bind a new value pointer to a field in the entry.
Base class for all ROOT issued exceptions.
Definition RError.hxx:78
A field translates read and write calls from/to underlying columns to/from tree values.
Processor specialization for vertically combined (chained) RNTupleProcessors.
std::vector< std::unique_ptr< RNTupleProcessor > > fInnerProcessors
void AddAllFieldsToEntry(const Internal::RNTupleProcessorProvenance &provenance, bool includeSubfields) final
Add all known fields (from on-disk information) to the entry.
void ConnectInnerProcessor(std::size_t processorNumber)
Update the entry to reflect any missing fields in the current inner processor.
bool CanReadFieldFromDisk(std::string_view fieldName) final
Check if a field exists on-disk and can be read by the processor.
void Initialize(std::shared_ptr< ROOT::Internal::RNTupleProcessorEntry > entry=nullptr) final
Initialize the processor by creating an (initially empty) fEntry, or setting an existing one.
std::vector< ROOT::NTupleSize_t > fInnerNEntries
void Connect(const std::unordered_set< Internal::RNTupleProcessorEntry::FieldIndex_t > &fieldIdxs, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance(), bool updateFields=false) final
Connect the provided fields indices in the entry to their on-disk fields.
Internal::RNTupleProcessorEntry::FieldIndex_t AddFieldToEntry(const std::string &fieldName, const std::string &typeName, void *valuePtr=nullptr, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance()) final
Add a field to the entry.
void LoadEntryImpl(const REntryMapping &mapping) final
Load the entry identified by the entry mapping.
void SetEntryMapping(ROOT::NTupleSize_t globalEntryNumber, REntryMapping &mapping) final
Set the local entry mapping (for nested processors), according to a global entry number.
void AddEntriesToJoinTable(Experimental::Internal::RNTupleJoinTable &joinTable, ROOT::NTupleSize_t entryOffset=0) final
Add the entry mappings for this processor to the provided join table.
ROOT::NTupleSize_t fLastLoadedEntry
void PrintStructureImpl(std::ostream &output) const final
Processor-specific implementation for printing its structure, called by PrintStructure().
void Disconnect() final
Disconnect the processor from associated physical storage.
Internal::RNTupleProcessorProvenance fProvenance
ROOT::NTupleSize_t GetNEntries() final
Get the total number of entries in this processor.
std::string fProcessorName
By default, the processor name is the name of the underlying RNTuple for RNTupleSingleProcessor,...
const std::string & GetProcessorName() const
Get the processor's name.
void SetProcessorName(std::string_view name)
Set the processor's name.
std::shared_ptr< void > GetPtr() const
Get the pointer to the field value managed by the processor's entry.
void Bind(std::shared_ptr< void > valuePtr)
Bind the value to valuePtr.
ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t fFieldIndex
bool HasValue() const
Check if the pointer currently holds a valid value.
void * GetRawPtr() const
Get a non-owning pointer to the field value managed by the processor's entry.
RNTupleProcessorValuePtr(ROOT::Internal::RNTupleProcessorEntry *processorEntry, ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t fieldIdx)
friend bool operator==(const RNTupleProcessorValuePtr< void > &lhs, const RNTupleProcessorValuePtr< void > &rhs)
void BindRawPtr(void *valuePtr)
Bind the value to valuePtr.
ROOT::Internal::RNTupleProcessorEntry * fProcessorEntry
void BindRawPtr(T *valuePtr)
Bind the value to valuePtr.
const T * operator->() const
Access the field value managed by the processor's entry.
RNTupleProcessorValuePtr(ROOT::Internal::RNTupleProcessorEntry *processorEntry, ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t fieldIdx)
ROOT::Internal::RNTupleProcessorEntry::FieldIndex_t fFieldIndex
const T & operator*() const
Get a reference to the field value managed by the processor's entry.
ROOT::Internal::RNTupleProcessorEntry * fProcessorEntry
bool HasValue() const
Check if the pointer currently holds a valid value.
void Bind(std::shared_ptr< T > valuePtr)
Bind the value to valuePtr.
friend bool operator==(const RNTupleProcessorValuePtr< T > &lhs, const RNTupleProcessorValuePtr< T > &rhs)
T * GetRawPtr() const
Get a non-owning pointer to the field value managed by the processor's entry.
std::shared_ptr< T > GetPtr() const
Get a shared pointer to the field value managed by the processor's entry.
Maps a processor's global (outer) entry index to its inner ones.
friend bool operator==(const REntryMapping &lhs, const REntryMapping &rhs)
REntryMapping & operator=(const REntryMapping &other)
REntryMapping(REntryMapping &&other)=default
REntryMapping(const REntryMapping &other)
std::unique_ptr< REntryMapping > fPrimaryMapping
const REntryMapping & GetAuxiliaryProcessorMapping() const
const REntryMapping & GetInnerProcessorMapping() const
void SetEntryNumber(ROOT::NTupleSize_t entryNumber)
ROOT::NTupleSize_t GetEntryNumber() const
std::unique_ptr< REntryMapping > fAuxiliaryMapping
friend bool operator!=(const REntryMapping &lhs, const REntryMapping &rhs)
REntryMapping & operator=(REntryMapping &&other)=default
const REntryMapping & GetPrimaryProcessorMapping() const
std::unique_ptr< REntryMapping > fInnerMapping
Iterator over the entries of an RNTuple, or vertical concatenation thereof.
RIterator(RNTupleProcessor &processor, ROOT::NTupleSize_t firstEntryIdx)
const value_type * operator->() const
friend bool operator==(const iterator &lh, const iterator &rh)
friend bool operator!=(const iterator &lh, const iterator &rh)
std::forward_iterator_tag iterator_category
RNTupleProcessor::REntryMapping fEntryMapping
Interface for iterating over entries of vertically ("chained") and/or horizontally ("joined") combine...
friend struct ROOT::Internal::RNTupleProcessorEntryLoader
ROOT::NTupleSize_t fNEntries
Total number of entries.
virtual void Disconnect()=0
Disconnect the processor from associated physical storage.
virtual Internal::RNTupleProcessorEntry::FieldIndex_t AddFieldToEntry(const std::string &canonicalFieldName, const std::string &typeName, void *valuePtr, const Internal::RNTupleProcessorProvenance &provenance)=0
Add a field to the entry.
RNTupleProcessorValuePtr< void > RequestField(const std::string &fieldName, const std::string &typeName, void *valuePtr=nullptr)
Request access to a field for reading during processing.
virtual void Connect(const std::unordered_set< Internal::RNTupleProcessorEntry::FieldIndex_t > &fieldIdxs, const Internal::RNTupleProcessorProvenance &provenance, bool updateFields)=0
Connect fields to the page source of the processor's underlying RNTuple(s).
std::unordered_set< Internal::RNTupleProcessorEntry::FieldIndex_t > fFieldIdxs
virtual void AddAllFieldsToEntry(const Internal::RNTupleProcessorProvenance &provenance, bool includeSubfields)=0
Add all known fields (from on-disk information) to the entry.
static std::unique_ptr< RNTupleProcessor > CreateChain(std::vector< RNTupleInputSpec > ntuples, const RNTupleProcessorOptions &opts=RNTupleProcessorOptions())
Create an RNTupleProcessor for a chain (i.e., a vertical combination) of RNTuples.
virtual void PrintStructureImpl(std::ostream &output) const =0
Processor-specific implementation for printing its structure, called by PrintStructure().
virtual ROOT::NTupleSize_t GetNEntries()=0
Get the total number of entries in this processor.
virtual void Initialize(std::shared_ptr< ROOT::Internal::RNTupleProcessorEntry > entry)=0
Initialize the processor by creating an (initially empty) fEntry, or setting an existing one.
const ROOT::Internal::RNTupleProcessorEntry & GetEntry() const
Get a reference to the processor's internal entry.
RNTupleProcessor & operator=(RNTupleProcessor &&)=delete
RNTupleProcessor(const RNTupleProcessor &)=delete
RNTupleProcessor(RNTupleProcessor &&)=delete
void LoadEntry(const REntryMapping &mapping)
Load the entry identified by the entry mapping.
RNTupleProcessor(const RNTupleProcessorOptions &options)
Create a new base RNTupleProcessor.
ROOT::NTupleSize_t GetNEntriesProcessed() const
Get the total number of entries processed so far.
void PrintStructure(std::ostream &output=std::cout)
Print a graphical representation of the processor composition.
ROOT::Internal::RNTupleProcessorEntry & GetEntry()
Get a reference to the processor's internal entry.
ROOT::NTupleSize_t fNEntriesProcessed
virtual void SetEntryMapping(ROOT::NTupleSize_t globalEntryNumber, REntryMapping &mapping)=0
Set the local entry mapping (for nested processors), according to a global entry number.
RNTupleProcessorValuePtr< T > RequestField(const std::string &fieldName, void *valuePtr=nullptr)
Request access to a field for reading during processing.
static std::unique_ptr< RNTupleProcessor > Create(RNTupleInputSpec ntuple, const RNTupleProcessorOptions &opts=RNTupleProcessorOptions())
Create an RNTupleProcessor for a single RNTuple.
virtual void LoadEntryImpl(const REntryMapping &mapping)=0
Load the entry identified by the entry mapping.
void IncrementEntryMapping(REntryMapping &mapping)
Increment the local entry mapping by one.
virtual ~RNTupleProcessor()=default
virtual Internal::RNTupleProcessorEntry::FieldIndex_t AddFieldToEntry(std::unique_ptr< ROOT::RFieldBase > field, const std::string &canonicalFieldName, void *valuePtr, const Internal::RNTupleProcessorProvenance &provenance)=0
Add a field to the entry.
const RNTupleProcessorOptions & GetOptions() const
Get the options used for this processor.
RNTupleProcessorOptions fOptions
virtual void AddEntriesToJoinTable(Experimental::Internal::RNTupleJoinTable &joinTable, ROOT::NTupleSize_t entryOffset=0)=0
Add the entry mappings for this processor to the provided join table.
bool IsInitialized() const
Check if the processor already has been initialized.
std::shared_ptr< ROOT::Internal::RNTupleProcessorEntry > fEntry
virtual bool CanReadFieldFromDisk(std::string_view fieldName)=0
Check if a field exists on-disk and can be read by the processor.
RNTupleProcessor & operator=(const RNTupleProcessor &)=delete
Processor specialization for processing a single RNTuple.
void SetEntryMapping(ROOT::NTupleSize_t globalEntryNumber, REntryMapping &mapping) final
Set the local entry mapping (for nested processors), according to a global entry number.
void PrintStructureImpl(std::ostream &output) const final
Processor-specific implementation for printing its structure, called by PrintStructure().
std::unique_ptr< ROOT::Internal::RPageSource > fPageSource
void LoadEntryImpl(const REntryMapping &mapping) final
Load the entry identified by the entry mapping.
std::unique_ptr< ROOT::RFieldBase > ConnectField(std::unique_ptr< ROOT::RFieldBase > field)
Connect an existing field to the processor's page source.
bool CanReadFieldFromDisk(std::string_view fieldName) final
Check if a field exists on-disk and can be read by the processor.
void Initialize(std::shared_ptr< ROOT::Internal::RNTupleProcessorEntry > entry=nullptr) final
Initialize the processor by creating an (initially empty) fEntry, or setting an existing one.
Internal::RNTupleProcessorEntry::FieldIndex_t AddFieldToEntry(const std::string &fieldName, const std::string &typeName, void *valuePtr=nullptr, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance()) final
Add a field to the entry.
void AddAllFieldsToEntry(const Internal::RNTupleProcessorProvenance &provenance, bool includeSubfields) final
Add all known fields (from on-disk information) to the entry.
void AddEntriesToJoinTable(Experimental::Internal::RNTupleJoinTable &joinTable, ROOT::NTupleSize_t entryOffset=0) final
Add the entry mappings for this processor to the provided join table.
std::unique_ptr< ROOT::RFieldBase > CreateAndConnectField(const std::string &qualifiedFieldName, const std::string &typeName)
Create a new field and connect it to the processor's page source.
ROOT::NTupleSize_t GetNEntries() final
Get the total number of entries in this processor.
void Connect(const std::unordered_set< Internal::RNTupleProcessorEntry::FieldIndex_t > &fieldIdxs, const Internal::RNTupleProcessorProvenance &provenance=Internal::RNTupleProcessorProvenance(), bool updateFields=false) final
Connect the provided fields indices in the entry to their on-disk fields.
void Disconnect() final
Disconnect the processor from associated physical storage.
const RNTupleProcessorEntry * LoadFullRNTupleProcessorEntry(ROOT::RNTupleProcessor &processor, bool includeSubfields)
std::string GetRenormalizedTypeName(const std::string &metaNormalizedName)
Given a type name normalized by ROOT meta, renormalize it for RNTuple. E.g., insert std::prefix.
constexpr NTupleSize_t kInvalidNTupleIndex
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.