RNTuple Attributes are the way to store custom metadata in RNTuple.
They work by associating rows of user-defined metadata to ranges of entries in their parent RNTuple (called the "main RNTuple"). These rows of metadata, called "attribute entries", are defined much like a regular RNTuple by an RNTupleModel and they belong to an "attribute set".
An attribute set is a standalone collection of attributes which is linked to one and only one RNTuple. Attribute sets are identified by their name and, similarly to RNTuples, they are created with an associated Model and can be written and read via bespoke classes (RNTupleAttrSetWriter/Reader). These classes are never used by themselves but are created from an existing RNTupleWriter or Reader.
Each main RNTuple can have an arbitrary number of associated attribute sets, though usually one is enough for most purposes. This tutorial shows how to create, write and read back attributes from an RNTuple.
NOTE: The RNTuple attributes are experimental at this point. Functionality and interface are still subject to changes.
#include <iostream>
#include <memory>
#include <utility>
constexpr const char *kFileName = "ntpl019_attributes.root";
constexpr const char *kNTupleName = "ntpl";
};
static void Write()
{
auto pEvent = model->MakeField<
Event>(
"event");
auto file = std::unique_ptr<TFile>(
TFile::Open(kFileName,
"RECREATE"));
attrModel->SetDescription("Metadata containing the events' provenance");
auto pRunNumber = attrModel->MakeField<std::int32_t>("runNumber");
auto attrSet =
writer->CreateAttributeSet(std::move(attrModel),
"Provenance");
auto attrRange = attrSet->BeginRange();
*pRunNumber = 0;
for (int i = 0; i < 100; ++i) {
if (i % 10 == 0 && i > 0) {
attrSet->CommitRange(std::move(attrRange));
attrRange = attrSet->BeginRange();
*pRunNumber += 1;
}
}
if (attrRange) {
attrSet->CommitRange(std::move(attrRange));
}
}
static bool IsGoodRunNumber(std::int32_t runNo)
{
return runNo == 4;
}
static void Read()
{
std::cout << "Here are the attribute sets linked to the RNTuple '" << kNTupleName << "':\n";
for (const auto &attrSetDesc : reader->GetDescriptor().GetAttrSetIterable()) {
std::cout << " " << attrSetDesc.GetName() << "\n";
}
auto attrSet = reader->OpenAttributeSet("Provenance");
auto pRunNumber = attrSet->GetModel().GetDefaultEntry().GetPtr<std::int32_t>("runNumber");
std::cout << "\nOpened attribute set '" << attrSet->GetDescriptor().GetName() << "' with description: \""
<< attrSet->GetDescriptor().GetDescription() << "\"\n";
for (auto mainIdx : reader->GetEntryRange()) {
std::cout << "Entry " << mainIdx << " has the following attributes associated to it:\n";
for (auto attrIdx : attrSet->GetAttributes(mainIdx)) {
auto range = attrSet->LoadEntry(attrIdx);
std::cout << " runNumber = " << *pRunNumber << " (valid for range [" << *range.GetFirst() << ", "
<< *range.GetLast() << "])\n";
}
}
auto pEvent = reader->GetModel().GetDefaultEntry().GetPtr<
Event>(
"event");
for (auto attrIdx : attrSet->GetAttributes()) {
auto range = attrSet->LoadEntry(attrIdx);
if (IsGoodRunNumber(*pRunNumber)) {
std::cout << "\nRun " << *pRunNumber << " is good. Events:\n";
for (auto mainIdx = range.GetStart(); mainIdx < range.GetEnd(); ++mainIdx) {
reader->LoadEntry(mainIdx);
std::cout << " Event " << mainIdx << " with pt = " << pEvent->pt << "\n";
}
}
}
}
void ntpl019_attributes()
{
Write();
Read();
}
static std::unique_ptr< RNTupleModel > Create()
static std::unique_ptr< RNTupleReader > Open(std::string_view ntupleName, std::string_view storage, const ROOT::RNTupleReadOptions &options=ROOT::RNTupleReadOptions())
Open an RNTuple for reading.
static std::unique_ptr< RNTupleWriter > Append(std::unique_ptr< ROOT::RNTupleModel > model, std::string_view ntupleName, TDirectory &fileOrDirectory, const ROOT::RNTupleWriteOptions &options=ROOT::RNTupleWriteOptions())
Creates an RNTupleWriter that writes into an existing TFile or TDirectory, without overwriting its co...
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Random number generator class based on M.
Double_t Rndm() override
Machine independent random number generator.