RNTuple Attributes Prototype
Giacomo Parolini
ROOT Team, EP/SFT Group, CERN
RNTuple Attributes - overview
2
RNTuple Attributes - overview
3
Main
RNTuple
Footer
AttributeSet�“A”
Anchor
AttributeSet�“B”
Anchor
AttributeSet�“C”
Anchor
Locator for A
Locator for B
Locator for C
AttributeSet Model
4
Field Zero
<AttrSet_Name>
_rangeStart
_rangeLen
UserAttr1
UserAttr2
Internal Model used by the AttributeSet
User-provided Model
Untyped Record
Writing
5
// Step 5: close attribute range (not optional: the writer will NOT commit the attribute range automatically)
attrSet->CommitRange(std::move(attrRange));
6
////// WRITING RNTuple + Attributes //////
// Step 0: create an RNTuple as usual
auto model = RNTupleModel::Create();
auto pInt = model->MakeField<int>("int");
auto file = std::unique_ptr<TFile>(TFile::Open(fileGuard.GetPath().c_str(), "RECREATE")); // NOTE: we need TFile-based, so we
auto writer = RNTupleWriter::Append(std::move(model), "ntpl", *file); // use RNTupleWriter::Append()
// Step 1: create model for the attribute set
auto attrModel = RNTupleModel::Create();
auto pMyAttr = attrModel->MakeField<std::string>("myAttr");
// Step 2: create the attribute set from the writer. Returns a (non-owning) RNTupleAttrSetWriterHandle
// with the same lifetime as the main RNTupleWriter.
auto attrSet = writer->CreateAttributeSet(std::move(attrModel), "MyAttrSet");
// Step 3: open attribute range. attrRange is a RNTupleAttrPendingRange
auto attrRange = attrSet->BeginRange();
// Step 4: assign attribute values.
// Values can be assigned anywhere between BeginRange() and CommitRange().
*pMyAttr = "This is a custom attribute";
for (int i = 0; i < 100; ++i) {
*pInt = i;
writer->Fill();
}
Writing API - some details
7
RNTupleAttrPendingRange BeginRange();
void CommitRange(RNTupleAttrPendingRange range);
void CommitRange(RNTupleAttrPendingRange range, REntry &entry);
Note: this currently only works for TFile-based RNTupleWriters. Will be extended to support the RMiniFile-based default writer as well.
Lifetime of Attribute Sets and Ranges
8
CreateAttributeSet(“A”)
CloseAttributeSet
RNTupleWriter
BeginRange
CommitRange
CreateAttributeSet(“B”)
AttributeSetWriter�“A”
BeginRange
CommitRange
(destructed)
AttributeSetWriter� “B”
AttrPendingRange
AttrPendingRange
Writing API - cont.
9
// Regular entries:
auto entry = writer->CreateEntry();
auto ptr = entry->GetPtr<int>("myInt");
*ptr = 42;
writer->Fill(*entry);
// Attributes:
auto attrEntry = attrSet->CreateEntry();
auto range = attrSet->BeginRange();
auto ptr = attrEntry->GetPtr<int>("myInt");
*ptr = 42;
attrSet->CommitRange(std::move(range), *attrEntry);
Writing - some notes
10
Reading
11
auto &attrEntry = attrSet->GetModel().GetDefaultEntry();
for (auto idx : attrs) {
auto range = attrSet->LoadAttrEntry(idx);
auto val = attrEntry.GetPtr<std::string>("string");
EXPECT_EQ(*val, "This is a custom attribute");
EXPECT_EQ(range.Start(), 0);
EXPECT_EQ(range.End(), 100);
}
12
////// READING RNTuple + Attributes //////
auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
// Fetch a specific attribute set. Returns a unique_ptr<RNTupleAttrSetReader>.
auto attrSet = reader->OpenAttributeSet("MyAttrSet");
// NOTE: all these functions return an iterable over indices (ROOT::NTupleSize_t).
// Get Attributes of a single entry.
auto attrs = attrSet->GetAttributes(0);
// Get Attributes of an entry range
attrs = attrSet->GetAttributesInRange(3, 10);
attrs = attrSet->GetAttributesContainingRange(3, 10);
// Get all Attributes
attrs = attrSet->GetAttributes();
Reading - cont.
13
auto &attrEntry = attrSet->GetModel().GetDefaultEntry();
for (auto idx : attrSet->GetAttributes()) {
auto range = attrSet->LoadAttrEntry(idx);
auto val = attrEntry.GetPtr<int>("int");
}
auto &entry = reader->GetModel().GetDefaultEntry();
for (auto idx : reader->GetEntryRange()) {
reader->LoadEntry(idx);
auto val = entry.GetPtr<int>("int");
}
Reading - empty ranges
14
Merging
15
Merging
16
Thank you!
17
Merging - empty ranges
Say we’re merging AttrSets A, B and C, each with 1 attribute spanning all entries
The merged AttrSet looks like this:
18
A
C
B
10 entries
10 entries
0 entries
A
C
20 entries
Attribute Entries � (name: {start, length})
Attribute Entries � (name: {start, length})
Merging only modifies the entries’ start