-
Notifications
You must be signed in to change notification settings - Fork 1.5k
[ntuple] Support reading alternative types through the RNTupleProcessor
#21462
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
0fa19e7
5ab60d8
eb47d0e
098b0b2
8095819
f2aeb00
091710b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -97,20 +97,36 @@ public: | |
|
|
||
| private: | ||
| struct RProcessorValue { | ||
| std::unique_ptr<ROOT::RFieldBase> fField; | ||
| std::string fQualifiedFieldName; | ||
| ROOT::RFieldBase::RValue fValue; | ||
| bool fIsValid; | ||
| RNTupleProcessorProvenance fProcessorProvenance; | ||
|
|
||
| RProcessorValue(ROOT::RFieldBase::RValue &&value, bool isValid, RNTupleProcessorProvenance provenance) | ||
| : fValue(std::move(value)), fIsValid(isValid), fProcessorProvenance(provenance) | ||
| RProcessorValue(std::unique_ptr<ROOT::RFieldBase> field, std::string_view qualifiedFieldName, | ||
| ROOT::RFieldBase::RValue &&value, bool isValid, RNTupleProcessorProvenance provenance) | ||
| : fField(std::move(field)), | ||
| fQualifiedFieldName(qualifiedFieldName), | ||
| fValue(std::move(value)), | ||
| fIsValid(isValid), | ||
| fProcessorProvenance(provenance) | ||
| { | ||
| } | ||
| }; | ||
|
|
||
| std::vector<RProcessorValue> fProcessorValues; | ||
| std::unordered_map<std::string, FieldIndex_t> fFieldName2Index; | ||
| // Maps from the field name to all type alternatives for that field that have been added to the entry. | ||
| std::unordered_map<std::string, std::unordered_set<FieldIndex_t>> fFieldName2Index; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure about using an |
||
|
|
||
| public: | ||
| ///////////////////////////////////////////////////////////////////////////// | ||
| /// \brief Clear all fields from the entry. | ||
| void Clear() | ||
| { | ||
| fProcessorValues.clear(); | ||
| fFieldName2Index.clear(); | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////// | ||
| /// \brief Set the validity of a field, i.e. whether it is possible to read its value in the current entry. | ||
| /// | ||
|
|
@@ -143,7 +159,7 @@ public: | |
| assert(fieldIdx < fProcessorValues.size()); | ||
|
|
||
| for (const auto &[fieldName, index] : fFieldName2Index) { | ||
| if (index == fieldIdx) { | ||
| if (index.find(fieldIdx) != index.end()) { | ||
| return fieldName; | ||
| } | ||
| } | ||
|
|
@@ -156,41 +172,59 @@ public: | |
| ///////////////////////////////////////////////////////////////////////////// | ||
| /// \brief Find the field index of the provided field in the entry. | ||
| /// | ||
| /// \param[in] fieldName The name of the field in the entry. | ||
| /// \param[in] canonicalFieldName The name of the field in the entry, including its processor name prefixes and | ||
| /// parent field names, if applicable. | ||
| /// | ||
| /// \return A `std::optional` containing the field index if it was found. | ||
| std::optional<FieldIndex_t> FindFieldIndex(std::string_view fieldName) const | ||
| std::optional<FieldIndex_t> FindFieldIndex(std::string_view canonicalFieldName, std::string_view typeName) const | ||
| { | ||
| auto it = fFieldName2Index.find(std::string(fieldName)); | ||
| auto it = fFieldName2Index.find(std::string(canonicalFieldName)); | ||
| if (it == fFieldName2Index.end()) { | ||
| return std::nullopt; | ||
| } | ||
| return it->second; | ||
|
|
||
| const auto &fieldIdxs = it->second; | ||
| assert(!fieldIdxs.empty()); | ||
|
|
||
| for (auto idx : fieldIdxs) { | ||
| if (fProcessorValues[idx].fField->GetTypeName() == typeName) { | ||
| return idx; | ||
| } | ||
| } | ||
|
|
||
| return std::nullopt; | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////// | ||
| /// \brief Add a new field to the entry. | ||
| /// | ||
| /// \param[in] fieldName Name of the field to add. | ||
| /// \param[in] qualifiedFieldName Name of the field to add, including its parent field if applicable. | ||
| /// \param[in] field Reference to the field to add, used to to create its corresponding RValue. | ||
| /// \param[in] valuePtr Pointer to an object corresponding to the field's type to bind to its value. If this is a | ||
| /// `nullptr`, a pointer will be created. | ||
| /// \param[in] provenance Processor provenance of the field. | ||
| /// | ||
| /// \return The field index of the newly added field. | ||
| FieldIndex_t AddField(std::string_view fieldName, ROOT::RFieldBase &field, void *valuePtr, | ||
| FieldIndex_t AddField(const std::string &qualifiedFieldName, std::unique_ptr<ROOT::RFieldBase> field, void *valuePtr, | ||
| const RNTupleProcessorProvenance &provenance) | ||
| { | ||
| if (FindFieldIndex(fieldName)) | ||
| auto fieldNameWithProcessorPrefix = qualifiedFieldName; | ||
| if (const auto &processorPrefix = provenance.Get(); !processorPrefix.empty()) | ||
| fieldNameWithProcessorPrefix = processorPrefix + "." + qualifiedFieldName; | ||
|
|
||
| if (FindFieldIndex(fieldNameWithProcessorPrefix, field->GetTypeName())) | ||
| throw ROOT::RException( | ||
| R__FAIL("field \"" + field.GetQualifiedFieldName() + "\" is already present in the entry")); | ||
| R__FAIL("field \"" + fieldNameWithProcessorPrefix + "\" is already present in the entry")); | ||
|
|
||
| auto value = field.CreateValue(); | ||
| auto fieldIdx = fProcessorValues.size(); | ||
| fFieldName2Index[fieldNameWithProcessorPrefix].insert(fieldIdx); | ||
|
|
||
| assert(field); | ||
| auto value = field->CreateValue(); | ||
| if (valuePtr) | ||
| value.BindRawPtr(valuePtr); | ||
| auto fieldIdx = fProcessorValues.size(); | ||
| fFieldName2Index[std::string(fieldName)] = fieldIdx; | ||
| fProcessorValues.emplace_back(RProcessorValue(std::move(value), true, provenance)); | ||
| fProcessorValues.emplace_back( | ||
| RProcessorValue(std::move(field), qualifiedFieldName, std::move(value), true, provenance)); | ||
|
|
||
| return fieldIdx; | ||
| } | ||
|
|
@@ -200,14 +234,22 @@ public: | |
| /// | ||
| /// \param[in] fieldIdx Index of the field to update. | ||
| /// \param[in] field The new field to use in the entry. | ||
| void UpdateField(FieldIndex_t fieldIdx, ROOT::RFieldBase &field) | ||
| void UpdateField(FieldIndex_t fieldIdx, std::unique_ptr<ROOT::RFieldBase> field) | ||
| { | ||
| assert(fieldIdx < fProcessorValues.size()); | ||
|
|
||
| auto currValuePtr = fProcessorValues[fieldIdx].fValue.GetPtr<void>(); | ||
| auto value = field.CreateValue(); | ||
| value.Bind(currValuePtr); | ||
| fProcessorValues[fieldIdx].fValue = value; | ||
| auto &fieldInfo = fProcessorValues[fieldIdx]; | ||
|
|
||
| if (field) { | ||
| auto newValue = field->CreateValue(); | ||
| auto currValuePtr = fieldInfo.fValue.GetPtr<void>(); | ||
| newValue.Bind(currValuePtr); | ||
| fieldInfo.fField = std::move(field); | ||
| fieldInfo.fValue = std::move(newValue); | ||
| fieldInfo.fIsValid = true; | ||
| } else { | ||
| fieldInfo.fIsValid = false; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this also reset |
||
| } | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////// | ||
|
|
@@ -275,14 +317,13 @@ public: | |
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////// | ||
| /// \brief Get the name of a field in the entry, including processor name prefixes in the case of auxiliary fields. | ||
| /// \brief Get the name of a field in the entry, including its parent fields. | ||
| /// | ||
| /// \param[in] fieldIdx The index of the field in the entry. | ||
| std::string GetFieldName(FieldIndex_t fieldIdx) const | ||
| std::string GetQualifiedFieldName(FieldIndex_t fieldIdx) const | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At this point this can probably return a
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure, by adding more field / values later on, |
||
| { | ||
| assert(fieldIdx < fProcessorValues.size()); | ||
| return fProcessorValues[fieldIdx].fProcessorProvenance.Get() + "." + | ||
| fProcessorValues[fieldIdx].fValue.GetField().GetQualifiedFieldName(); | ||
| return fProcessorValues[fieldIdx].fQualifiedFieldName; | ||
| } | ||
|
|
||
| ///////////////////////////////////////////////////////////////////////////// | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please split all the
std::string_view->const std::string&changes into a separate commit?