Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions tree/ntupleutil/v7/inc/ROOT/RNTupleImporter.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ importer->Import();
~~~

The output file is created if it does not exist, otherwise the ntuple is added to the existing file.
Directories in the output file are created as necessary, allowing ntuples to be stored in a nested structure (e.g. DirName/TreeName).
Note that input file and output file can be identical if the ntuple is stored under a different name than the tree
(use `SetNTupleName()`).

Expand Down
19 changes: 17 additions & 2 deletions tree/ntupleutil/v7/src/RNTupleImporter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -371,13 +371,28 @@ ROOT::RResult<void> ROOT::Experimental::RNTupleImporter::PrepareSchema()

void ROOT::Experimental::RNTupleImporter::Import()
{
if (fDestFile->FindKey(fNTupleName.c_str()) != nullptr)
TDirectory *targetDir = fDestFile.get();
// Extract the ntuple name and directory name
auto lastSlash = fNTupleName.find_last_of('/');
std::string ntupleName = fNTupleName;
if (lastSlash != std::string::npos) {
// Create the directory in the output file if it does not exist
auto dirName = fNTupleName.substr(0, lastSlash);
ntupleName = fNTupleName.substr(lastSlash + 1);
targetDir = fDestFile->mkdir(dirName.c_str(), "", true);
if (!targetDir) {
throw RException(R__FAIL("Failed to create directory " + dirName + " in file " + fDestFileName));
}
}

if (targetDir->FindKey(ntupleName.c_str()) != nullptr) {
throw RException(R__FAIL("Key '" + fNTupleName + "' already exists in file " + fDestFileName));
}

PrepareSchema();

std::unique_ptr<ROOT::Internal::RPageSink> sink =
std::make_unique<ROOT::Internal::RPageSinkFile>(fNTupleName, *fDestFile, fWriteOptions);
std::make_unique<ROOT::Internal::RPageSinkFile>(ntupleName, *targetDir, fWriteOptions);
sink->GetMetrics().Enable();
auto ctrZippedBytes = sink->GetMetrics().GetCounter("RPageSinkFile.szWritePayload");

Expand Down
22 changes: 22 additions & 0 deletions tree/ntupleutil/v7/test/ntuple_importer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,28 @@ TEST(RNTupleImporter, Empty)
EXPECT_THROW(importer->Import(), ROOT::RException);
}

TEST(RNTupleImporter, CreateInDirectory)
{
FileRaii fileGuard("test_ntuple_importer_create_in_directory.root");
{
std::unique_ptr<TFile> file(TFile::Open(fileGuard.GetPath().c_str(), "RECREATE"));
TDirectory *dir = file->mkdir("dir1");
ASSERT_NE(dir, nullptr);
file->cd("dir1");
auto tree = std::make_unique<TTree>("tree", "");
tree->Write();
}

auto importer = RNTupleImporter::Create(fileGuard.GetPath(), "dir1/tree", fileGuard.GetPath());
importer->SetIsQuiet(true);
EXPECT_THROW(importer->Import(), ROOT::RException);
importer->SetNTupleName("dir2/ntuple");
importer->Import();
auto reader = RNTupleReader::Open("dir2/ntuple", fileGuard.GetPath());
EXPECT_EQ(0U, reader->GetNEntries());
EXPECT_THROW(importer->Import(), ROOT::RException);
}

TEST(RNTupleImporter, CreateFromTree)
{
FileRaii fileGuard("test_ntuple_importer_empty.root");
Expand Down
Loading