@@ -4223,3 +4223,184 @@ TEST(RNTupleMerger, MergeNewerVersion)
42234223 }
42244224 }
42254225}
4226+
4227+ TEST (RNTupleMerger, MergeReal32Trunc)
4228+ {
4229+ // Merge two files, both containing the same Real32Trunc-encoded field, but with different bit widths.
4230+ FileRaii fileGuard1 (" test_ntuple_merge_real32trunc_in_1.root" );
4231+ {
4232+ auto model = RNTupleModel::Create ();
4233+ auto field = std::make_unique<RField<float >>(" flt" );
4234+ field->SetTruncated (14 );
4235+ model->AddField (std::move (field));
4236+ auto ntuple = RNTupleWriter::Recreate (std::move (model), " ntuple" , fileGuard1.GetPath ());
4237+ auto fieldFlt = ntuple->GetModel ().GetDefaultEntry ().GetPtr <float >(" flt" );
4238+ for (int i = 0 ; i < 10 ; ++i) {
4239+ *fieldFlt = i;
4240+ ntuple->Fill ();
4241+ }
4242+ }
4243+ FileRaii fileGuard2 (" test_ntuple_merge_real32trunc_in_2.root" );
4244+ {
4245+ auto model = RNTupleModel::Create ();
4246+ auto field = std::make_unique<RField<float >>(" flt" );
4247+ field->SetTruncated (24 );
4248+ model->AddField (std::move (field));
4249+ auto ntuple = RNTupleWriter::Recreate (std::move (model), " ntuple" , fileGuard2.GetPath ());
4250+ auto fieldFlt = ntuple->GetModel ().GetDefaultEntry ().GetPtr <float >(" flt" );
4251+ for (int i = 0 ; i < 10 ; ++i) {
4252+ *fieldFlt = 10 + i;
4253+ ntuple->Fill ();
4254+ }
4255+ }
4256+ {
4257+ // Gather the input sources
4258+ std::vector<std::unique_ptr<RPageSource>> sources;
4259+ sources.push_back (RPageSource::Create (" ntuple" , fileGuard1.GetPath (), RNTupleReadOptions ()));
4260+ sources.push_back (RPageSource::Create (" ntuple" , fileGuard2.GetPath (), RNTupleReadOptions ()));
4261+ std::vector<RPageSource *> sourcePtrs;
4262+ for (const auto &s : sources) {
4263+ sourcePtrs.push_back (s.get ());
4264+ }
4265+
4266+ // Now merge the inputs
4267+ for (const auto mmode : {ENTupleMergingMode::kFilter , ENTupleMergingMode::kStrict , ENTupleMergingMode::kUnion }) {
4268+ SCOPED_TRACE (std::string (" with merging mode = " ) + ToString (mmode));
4269+ FileRaii fileGuardOut (" test_ntuple_merge_real32trunc_out.root" );
4270+ {
4271+ auto destination = std::make_unique<RPageSinkFile>(" ntuple" , fileGuardOut.GetPath (), RNTupleWriteOptions ());
4272+ RNTupleMerger merger{std::move (destination)};
4273+ RNTupleMergeOptions opts;
4274+ opts.fMergingMode = mmode;
4275+ auto res = merger.Merge (sourcePtrs, opts);
4276+ // Currently we're not supporting merging columns with the same type but different metadata.
4277+ // TODO: support this.
4278+ EXPECT_FALSE (bool (res));
4279+ EXPECT_THAT (res.GetError ()->GetReport (), testing::HasSubstr (" have different column metadata" ));
4280+ }
4281+ }
4282+ }
4283+ }
4284+
4285+ TEST (RNTupleMerger, MergeReal32Quant)
4286+ {
4287+ // Merge two files, both containing the same Real32Quant-encoded field, but with different value ranges.
4288+ FileRaii fileGuard1 (" test_ntuple_merge_real32quant_in_1.root" );
4289+ {
4290+ auto model = RNTupleModel::Create ();
4291+ auto field = std::make_unique<RField<float >>(" flt" );
4292+ field->SetQuantized (20 , {0 ., 100 .});
4293+ model->AddField (std::move (field));
4294+ auto ntuple = RNTupleWriter::Recreate (std::move (model), " ntuple" , fileGuard1.GetPath ());
4295+ auto fieldFlt = ntuple->GetModel ().GetDefaultEntry ().GetPtr <float >(" flt" );
4296+ for (int i = 0 ; i < 10 ; ++i) {
4297+ *fieldFlt = i;
4298+ ntuple->Fill ();
4299+ }
4300+ }
4301+ FileRaii fileGuard2 (" test_ntuple_merge_real32quant_in_2.root" );
4302+ {
4303+ auto model = RNTupleModel::Create ();
4304+ auto field = std::make_unique<RField<float >>(" flt" );
4305+ field->SetQuantized (20 , {-100 ., 100 .});
4306+ model->AddField (std::move (field));
4307+ auto ntuple = RNTupleWriter::Recreate (std::move (model), " ntuple" , fileGuard2.GetPath ());
4308+ auto fieldFlt = ntuple->GetModel ().GetDefaultEntry ().GetPtr <float >(" flt" );
4309+ for (int i = 0 ; i < 10 ; ++i) {
4310+ *fieldFlt = 10 + i;
4311+ ntuple->Fill ();
4312+ }
4313+ }
4314+ {
4315+ // Gather the input sources
4316+ std::vector<std::unique_ptr<RPageSource>> sources;
4317+ sources.push_back (RPageSource::Create (" ntuple" , fileGuard1.GetPath (), RNTupleReadOptions ()));
4318+ sources.push_back (RPageSource::Create (" ntuple" , fileGuard2.GetPath (), RNTupleReadOptions ()));
4319+ std::vector<RPageSource *> sourcePtrs;
4320+ for (const auto &s : sources) {
4321+ sourcePtrs.push_back (s.get ());
4322+ }
4323+
4324+ // Now merge the inputs
4325+ for (const auto mmode : {ENTupleMergingMode::kFilter , ENTupleMergingMode::kStrict , ENTupleMergingMode::kUnion }) {
4326+ SCOPED_TRACE (std::string (" with merging mode = " ) + ToString (mmode));
4327+ FileRaii fileGuardOut (" test_ntuple_merge_real32quant_out.root" );
4328+ {
4329+ auto destination = std::make_unique<RPageSinkFile>(" ntuple" , fileGuardOut.GetPath (), RNTupleWriteOptions ());
4330+ RNTupleMerger merger{std::move (destination)};
4331+ RNTupleMergeOptions opts;
4332+ opts.fMergingMode = mmode;
4333+ auto res = merger.Merge (sourcePtrs, opts);
4334+ // Currently we're not supporting merging columns with the same type but different metadata.
4335+ // TODO: support this.
4336+ ASSERT_FALSE (bool (res));
4337+ EXPECT_THAT (res.GetError ()->GetReport (), testing::HasSubstr (" have different column metadata" ));
4338+ }
4339+ }
4340+ }
4341+ }
4342+
4343+ TEST (RNTupleMerger, MergeReal32TruncQuantMixed)
4344+ {
4345+ // Merge two files, both containing the same field, but with the first being Real32Trunc and the second Real32Quant
4346+ FileRaii fileGuard1 (" test_ntuple_merge_real32truncquant_in_1.root" );
4347+ {
4348+ auto model = RNTupleModel::Create ();
4349+ auto field = std::make_unique<RField<float >>(" flt" );
4350+ field->SetTruncated (24 );
4351+ model->AddField (std::move (field));
4352+ auto ntuple = RNTupleWriter::Recreate (std::move (model), " ntuple" , fileGuard1.GetPath ());
4353+ auto fieldFlt = ntuple->GetModel ().GetDefaultEntry ().GetPtr <float >(" flt" );
4354+ for (int i = 0 ; i < 10 ; ++i) {
4355+ *fieldFlt = i;
4356+ ntuple->Fill ();
4357+ }
4358+ }
4359+ FileRaii fileGuard2 (" test_ntuple_merge_real32truncquant_in_2.root" );
4360+ {
4361+ auto model = RNTupleModel::Create ();
4362+ auto field = std::make_unique<RField<float >>(" flt" );
4363+ field->SetQuantized (20 , {-1 ., 100 .});
4364+ model->AddField (std::move (field));
4365+ auto ntuple = RNTupleWriter::Recreate (std::move (model), " ntuple" , fileGuard2.GetPath ());
4366+ auto fieldFlt = ntuple->GetModel ().GetDefaultEntry ().GetPtr <float >(" flt" );
4367+ for (int i = 0 ; i < 10 ; ++i) {
4368+ *fieldFlt = 10 + i;
4369+ ntuple->Fill ();
4370+ }
4371+ }
4372+ {
4373+ // Gather the input sources
4374+ std::vector<std::unique_ptr<RPageSource>> sources;
4375+ sources.push_back (RPageSource::Create (" ntuple" , fileGuard1.GetPath (), RNTupleReadOptions ()));
4376+ sources.push_back (RPageSource::Create (" ntuple" , fileGuard2.GetPath (), RNTupleReadOptions ()));
4377+ std::vector<RPageSource *> sourcePtrs;
4378+ for (const auto &s : sources) {
4379+ sourcePtrs.push_back (s.get ());
4380+ }
4381+
4382+ // Now merge the inputs
4383+ for (const auto mmode : {ENTupleMergingMode::kFilter , ENTupleMergingMode::kStrict , ENTupleMergingMode::kUnion }) {
4384+ SCOPED_TRACE (std::string (" with merging mode = " ) + ToString (mmode));
4385+ FileRaii fileGuardOut (" test_ntuple_merge_real32truncquant_out.root" );
4386+ {
4387+ auto destination = std::make_unique<RPageSinkFile>(" ntuple" , fileGuardOut.GetPath (), RNTupleWriteOptions ());
4388+ RNTupleMerger merger{std::move (destination)};
4389+ RNTupleMergeOptions opts;
4390+ opts.fMergingMode = mmode;
4391+ auto res = merger.Merge (sourcePtrs, opts);
4392+ EXPECT_TRUE (bool (res));
4393+ }
4394+ {
4395+ auto reader = ROOT::RNTupleReader::Open (" ntuple" , fileGuardOut.GetPath ());
4396+ EXPECT_EQ (reader->GetNEntries (), 20 );
4397+ EXPECT_EQ (reader->GetDescriptor ().GetNPhysicalColumns (), 2 );
4398+ auto pFlt = reader->GetModel ().GetDefaultEntry ().GetPtr <float >(" flt" );
4399+ for (auto i : reader->GetEntryRange ()) {
4400+ reader->LoadEntry (i);
4401+ EXPECT_NEAR (*pFlt, i, 0 .01f );
4402+ }
4403+ }
4404+ }
4405+ }
4406+ }
0 commit comments