Skip to content

Commit 263b12a

Browse files
committed
[ntuple] automatically evolve fixed size array into RVec
1 parent 69e0c76 commit 263b12a

File tree

4 files changed

+83
-0
lines changed

4 files changed

+83
-0
lines changed

tree/ntuple/inc/ROOT/RField/RFieldSequenceContainer.hxx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ protected:
154154
void ReadGlobalImpl(ROOT::NTupleSize_t globalIndex, void *to) final;
155155
std::size_t ReadBulkImpl(const RBulkSpec &bulkSpec) final;
156156

157+
std::unique_ptr<RFieldBase> BeforeConnectPageSource(ROOT::Internal::RPageSource &pageSource) final;
157158
void ReconcileOnDiskField(const RNTupleDescriptor &desc) final;
158159

159160
void CommitClusterImpl() final { fNWritten = 0; }

tree/ntuple/src/RFieldSequenceContainer.cxx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,22 @@ void ROOT::RRVecField::GenerateColumns(const ROOT::RNTupleDescriptor &desc)
424424
GenerateColumnsImpl<ROOT::Internal::RColumnIndex>(desc);
425425
}
426426

427+
std::unique_ptr<ROOT::RFieldBase> ROOT::RRVecField::BeforeConnectPageSource(Internal::RPageSource &pageSource)
428+
{
429+
if (GetOnDiskId() == kInvalidDescriptorId)
430+
return nullptr;
431+
432+
const auto descGuard = pageSource.GetSharedDescriptorGuard();
433+
const auto &fieldDesc = descGuard->GetFieldDescriptor(GetOnDiskId());
434+
if (fieldDesc.GetTypeName().rfind("std::array<", 0) == 0) {
435+
auto substitute = std::make_unique<RArrayAsRVecField>(
436+
GetFieldName(), fSubfields[0]->Clone(fSubfields[0]->GetFieldName()), fieldDesc.GetNRepetitions());
437+
substitute->SetOnDiskId(GetOnDiskId());
438+
return substitute;
439+
}
440+
return nullptr;
441+
}
442+
427443
void ROOT::RRVecField::ReconcileOnDiskField(const RNTupleDescriptor &desc)
428444
{
429445
EnsureMatchingOnDiskField(desc.GetFieldDescriptor(GetOnDiskId()), kDiffTypeName);

tree/ntuple/test/ntuple_evolution_shape.cxx

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,50 @@ struct RenamedIntermediateDerived : public RenamedIntermediate2 {
956956
}
957957
}
958958

959+
TEST(RNTupleEvolution, ArrayAsVector)
960+
{
961+
FileRaii fileGuard("test_ntuple_evolution_array_as_vector.root");
962+
963+
ExecInFork([&] {
964+
// The child process writes the file and exits, but the file must be preserved to be read by the parent.
965+
fileGuard.PreserveFile();
966+
967+
ASSERT_TRUE(gInterpreter->Declare(R"(
968+
struct ArrayAsVector {
969+
std::array<int, 2> fArr = {1, 2};
970+
int x = 3;
971+
};
972+
)"));
973+
974+
auto model = RNTupleModel::Create();
975+
model->AddField(RFieldBase::Create("f", "ArrayAsVector").Unwrap());
976+
977+
auto writer = RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
978+
writer->Fill();
979+
980+
writer.reset();
981+
});
982+
983+
ASSERT_TRUE(gInterpreter->Declare(R"(
984+
struct ArrayAsVector {
985+
ROOT::RVec<short> fArr;
986+
int x;
987+
};
988+
)"));
989+
990+
auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
991+
ASSERT_EQ(1, reader->GetNEntries());
992+
993+
void *ptr = reader->GetModel().GetDefaultEntry().GetPtr<void>("f").get();
994+
DeclarePointer("ArrayAsVector", "ptrArrayAsVector", ptr);
995+
996+
reader->LoadEntry(0);
997+
EXPECT_EVALUATE_EQ("ptrArrayAsVector->x", 3);
998+
EXPECT_EVALUATE_EQ("ptrArrayAsVector->fArr.size()", 2);
999+
EXPECT_EVALUATE_EQ("ptrArrayAsVector->fArr[0]", 1);
1000+
EXPECT_EVALUATE_EQ("ptrArrayAsVector->fArr[1]", 2);
1001+
}
1002+
9591003
TEST(RNTupleEvolution, StreamerField)
9601004
{
9611005
FileRaii fileGuard("test_ntuple_evolution_streamer_field.root");

tree/ntuple/test/ntuple_evolution_type.cxx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,3 +229,25 @@ TEST(RNTupleEvolution, Enum)
229229
EXPECT_EQ(42, ve1(0));
230230
EXPECT_EQ(137, ve2(0));
231231
}
232+
233+
TEST(RNTupleEvolution, ArrayAsRVec)
234+
{
235+
FileRaii fileGuard("test_ntuple_evolution_array_as_rvec.root");
236+
{
237+
auto model = ROOT::RNTupleModel::Create();
238+
auto a = model->MakeField<std::array<int, 2>>("a");
239+
auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
240+
241+
*a = {1, 2};
242+
writer->Fill();
243+
}
244+
245+
auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
246+
247+
auto a = reader->GetView<ROOT::RVec<short>>("a");
248+
const auto &f = a.GetField(); // necessary to silence clang warning
249+
EXPECT_EQ(typeid(f), typeid(ROOT::RArrayAsRVecField));
250+
EXPECT_EQ(2u, a(0).size());
251+
EXPECT_EQ(1, a(0)[0]);
252+
EXPECT_EQ(2, a(0)[1]);
253+
}

0 commit comments

Comments
 (0)