Skip to content

Commit

Permalink
Fix RNTuple writer after API break in ROOT (#547)
Browse files Browse the repository at this point in the history
* Fix RNTuple writer after API break in ROOT

* Use preprocessor version check for selecting RNTuple functionality

* Adapt RNTupleReader to new RNTuple API

* Use ROOT Version header that works with older versions

* Make sure to have valid fields for the Frame parameters
  • Loading branch information
tmadlener authored Apr 2, 2024
1 parent 400f4f0 commit 14109ff
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 26 deletions.
4 changes: 4 additions & 0 deletions include/podio/RNTupleReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@

#include <ROOT/RNTuple.hxx>
#include <ROOT/RNTupleModel.hxx>
#include <RVersion.h>
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
#include <ROOT/RNTupleReader.hxx>
#endif

namespace podio {

Expand Down
4 changes: 4 additions & 0 deletions include/podio/RNTupleWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
#include "TFile.h"
#include <ROOT/RNTuple.hxx>
#include <ROOT/RNTupleModel.hxx>
#include <RVersion.h>
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
#include <ROOT/RNTupleWriter.hxx>
#endif

#include <string>
#include <unordered_map>
Expand Down
26 changes: 25 additions & 1 deletion src/RNTupleReader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,15 @@ std::unique_ptr<ROOTFrameData> RNTupleReader::readEntry(const std::string& categ
m_entries[category] = entNum + 1;

ROOTFrameData::BufferMap buffers;
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
// We need to create a non-bare entry here, because the entries for the
// parameters are not explicitly (re)set and we need them default initialized.
// In principle we would only need a bare entry for the collection data, since
// we set all the fields there in any case.
auto dentry = m_readers[category][0]->GetModel().CreateEntry();
#else
auto dentry = m_readers[category][0]->GetModel()->GetDefaultEntry();
#endif

for (size_t i = 0; i < m_collectionInfo[category].id.size(); ++i) {
const auto& collType = m_collectionInfo[category].type[i];
Expand All @@ -157,31 +165,47 @@ std::unique_ptr<ROOTFrameData> RNTupleReader::readEntry(const std::string& categ
if (m_collectionInfo[category].isSubsetCollection[i]) {
auto brName = root_utils::subsetBranch(m_collectionInfo[category].name[i]);
auto vec = new std::vector<podio::ObjectID>;
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
dentry->BindRawPtr(brName, vec);
#else
dentry->CaptureValueUnsafe(brName, vec);
#endif
collBuffers.references->at(0) = std::unique_ptr<std::vector<podio::ObjectID>>(vec);
} else {
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
dentry->BindRawPtr(m_collectionInfo[category].name[i], collBuffers.data);
#else
dentry->CaptureValueUnsafe(m_collectionInfo[category].name[i], collBuffers.data);
#endif

const auto relVecNames = podio::DatamodelRegistry::instance().getRelationNames(collType);
for (size_t j = 0; j < relVecNames.relations.size(); ++j) {
const auto relName = relVecNames.relations[j];
auto vec = new std::vector<podio::ObjectID>;
const auto brName = root_utils::refBranch(m_collectionInfo[category].name[i], relName);
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
dentry->BindRawPtr(brName, vec);
#else
dentry->CaptureValueUnsafe(brName, vec);
#endif
collBuffers.references->at(j) = std::unique_ptr<std::vector<podio::ObjectID>>(vec);
}

for (size_t j = 0; j < relVecNames.vectorMembers.size(); ++j) {
const auto vecName = relVecNames.vectorMembers[j];
const auto brName = root_utils::vecBranch(m_collectionInfo[category].name[i], vecName);
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
dentry->BindRawPtr(brName, collBuffers.vectorMembers->at(j).second);
#else
dentry->CaptureValueUnsafe(brName, collBuffers.vectorMembers->at(j).second);
#endif
}
}

buffers.emplace(m_collectionInfo[category].name[i], std::move(collBuffers));
}

m_readers[category][0]->LoadEntry(entNum);
m_readers[category][0]->LoadEntry(entNum, *dentry);

auto parameters = readEventMetaData(category, entNum);

Expand Down
72 changes: 47 additions & 25 deletions src/RNTupleWriter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "rootUtils.h"

#include "TFile.h"

#include <ROOT/RField.hxx>
#include <ROOT/RNTuple.hxx>
#include <ROOT/RNTupleModel.hxx>
Expand Down Expand Up @@ -44,8 +45,13 @@ std::pair<std::vector<std::string>&, std::vector<std::vector<T>>&> RNTupleWriter
template <typename T>
void RNTupleWriter::fillParams(GenericParameters& params, ROOT::Experimental::REntry* entry) {
auto [key, value] = getKeyValueVectors<T>();
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
entry->BindRawPtr(root_utils::getGPKeyName<T>(), &key);
entry->BindRawPtr(root_utils::getGPValueName<T>(), &value);
#else
entry->CaptureValueUnsafe(root_utils::getGPKeyName<T>(), &key);
entry->CaptureValueUnsafe(root_utils::getGPValueName<T>(), &value);
#endif

key.clear();
key.reserve(params.getMap<T>().size());
Expand Down Expand Up @@ -107,29 +113,46 @@ void RNTupleWriter::writeFrame(const podio::Frame& frame, const std::string& cat
}
}

#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
auto entry = m_categories[category].writer->GetModel().CreateBareEntry();
#else
auto entry = m_categories[category].writer->GetModel()->CreateBareEntry();
#endif

ROOT::Experimental::RNTupleWriteOptions options;
options.SetCompression(ROOT::RCompressionSetting::EDefaults::kUseGeneralPurpose);

for (const auto& [name, coll] : collections) {
auto collBuffers = coll->getBuffers();
if (collBuffers.vecPtr) {
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
entry->BindRawPtr(name, (void*)collBuffers.vecPtr);
#else
entry->CaptureValueUnsafe(name, (void*)collBuffers.vecPtr);
#endif
}

if (coll->isSubsetCollection()) {
auto& refColl = (*collBuffers.references)[0];
const auto brName = root_utils::subsetBranch(name);
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
entry->BindRawPtr(brName, refColl.get());
#else
entry->CaptureValueUnsafe(brName, refColl.get());
#endif

} else {

const auto relVecNames = podio::DatamodelRegistry::instance().getRelationNames(coll->getValueTypeName());
if (auto refColls = collBuffers.references) {
int i = 0;
for (auto& c : (*refColls)) {
const auto brName = root_utils::refBranch(name, relVecNames.relations[i]);
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
entry->BindRawPtr(brName, c.get());
#else
entry->CaptureValueUnsafe(brName, c.get());
#endif
++i;
}
}
Expand All @@ -140,7 +163,11 @@ void RNTupleWriter::writeFrame(const podio::Frame& frame, const std::string& cat
const auto typeName = "vector<" + type + ">";
const auto brName = root_utils::vecBranch(name, relVecNames.vectorMembers[i]);
auto ptr = *(std::vector<int>**)vec;
#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
entry->BindRawPtr(brName, ptr);
#else
entry->CaptureValueUnsafe(brName, ptr);
#endif
++i;
}
}
Expand All @@ -163,6 +190,13 @@ void RNTupleWriter::writeFrame(const podio::Frame& frame, const std::string& cat
std::unique_ptr<ROOT::Experimental::RNTupleModel>
RNTupleWriter::createModels(const std::vector<StoreCollection>& collections) {
auto model = ROOT::Experimental::RNTupleModel::CreateBare();

#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 31, 0)
using ROOT::Experimental::RFieldBase;
#else
using ROOT::Experimental::Detail::RFieldBase;
#endif

for (auto& [name, coll] : collections) {
// For the first entry in each category we also record the datamodel
// definition
Expand All @@ -172,14 +206,14 @@ RNTupleWriter::createModels(const std::vector<StoreCollection>& collections) {

if (collBuffers.vecPtr) {
auto collClassName = "std::vector<" + std::string(coll->getDataTypeName()) + ">";
auto field = ROOT::Experimental::Detail::RFieldBase::Create(name, collClassName).Unwrap();
auto field = RFieldBase::Create(name, collClassName).Unwrap();
model->AddField(std::move(field));
}

if (coll->isSubsetCollection()) {
const auto brName = root_utils::subsetBranch(name);
auto collClassName = "vector<podio::ObjectID>";
auto field = ROOT::Experimental::Detail::RFieldBase::Create(brName, collClassName).Unwrap();
auto field = RFieldBase::Create(brName, collClassName).Unwrap();
model->AddField(std::move(field));
} else {

Expand All @@ -189,7 +223,7 @@ RNTupleWriter::createModels(const std::vector<StoreCollection>& collections) {
for (auto& c [[maybe_unused]] : (*refColls)) {
const auto brName = root_utils::refBranch(name, relVecNames.relations[i]);
auto collClassName = "vector<podio::ObjectID>";
auto field = ROOT::Experimental::Detail::RFieldBase::Create(brName, collClassName).Unwrap();
auto field = RFieldBase::Create(brName, collClassName).Unwrap();
model->AddField(std::move(field));
++i;
}
Expand All @@ -200,7 +234,7 @@ RNTupleWriter::createModels(const std::vector<StoreCollection>& collections) {
for (auto& [type, vec] : (*vminfo)) {
const auto typeName = "vector<" + type + ">";
const auto brName = root_utils::vecBranch(name, relVecNames.vectorMembers[i]);
auto field = ROOT::Experimental::Detail::RFieldBase::Create(brName, typeName).Unwrap();
auto field = RFieldBase::Create(brName, typeName).Unwrap();
model->AddField(std::move(field));
++i;
}
Expand All @@ -212,27 +246,15 @@ RNTupleWriter::createModels(const std::vector<StoreCollection>& collections) {
// so we have to split them manually
// model->MakeField<podio::GenericParameters>(root_utils::paramBranchName);

model->AddField(
ROOT::Experimental::Detail::RFieldBase::Create(root_utils::intKeyName, "std::vector<std::string>>").Unwrap());
model->AddField(
ROOT::Experimental::Detail::RFieldBase::Create(root_utils::floatKeyName, "std::vector<std::string>>").Unwrap());
model->AddField(
ROOT::Experimental::Detail::RFieldBase::Create(root_utils::doubleKeyName, "std::vector<std::string>>").Unwrap());
model->AddField(
ROOT::Experimental::Detail::RFieldBase::Create(root_utils::stringKeyName, "std::vector<std::string>>").Unwrap());

model->AddField(
ROOT::Experimental::Detail::RFieldBase::Create(root_utils::intValueName, "std::vector<std::vector<int>>")
.Unwrap());
model->AddField(
ROOT::Experimental::Detail::RFieldBase::Create(root_utils::floatValueName, "std::vector<std::vector<float>>")
.Unwrap());
model->AddField(
ROOT::Experimental::Detail::RFieldBase::Create(root_utils::doubleValueName, "std::vector<std::vector<double>>")
.Unwrap());
model->AddField(ROOT::Experimental::Detail::RFieldBase::Create(root_utils::stringValueName,
"std::vector<std::vector<std::string>>")
.Unwrap());
model->AddField(RFieldBase::Create(root_utils::intKeyName, "std::vector<std::string>>").Unwrap());
model->AddField(RFieldBase::Create(root_utils::floatKeyName, "std::vector<std::string>>").Unwrap());
model->AddField(RFieldBase::Create(root_utils::doubleKeyName, "std::vector<std::string>>").Unwrap());
model->AddField(RFieldBase::Create(root_utils::stringKeyName, "std::vector<std::string>>").Unwrap());

model->AddField(RFieldBase::Create(root_utils::intValueName, "std::vector<std::vector<int>>").Unwrap());
model->AddField(RFieldBase::Create(root_utils::floatValueName, "std::vector<std::vector<float>>").Unwrap());
model->AddField(RFieldBase::Create(root_utils::doubleValueName, "std::vector<std::vector<double>>").Unwrap());
model->AddField(RFieldBase::Create(root_utils::stringValueName, "std::vector<std::vector<std::string>>").Unwrap());

model->Freeze();
return model;
Expand Down

0 comments on commit 14109ff

Please sign in to comment.