Skip to content

Commit 2cd3238

Browse files
committed
[ntuple] automatically evolve fixed size array into RVec
1 parent 6d9d6ef commit 2cd3238

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
@@ -207,3 +207,25 @@ 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+
const auto &f = a.GetField(); // necessary to silence clang warning
227+
EXPECT_EQ(typeid(f), typeid(ROOT::RArrayAsRVecField));
228+
EXPECT_EQ(2u, a(0).size());
229+
EXPECT_EQ(1, a(0)[0]);
230+
EXPECT_EQ(2, a(0)[1]);
231+
}

0 commit comments

Comments
 (0)