Skip to content

Commit 7f9b999

Browse files
committed
[ntuple] automatically evolve fixed size array into RVec
1 parent d6c9b5d commit 7f9b999

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: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,51 @@ struct RenamedIntermediateDerived : public RenamedIntermediate2 {
956956
}
957957
}
958958

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

tree/ntuple/test/ntuple_evolution_type.cxx

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,3 +207,24 @@ TEST(RNTupleEvolution, CheckPairTuple)
207207
EXPECT_EQ(1, std::get<0>(p(0)));
208208
EXPECT_DOUBLE_EQ(2.0, std::get<1>(p(0)));
209209
}
210+
211+
TEST(RNTupleEvolution, ArrayAsRVec)
212+
{
213+
FileRaii fileGuard("test_ntuple_evolution_array_as_rvec.root");
214+
{
215+
auto model = ROOT::RNTupleModel::Create();
216+
auto a = model->MakeField<std::array<int, 2>>("a");
217+
auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), "ntpl", fileGuard.GetPath());
218+
219+
*a = {1, 2};
220+
writer->Fill();
221+
}
222+
223+
auto reader = RNTupleReader::Open("ntpl", fileGuard.GetPath());
224+
225+
auto a = reader->GetView<ROOT::RVec<short>>("a");
226+
EXPECT_EQ(typeid(a.GetField()), typeid(ROOT::RArrayAsRVecField));
227+
EXPECT_EQ(2u, a(0).size());
228+
EXPECT_EQ(1, a(0)[0]);
229+
EXPECT_EQ(2, a(0)[1]);
230+
}

0 commit comments

Comments
 (0)