Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-08-16 09:21:19

0001 /// \file ROOT/RNTupleAttrReading.hxx
0002 /// \ingroup NTuple
0003 /// \author Giacomo Parolini <giacomo.parolini@cern.ch>
0004 /// \date 2026-04-01
0005 /// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
0006 /// is welcome!
0007 
0008 #ifndef ROOT7_RNTuple_Attr_Reading
0009 #define ROOT7_RNTuple_Attr_Reading
0010 
0011 #include <memory>
0012 #include <optional>
0013 #include <utility>
0014 #include <vector>
0015 
0016 #include <ROOT/RNTupleFillContext.hxx>
0017 #include <ROOT/RNTupleAttrUtils.hxx>
0018 #include <ROOT/RNTupleUtils.hxx>
0019 
0020 namespace ROOT {
0021 
0022 class REntry;
0023 class RNTupleDescriptor;
0024 class RNTupleModel;
0025 
0026 namespace Experimental {
0027 
0028 class RNTupleAttrEntryIterable;
0029 
0030 // clang-format off
0031 /**
0032 \class ROOT::Experimental::RNTupleAttrRange
0033 \ingroup NTuple
0034 \brief A range of main entries referred to by an attribute entry
0035 
0036 Each attribute entry contains a set of values referring to 0 or more contiguous entries in the main RNTuple.
0037 This class represents that contiguous range of entries.
0038 */
0039 // clang-format on
0040 class RNTupleAttrRange final {
0041    ROOT::NTupleSize_t fStart = 0;
0042    ROOT::NTupleSize_t fLength = 0;
0043 
0044    RNTupleAttrRange(ROOT::NTupleSize_t start, ROOT::NTupleSize_t length) : fStart(start), fLength(length) {}
0045 
0046 public:
0047    static RNTupleAttrRange FromStartLength(ROOT::NTupleSize_t start, ROOT::NTupleSize_t length)
0048    {
0049       return RNTupleAttrRange{start, length};
0050    }
0051 
0052    /// Creates an AttributeRange from [start, end), where `end` is one past the last valid entry of the range
0053    /// (`FromStartEnd(0, 10)` will create a range whose last valid index is 9).
0054    static RNTupleAttrRange FromStartEnd(ROOT::NTupleSize_t start, ROOT::NTupleSize_t end)
0055    {
0056       R__ASSERT(end >= start);
0057       return RNTupleAttrRange{start, end - start};
0058    }
0059 
0060    RNTupleAttrRange() = default;
0061 
0062    /// Returns the first valid entry index in the range. Returns nullopt if the range has zero length.
0063    std::optional<ROOT::NTupleSize_t> GetFirst() const { return fLength ? std::make_optional(fStart) : std::nullopt; }
0064    /// Returns the beginning of the range. Note that this is *not* a valid index in the range if the range has zero
0065    /// length.
0066    ROOT::NTupleSize_t GetStart() const { return fStart; }
0067    /// Returns the last valid entry index in the range. Returns nullopt if the range has zero length.
0068    std::optional<ROOT::NTupleSize_t> GetLast() const
0069    {
0070       return fLength ? std::make_optional(fStart + fLength - 1) : std::nullopt;
0071    }
0072    /// Returns one past the last valid index of the range, equal to `GetStart() + GetLength()`.
0073    ROOT::NTupleSize_t GetEnd() const { return fStart + fLength; }
0074    ROOT::NTupleSize_t GetLength() const { return fLength; }
0075 
0076    /// Returns the pair { firstEntryIdx, lastEntryIdx } (inclusive). Returns nullopt if the range has zero length.
0077    std::optional<std::pair<ROOT::NTupleSize_t, ROOT::NTupleSize_t>> GetFirstLast() const
0078    {
0079       return fLength ? std::make_optional(std::make_pair(fStart, fStart + fLength - 1)) : std::nullopt;
0080    }
0081    /// Returns the pair { start, length }.
0082    std::pair<ROOT::NTupleSize_t, ROOT::NTupleSize_t> GetStartLength() const { return {fStart, fLength}; }
0083 };
0084 
0085 // clang-format off
0086 /**
0087 \class ROOT::Experimental::RNTupleAttrSetReader
0088 \ingroup NTuple
0089 \brief Class used to read a RNTupleAttrSet in the context of a RNTupleReader
0090 
0091 An RNTupleAttrSetReader is created via RNTupleReader::OpenAttributeSet. Once created, it may outlive its parent Reader.
0092 Reading Attributes works similarly to reading regular RNTuple entries: you can either create entries or just use the
0093 AttrSetReader Model's default entry and load data into it via LoadEntry.
0094 
0095 ~~ {.cpp}
0096 // Reading Attributes via RNTupleAttrSetReader
0097 // -------------------------------------------
0098 
0099 // Assuming `reader` is a RNTupleReader:
0100 auto attrSet = reader->OpenAttributeSet("MyAttrSet");
0101 
0102 // Just like how you would read a regular RNTuple, first get the pointer to the fields you want to read:
0103 auto &attrEntry = attrSet->GetModel().GetDefaultEntry();
0104 auto pAttr = attrEntry->GetPtr<std::string>("myAttr");
0105 
0106 // Then select which attributes you want to read. E.g. read all attributes linked to the entry at index 10:
0107 for (auto idx : attrSet->GetAttributes(10)) {
0108    attrSet->LoadEntry(idx);
0109    cout << "entry " << idx << " has attribute " << *pAttr << "\n";
0110 }
0111 ~~
0112 */
0113 // clang-format on
0114 class RNTupleAttrSetReader final {
0115    friend class ROOT::RNTupleReader;
0116    friend class RNTupleAttrEntryIterable;
0117 
0118    /// List containing pairs { entryRange, entryIndex }, used to quickly find out which entries in the Attribute
0119    /// RNTuple contain entries that overlap a given range. The list is sorted by range start, i.e.
0120    /// entryRange.first.Start().
0121    std::vector<std::pair<RNTupleAttrRange, NTupleSize_t>> fEntryRanges;
0122    /// The internal Reader used to read the AttributeSet RNTuple
0123    std::unique_ptr<RNTupleReader> fReader;
0124    /// The reconstructed user model
0125    std::unique_ptr<ROOT::RNTupleModel> fUserModel;
0126 
0127    RNTupleAttrSetReader(std::unique_ptr<RNTupleReader> reader, std::uint16_t vSchemaMajor);
0128 
0129 public:
0130    RNTupleAttrSetReader(const RNTupleAttrSetReader &) = delete;
0131    RNTupleAttrSetReader &operator=(const RNTupleAttrSetReader &) = delete;
0132    RNTupleAttrSetReader(RNTupleAttrSetReader &&) = default;
0133    RNTupleAttrSetReader &operator=(RNTupleAttrSetReader &&) = default;
0134    ~RNTupleAttrSetReader() = default;
0135 
0136    /// Returns the read-only descriptor of this attribute set
0137    const ROOT::RNTupleDescriptor &GetDescriptor() const;
0138    /// Returns the read-only model of this attribute set
0139    const ROOT::RNTupleModel &GetModel() const { return *fUserModel; }
0140 
0141    /// Creates an entry suitable for use with LoadEntry.
0142    /// This is a convenience method equivalent to GetModel().CreateEntry().
0143    std::unique_ptr<REntry> CreateEntry();
0144 
0145    /// Loads the attribute entry at position `index` into the default entry.
0146    /// Returns the range of main RNTuple entries that the loaded set of attributes refers to.
0147    RNTupleAttrRange LoadEntry(NTupleSize_t index);
0148    /// Loads the attribute entry at position `index` into the given entry.
0149    /// Returns the range of main RNTuple entries that the loaded set of attributes refers to.
0150    RNTupleAttrRange LoadEntry(NTupleSize_t index, REntry &entry);
0151 
0152    /// Returns the number of all attribute entries in this attribute set.
0153    std::size_t GetNEntries() const { return fEntryRanges.size(); }
0154 
0155    /// Returns all the attributes in this Set. The returned attributes are sorted by entry range start.
0156    RNTupleAttrEntryIterable GetAttributes();
0157    /// Returns all the attributes whose range contains index `entryIndex`.
0158    RNTupleAttrEntryIterable GetAttributes(NTupleSize_t entryIndex);
0159    /// Returns all the attributes whose range fully contains `[startEntry, endEntry)`
0160    RNTupleAttrEntryIterable GetAttributesContainingRange(NTupleSize_t startEntry, NTupleSize_t endEntry);
0161    /// Returns all the attributes whose range is fully contained in `[startEntry, endEntry)`
0162    RNTupleAttrEntryIterable GetAttributesInRange(NTupleSize_t startEntry, NTupleSize_t endEntry);
0163 };
0164 
0165 // clang-format off
0166 /**
0167 \class ROOT::Experimental::RNTupleAttrEntryIterable
0168 \ingroup NTuple
0169 \brief Iterable class used to loop over attribute entries.
0170 
0171 This class allows to perform range-for iteration on some set of attributes, typically returned by the
0172 RNTupleAttrSetReader::GetAttributes family of methods.
0173 
0174 See the documentation of RNTupleAttrSetReader for example usage.
0175 */
0176 // clang-format on
0177 class RNTupleAttrEntryIterable final {
0178 public:
0179    struct RFilter {
0180       RNTupleAttrRange fRange;
0181       bool fIsContained;
0182    };
0183 
0184 private:
0185    RNTupleAttrSetReader *fReader = nullptr;
0186    std::optional<RFilter> fFilter;
0187 
0188 public:
0189    class RIterator final {
0190    private:
0191       using Iter_t = decltype(std::declval<RNTupleAttrSetReader>().fEntryRanges.begin());
0192       Iter_t fCur, fEnd;
0193       std::optional<RFilter> fFilter;
0194 
0195       Iter_t SkipFiltered() const;
0196       bool FullyContained(RNTupleAttrRange range) const;
0197 
0198    public:
0199       using iterator_category = std::forward_iterator_tag;
0200       using iterator = RIterator;
0201       using value_type = NTupleSize_t;
0202       using difference_type = std::ptrdiff_t;
0203       using pointer = const value_type *;
0204       using reference = const value_type &;
0205 
0206       RIterator(Iter_t iter, Iter_t end, std::optional<RFilter> filter) : fCur(iter), fEnd(end), fFilter(filter)
0207       {
0208          if (fFilter) {
0209             if (fFilter->fRange.GetLength() == 0)
0210                fCur = end;
0211             else
0212                fCur = SkipFiltered();
0213          }
0214       }
0215       iterator operator++()
0216       {
0217          ++fCur;
0218          fCur = SkipFiltered();
0219          return *this;
0220       }
0221       iterator operator++(int)
0222       {
0223          iterator it = *this;
0224          operator++();
0225          return it;
0226       }
0227       reference operator*() { return fCur->second; }
0228       bool operator!=(const iterator &rh) const { return !operator==(rh); }
0229       bool operator==(const iterator &rh) const { return fCur == rh.fCur; }
0230    };
0231 
0232    explicit RNTupleAttrEntryIterable(RNTupleAttrSetReader &reader, std::optional<RFilter> filter = {})
0233       : fReader(&reader), fFilter(filter)
0234    {
0235    }
0236 
0237    RIterator begin() { return RIterator{fReader->fEntryRanges.begin(), fReader->fEntryRanges.end(), fFilter}; }
0238    RIterator end() { return RIterator{fReader->fEntryRanges.end(), fReader->fEntryRanges.end(), fFilter}; }
0239 };
0240 
0241 } // namespace Experimental
0242 } // namespace ROOT
0243 
0244 #endif