Skip to content

Commit

Permalink
[ntuple] Use name of first TTree when importing unnamed TChain
Browse files Browse the repository at this point in the history
Fixes issue #13088.
  • Loading branch information
enirolf authored and jblomer committed Jul 24, 2023
1 parent 492dc79 commit 46f2e5f
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 28 deletions.
11 changes: 10 additions & 1 deletion tree/ntupleutil/v7/src/RNTupleImporter.cxx
Expand Up @@ -24,6 +24,7 @@
#include <ROOT/RStringView.hxx>

#include <TBranch.h>
#include <TChain.h>
#include <TClass.h>
#include <TDataType.h>
#include <TLeaf.h>
Expand Down Expand Up @@ -110,7 +111,15 @@ std::unique_ptr<ROOT::Experimental::RNTupleImporter>
ROOT::Experimental::RNTupleImporter::Create(TTree *sourceTree, std::string_view destFileName)
{
auto importer = std::unique_ptr<RNTupleImporter>(new RNTupleImporter());
importer->fNTupleName = sourceTree->GetName();

if (sourceTree->IsA() == TChain::Class() && std::strcmp(sourceTree->GetName(), "") == 0) {
if (sourceTree->LoadTree(0) != 0)
throw RException(R__FAIL("failure retrieving first tree from provided chain"));
importer->fNTupleName = sourceTree->GetTree()->GetName();
} else {
importer->fNTupleName = sourceTree->GetName();
}

importer->fSourceTree = sourceTree;

// If we have IMT enabled, its best use is for parallel page compression
Expand Down
72 changes: 45 additions & 27 deletions tree/ntupleutil/v7/test/ntuple_importer.cxx
Expand Up @@ -59,46 +59,64 @@ TEST(RNTupleImporter, CreateFromTree)

TEST(RNTupleImporter, CreateFromChain)
{
FileRaii fileGuard1("test_ntuple_create_from_chain_1.root");
FileRaii treeFileGuard("test_ntuple_create_from_chain_1.root");
{
std::unique_ptr<TFile> file(TFile::Open(fileGuard1.GetPath().c_str(), "RECREATE"));
auto tree = std::make_unique<TTree>("tree", "");
std::unique_ptr<TFile> file(TFile::Open(treeFileGuard.GetPath().c_str(), "RECREATE"));

auto tree1 = std::make_unique<TTree>("tree1", "");
Int_t a = 42;
// For single-leaf branches, use branch name, not leaf name
tree->Branch("a", &a);
tree->Fill();
tree->Write();
tree1->Branch("a", &a);
tree1->Fill();
tree1->Write();

auto tree2 = std::make_unique<TTree>("tree2", "");
a = 43;
tree2->Branch("a", &a);
tree2->Fill();
tree2->Write();
}

FileRaii fileGuard2("test_ntuple_create_from_chain_2.root");
FileRaii chainFileGuard("test_ntuple_create_from_chain_2.root");
{
std::unique_ptr<TFile> file(TFile::Open(fileGuard2.GetPath().c_str(), "RECREATE"));
auto tree = std::make_unique<TTree>("tree", "");
Int_t a = 43;
// For single-leaf branches, use branch name, not leaf name
tree->Branch("a", &a);
tree->Fill();
tree->Write();
std::unique_ptr<TFile> file(TFile::Open(chainFileGuard.GetPath().c_str(), "RECREATE"));

TChain namedChain("tree");
namedChain.Add((treeFileGuard.GetPath() + "?#tree1").c_str());
namedChain.Add((treeFileGuard.GetPath() + "?#tree2").c_str());
namedChain.Write();
}

TChain *chain = new TChain("tree");
chain->Add(fileGuard1.GetPath().c_str());
chain->Add(fileGuard2.GetPath().c_str());
std::unique_ptr<TFile> file(TFile::Open(chainFileGuard.GetPath().c_str()));
auto namedChain = file->Get<TChain>("tree");

auto importer = RNTupleImporter::Create(chain, fileGuard1.GetPath());
importer->SetIsQuiet(true);
EXPECT_THROW(importer->Import(), ROOT::Experimental::RException);
importer->SetNTupleName("ntuple");
importer->Import();
auto importer1 = RNTupleImporter::Create(namedChain, chainFileGuard.GetPath());
importer1->SetIsQuiet(true);
EXPECT_THROW(importer1->Import(), ROOT::Experimental::RException);
importer1->SetNTupleName("ntuple");
importer1->Import();

auto reader = RNTupleReader::Open("ntuple", fileGuard1.GetPath());
auto viewA = reader->GetView<std::int32_t>("a");
auto reader1 = RNTupleReader::Open("ntuple", chainFileGuard.GetPath());
auto viewA = reader1->GetView<std::int32_t>("a");

EXPECT_EQ(2U, reader->GetNEntries());
EXPECT_EQ(2U, reader1->GetNEntries());
EXPECT_EQ(42, viewA(0));
EXPECT_EQ(43, viewA(1));

EXPECT_THROW(importer->Import(), ROOT::Experimental::RException);
EXPECT_THROW(importer1->Import(), ROOT::Experimental::RException);

TChain unnamedChain;
unnamedChain.Add((treeFileGuard.GetPath() + "?#tree1").c_str());
unnamedChain.Add((treeFileGuard.GetPath() + "?#tree2").c_str());

auto importer2 = RNTupleImporter::Create(&unnamedChain, chainFileGuard.GetPath());
importer2->SetIsQuiet(true);
importer2->Import();

// Without explicitly setting the name of the imported chain, we expect it to be equal to the name of the first tree
// in the chain.
std::unique_ptr<RNTupleReader> reader2;
EXPECT_NO_THROW(reader2 = RNTupleReader::Open("tree1", chainFileGuard.GetPath()));
EXPECT_EQ(2U, reader2->GetNEntries());
}

TEST(RNTupleImporter, Simple)
Expand Down

0 comments on commit 46f2e5f

Please sign in to comment.