Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
RNTupleProcessorEntry.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 2025-06-25
4
5/*************************************************************************
6 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. *
7 * All rights reserved. *
8 * *
9 * For the licensing terms see $ROOTSYS/LICENSE. *
10 * For the list of contributors see $ROOTSYS/README/CREDITS. *
11 *************************************************************************/
12
13#ifndef ROOT_RNTupleProcessorEntry
14#define ROOT_RNTupleProcessorEntry
15
16#include <ROOT/RFieldBase.hxx>
17
18#include <cassert>
19#include <string>
20#include <string_view>
21#include <unordered_map>
22#include <vector>
23
24namespace ROOT {
25namespace Internal {
26/**
27\class ROOT::RNTupleProcessorProvenance
28\ingroup NTuple
29\brief Identifies how a processor is composed.
30
31The processor provenance is used in RNTupleProcessorEntry to identify how an (auxiliary) field in a composed processor
32can be accessed.
33*/
34// clang-format on
36private:
37 std::string fProvenance{};
38
39public:
41 RNTupleProcessorProvenance(const std::string &provenance) : fProvenance(provenance) {}
42
43 /////////////////////////////////////////////////////////////////////////////
44 /// \brief Get the full processor provenance, in the form of "x.y.z".
45 std::string Get() const { return fProvenance; }
46
47 /////////////////////////////////////////////////////////////////////////////
48 /// \brief Add a new processor to the provenance.
49 ///
50 /// \param[in] processorName Name of the processor to add.
51 ///
52 /// \return The updated provenance.
53 RNTupleProcessorProvenance Evolve(const std::string &processorName) const
54 {
55 if (fProvenance.empty())
56 return RNTupleProcessorProvenance(processorName);
57
58 return RNTupleProcessorProvenance(fProvenance + "." + processorName);
59 }
60
61 /////////////////////////////////////////////////////////////////////////////
62 /// \brief Check whether the provenance subsumes the provenance in `other`.
63 ///
64 /// \param[in] other The other provenance
65 bool Contains(const RNTupleProcessorProvenance &other) const
66 {
67 return fProvenance.rfind(other.fProvenance) != std::string::npos;
68 }
69
70 /////////////////////////////////////////////////////////////////////////////
71 /// \brief Check whether the provided field name contains this provenance.
72 ///
73 /// \param[in] fieldName Field name to check.
74 bool IsPresentInFieldName(std::string_view fieldName) const
75 {
76 return !fProvenance.empty() && fieldName.find(fProvenance) == 0;
77 }
78
79 bool Empty() const { return fProvenance.empty(); }
80};
81
82// clang-format off
83/**
84\class ROOT::Internal::RNTupleProcessorEntry
85\ingroup NTuple
86\brief Collection of values in an RNTupleProcessor, analogous to REntry, with checks and support for missing values.
87*/
88// clang-format on
90public:
91 // We don't use RFieldTokens here, because it (semantically) does not make sense for the entry to be fixed to the
92 // schema ID of a particular model.
93 using FieldIndex_t = std::uint64_t;
94
95private:
97 std::unique_ptr<ROOT::RFieldBase> fField;
102
103 // If the field is artificial (i.e., not actually present on disk), this holds the entry index of the field it
104 // should get the on-disk ID from.
106
107 RProcessorValue(std::unique_ptr<ROOT::RFieldBase> field, std::string_view qualifiedFieldName,
109 : fField(std::move(field)),
110 fQualifiedFieldName(qualifiedFieldName),
111 fValue(std::move(value)),
112 fIsValid(isValid),
113 fProcessorProvenance(std::move(provenance))
114 {
115 }
116 };
117
118 std::vector<RProcessorValue> fProcessorValues;
119 // Maps from the field name to all type alternatives for that field that have been added to the entry.
120 std::unordered_map<std::string, std::vector<FieldIndex_t>> fFieldName2Index;
121
122public:
123 /////////////////////////////////////////////////////////////////////////////
124 /// \brief Clear all fields from the entry.
125 void Clear()
126 {
127 fProcessorValues.clear();
128 fFieldName2Index.clear();
129 }
130
131 /////////////////////////////////////////////////////////////////////////////
132 /// \brief Reset the specified fields to a proto field, disconnected from any physical storage.
133 ///
134 /// \param[in] fieldIdx Fields to reset.
135 void ResetFields(const std::unordered_set<FieldIndex_t> &fieldIdxs)
136 {
137 for (auto fieldIdx : fieldIdxs) {
138 auto &value = fProcessorValues[fieldIdx];
139 UpdateField(fieldIdx, value.fField->Clone(value.fField->GetFieldName()));
140 }
141 }
142
143 /////////////////////////////////////////////////////////////////////////////
144 /// \brief Set the validity of a field, i.e. whether it is possible to read its value in the current entry.
145 ///
146 /// \param[in] fieldIdx The index of the field in the entry.
147 /// \param[in] isValid The new validity of the field.
148 void SetFieldValidity(FieldIndex_t fieldIdx, bool isValid)
149 {
150 assert(fieldIdx < fProcessorValues.size());
151 fProcessorValues[fieldIdx].fIsValid = isValid;
152 }
153
154 /////////////////////////////////////////////////////////////////////////////
155 /// \brief Check whether a field is valid for reading.
156 ///
157 /// \param[in] fieldIdx The index of the field in the entry.
158 bool IsValidField(FieldIndex_t fieldIdx) const
159 {
160 assert(fieldIdx < fProcessorValues.size());
161 return fProcessorValues[fieldIdx].fIsValid;
162 }
163
164 /////////////////////////////////////////////////////////////////////////////
165 /// \brief Set a field's origin index
166 ///
167 /// \param[in] fieldIdx The index of the field in the entry to set.
168 /// \param[in] fieldOriginIdx The index of the field in the entry the field identified by `fieldIdx` should
169 /// point to.
170 ///
171 /// Setting the origin index should be used for articifial fields.
172 void SetFieldOriginIdx(FieldIndex_t fieldIdx, FieldIndex_t fieldOriginIdx)
173 {
174 assert(fieldIdx < fProcessorValues.size());
175 fProcessorValues[fieldIdx].fFieldOriginIdx = fieldOriginIdx;
176 }
177
178 /////////////////////////////////////////////////////////////////////////////
179 /// \brief Get a field's origin field index.
180 ///
181 /// \param[in] fieldIdx The index of the field in the entry to set.
182 ///
183 /// \return The index of the field's origin field.
185 {
186 assert(fieldIdx < fProcessorValues.size());
187 return fProcessorValues[fieldIdx].fFieldOriginIdx;
188 }
189
190 /////////////////////////////////////////////////////////////////////////////
191 /// \brief Find the name of a field from its field index.
192 ///
193 /// \param[in] fieldIdx The index of the field in the entry.
194 ///
195 /// \warning This function has linear complexity, only use it for more helpful error messages!
196 const std::string &FindFieldName(FieldIndex_t fieldIdx) const;
197
198 /////////////////////////////////////////////////////////////////////////////
199 /// \brief Find the field index of the provided field in the entry.
200 ///
201 /// \param[in] canonicalFieldName The name of the field in the entry, including its processor name prefixes and
202 /// parent field names, if applicable.
203 /// \param[in] typeName Type of the field, if relevant. If no type name is provided, the first field corresponding to
204 /// the provided name is returned.
205 ///
206 /// \return A `std::optional` containing the field index if it was found.
207 std::optional<FieldIndex_t>
208 FindFieldIndex(std::string_view canonicalFieldName, std::string_view typeName = "") const;
209
210 /////////////////////////////////////////////////////////////////////////////
211 /// \brief Add a new field to the entry.
212 ///
213 /// \param[in] qualifiedFieldName Name of the field to add, including its parent field if applicable.
214 /// \param[in] field Reference to the field to add, used to to create its corresponding RValue.
215 /// \param[in] valuePtr Pointer to an object corresponding to the field's type to bind to its value. If this is a
216 /// `nullptr`, a pointer will be created.
217 /// \param[in] provenance Processor provenance of the field.
218 ///
219 /// \return The field index of the newly added field.
220 FieldIndex_t AddField(const std::string &qualifiedFieldName, std::unique_ptr<ROOT::RFieldBase> field, void *valuePtr,
221 const RNTupleProcessorProvenance &provenance);
222
223 /////////////////////////////////////////////////////////////////////////////
224 /// \brief Update a field in the entry, preserving the value pointer.
225 ///
226 /// \param[in] fieldIdx Index of the field to update.
227 /// \param[in] field The new field to use in the entry.
228 void UpdateField(FieldIndex_t fieldIdx, std::unique_ptr<ROOT::RFieldBase> field);
229
230 /////////////////////////////////////////////////////////////////////////////
231 /// \brief Get a field by its index.
232 ///
233 /// \param[in] fieldIdx Index of the field.
234 ///
235 /// \return A constref to the field.
236 const ROOT::RFieldBase &GetField(FieldIndex_t fieldIdx) const;
237
238 /////////////////////////////////////////////////////////////////////////////
239 /// \brief Bind a new value pointer to a field in the entry.
240 ///
241 /// \param[in] fieldIdx The index of the field in the entry.
242 /// \param[in] valuePtr Pointer to the value to bind to the field.
243 void BindRawPtr(FieldIndex_t fieldIdx, void *valuePtr);
244
245 /////////////////////////////////////////////////////////////////////////////
246 /// \brief Bind a new value pointer to a field in the entry.
247 ///
248 /// \param[in] fieldIdx The index of the field in the entry.
249 /// \param[in] valuePtr Pointer to the value to bind to the field.
250 void Bind(FieldIndex_t fieldIdx, std::shared_ptr<void> valuePtr);
251
252 /////////////////////////////////////////////////////////////////////////////
253 /// \brief Read the field value corresponding to the given field index for the provided entry index.
254 ///
255 /// \param[in] fieldIdx The index of the field in the entry.
256 /// \param[in] entryIdx The entry number to read.
257 void ReadValue(FieldIndex_t fieldIdx, ROOT::NTupleSize_t entryIdx);
258
260 {
261 assert(fieldIdx < fProcessorValues.size());
262 return fProcessorValues[fieldIdx].fValue;
263 }
264
265 /////////////////////////////////////////////////////////////////////////////
266 /// \brief Get the processor provenance of a field in the entry.
267 ///
268 /// \param[in] fieldIdx The index of the field in the entry.
270 {
271 assert(fieldIdx < fProcessorValues.size());
272 return fProcessorValues[fieldIdx].fProcessorProvenance;
273 }
274
275 /////////////////////////////////////////////////////////////////////////////
276 /// \brief Get the name of a field in the entry, including its parent fields.
277 ///
278 /// \param[in] fieldIdx The index of the field in the entry.
279 std::string GetQualifiedFieldName(FieldIndex_t fieldIdx) const
280 {
281 assert(fieldIdx < fProcessorValues.size());
282 return fProcessorValues[fieldIdx].fQualifiedFieldName;
283 }
284
285 /////////////////////////////////////////////////////////////////////////////
286 /// \brief Get all field indices of this entry.
287 std::unordered_set<FieldIndex_t> GetFieldIndices() const;
288};
289} // namespace Internal
290} // namespace ROOT
291
292#endif // ROOT_RNTupleProcessorEntry
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Collection of values in an RNTupleProcessor, analogous to REntry, with checks and support for missing...
void SetFieldValidity(FieldIndex_t fieldIdx, bool isValid)
Set the validity of a field, i.e.
FieldIndex_t GetFieldOriginIdx(FieldIndex_t fieldIdx)
Get a field's origin field index.
std::vector< RProcessorValue > fProcessorValues
const ROOT::RFieldBase & GetField(FieldIndex_t fieldIdx) const
Get a field by its index.
const RNTupleProcessorProvenance & GetFieldProvenance(FieldIndex_t fieldIdx) const
Get the processor provenance of a field in the entry.
const ROOT::RFieldBase::RValue & GetValue(FieldIndex_t fieldIdx) const
void Clear()
Clear all fields from the entry.
bool IsValidField(FieldIndex_t fieldIdx) const
Check whether a field is valid for reading.
std::optional< FieldIndex_t > FindFieldIndex(std::string_view canonicalFieldName, std::string_view typeName="") const
Find the field index of the provided field in the entry.
const std::string & FindFieldName(FieldIndex_t fieldIdx) const
Find the name of a field from its field index.
void UpdateField(FieldIndex_t fieldIdx, std::unique_ptr< ROOT::RFieldBase > field)
Update a field in the entry, preserving the value pointer.
std::unordered_set< FieldIndex_t > GetFieldIndices() const
Get all field indices of this entry.
std::string GetQualifiedFieldName(FieldIndex_t fieldIdx) const
Get the name of a field in the entry, including its parent fields.
void SetFieldOriginIdx(FieldIndex_t fieldIdx, FieldIndex_t fieldOriginIdx)
Set a field's origin index.
std::unordered_map< std::string, std::vector< FieldIndex_t > > fFieldName2Index
void ReadValue(FieldIndex_t fieldIdx, ROOT::NTupleSize_t entryIdx)
Read the field value corresponding to the given field index for the provided entry 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.
void ResetFields(const std::unordered_set< FieldIndex_t > &fieldIdxs)
Reset the specified fields to a proto field, disconnected from any physical storage.
FieldIndex_t AddField(const std::string &qualifiedFieldName, std::unique_ptr< ROOT::RFieldBase > field, void *valuePtr, const RNTupleProcessorProvenance &provenance)
Add a new field to the entry.
RNTupleProcessorProvenance(const std::string &provenance)
std::string Get() const
Get the full processor provenance, in the form of "x.y.z".
bool Contains(const RNTupleProcessorProvenance &other) const
Check whether the provenance subsumes the provenance in other.
RNTupleProcessorProvenance Evolve(const std::string &processorName) const
Add a new processor to the provenance.
bool IsPresentInFieldName(std::string_view fieldName) const
Check whether the provided field name contains this provenance.
Points to an object with RNTuple I/O support and keeps a pointer to the corresponding field.
A field translates read and write calls from/to underlying columns to/from tree values.
std::uint64_t DescriptorId_t
Distriniguishes elements of the same type within a descriptor, e.g. different fields.
std::uint64_t NTupleSize_t
Integer type long enough to hold the maximum number of entries in a column.
constexpr DescriptorId_t kInvalidDescriptorId
RProcessorValue(std::unique_ptr< ROOT::RFieldBase > field, std::string_view qualifiedFieldName, ROOT::RFieldBase::RValue &&value, bool isValid, RNTupleProcessorProvenance provenance)