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
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ def _RNTupleWriter_Append(model, *args):
model = model.Clone()
import ROOT

if len(args) > 1 and isinstance(args[1], ROOT.Experimental.RFile):
return RNTupleContextWrapper(ROOT.Experimental.RNTupleWriter_Append(model, *args), "RNTupleWriter", on_ctx_exit = _RNTupleWriter_exit)

return RNTupleContextWrapper(ROOT.RNTupleWriter._Append(model, *args), "RNTupleWriter", on_ctx_exit = _RNTupleWriter_exit)


Expand Down
2 changes: 2 additions & 0 deletions tutorials/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ if (NOT dataframe)
# RNTuple tutorials depending on RDataFrame
list(APPEND dataframe_veto io/ntuple/ntpl004_dimuon.C)
list(APPEND dataframe_veto io/ntuple/ntpl008_import.C)
# RFile tutorials depending on RDataFrame
list(APPEND dataframe_veto io/experimental/rfile/rfile003_ttree.C)
endif()

if(NOT sqlite)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
# \date 2025-11-06
# \author Giacomo Parolini <giacomo.parolini@cern.ch>

import ROOT

import os

Check failure on line 16 in tutorials/io/experimental/rfile/rfile001_basics.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (I001)

tutorials/io/experimental/rfile/rfile001_basics.py:14:1: I001 Import block is un-sorted or un-formatted help: Organize imports


def write_hist_to_rfile(fileName):
# Create a histogram to write to the file
hist = ROOT.TH1D("hist", "hist", 10, 0, 100)
Expand All @@ -30,7 +31,7 @@

# When the `with` statement is exited the file will write itself to disk and close itself.
# To manually write the file without closing it, one can use `file.Flush()`.


def read_hist_from_rfile(fileName):
# Open an existing ROOT file for reading (will raise an exception if `fileName` cannot be read).
Expand Down
62 changes: 62 additions & 0 deletions tutorials/io/experimental/rfile/rfile002_rntuple.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/// \file
/// \ingroup ROOT7 tutorial_io
/// Demonstrate how to read/write an RNTuple with RFile
///
/// \macro_code
/// \macro_output
///
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
Comment thread
silverweed marked this conversation as resolved.
/// is welcome!
///
/// \date 2026-10-12
/// \author Giacomo Parolini <giacomo.parolini@cern.ch>

void write_rntuple_to_rfile(const char *fileName)
{
// Create a new ROOT file for writing
auto file = ROOT::Experimental::RFile::Recreate(fileName);

// Define the RNTuple schema
auto model = ROOT::RNTupleModel::Create();
auto pInt = model->MakeField<int>("intField");

// Create an RNTupleWriter to append to the RFile
auto writer = ROOT::Experimental::RNTupleWriter_Append(std::move(model), "ntuple", *file);
Comment thread
vepadulano marked this conversation as resolved.

// Fill the RNTuple with data
for (int i = 0; i < 10; ++i) {
*pInt = i;
writer->Fill();
}

// `writer` will write the data to file upon destruction. Then `file` will write itself to disk in turn.
}

void read_rntuple_from_rfile(const char *fileName)
{
// Open an existing ROOT file for reading (will throw an exception if `fileName` cannot be read).
auto file = ROOT::Experimental::RFile::Open(fileName);

// Get back the RNTuple anchor from the file
auto rntuple = file->Get<ROOT::RNTuple>("ntuple");
R__ASSERT(rntuple); // we just wrote the RNTuple to the file so we expect to find it

// Create an RNTupleReader from the anchor
auto reader = ROOT::RNTupleReader::Open(*rntuple);
auto pInt = reader->GetModel().GetDefaultEntry().GetPtr<int>("intField");

for (auto i : reader->GetEntryRange()) {
reader->LoadEntry(i);
std::cout << "value[" << i << "] = " << *pInt << "\n";
}
}

void rfile002_rntuple()
{
const char *const fileName = "rfile_rntuple.root";

write_rntuple_to_rfile(fileName);
read_rntuple_from_rfile(fileName);

gSystem->Unlink(fileName);
}
58 changes: 58 additions & 0 deletions tutorials/io/experimental/rfile/rfile002_rntuple.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# \file
# \ingroup ROOT7 tutorial_io
# Demonstrate how to read/write an RNTuple with RFile
#
# \macro_code
# \macro_output
#
# \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
# is welcome!
#
# \date 2026-10-12
# \author Giacomo Parolini <giacomo.parolini@cern.ch>

import ROOT

import os

Check failure on line 16 in tutorials/io/experimental/rfile/rfile002_rntuple.py

View workflow job for this annotation

GitHub Actions / ruff

ruff (I001)

tutorials/io/experimental/rfile/rfile002_rntuple.py:14:1: I001 Import block is un-sorted or un-formatted help: Organize imports


def write_rntuple_to_rfile(fileName):
# Create a new ROOT file for writing
with ROOT.Experimental.RFile.Recreate(fileName) as file:
# Define the RNTuple schema
model = ROOT.RNTupleModel.Create()
model.MakeField["int"]("intField")
# Create an RNTupleWriter to append to the RFile
with ROOT.RNTupleWriter.Append(model, "ntuple", file) as writer:
entry = writer.CreateEntry()

# Fill the RNTuple with data
for i in range(10):
entry["intField"] = i
writer.Fill(entry)

# `writer` will write the data to file upon exiting the with statement....
# ...then `file` will write itself to disk in turn when exiting the outer with statement.


def read_rntuple_from_rfile(fileName):
# Open an existing ROOT file for reading (will throw an exception if `fileName` cannot be read).
with ROOT.Experimental.RFile.Open(fileName) as file:
# Get back the RNTuple anchor from the file
rntuple = file.Get("ntuple")

# Create an RNTupleReader from the anchor
with ROOT.RNTupleReader.Open(rntuple) as reader:
entry = reader.CreateEntry()
for i in reader.GetEntryRange():
reader.LoadEntry(i, entry)
print(f"value[{i}] = {entry['intField']}")


fileName = "rfile_rntuple_py.root"
try:
write_rntuple_to_rfile(fileName)
read_rntuple_from_rfile(fileName)
os.remove(fileName)
except FileNotFoundError:
pass
50 changes: 50 additions & 0 deletions tutorials/io/experimental/rfile/rfile003_ttree.C
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/// \file
/// \ingroup ROOT7 tutorial_io
/// Demonstrate how to read a TTree with RFile.
///
/// Note that, due to how TTree handles lifetime and its relationship with TDirectory, writing TTree through RFile
/// is currently unsupported.
///
/// \macro_code
/// \macro_output
///
/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
/// is welcome!
///
/// \date 2026-10-12
/// \author Giacomo Parolini <giacomo.parolini@cern.ch>
#include <iostream>
#include <TSystem.h>
#include <TTree.h>
#include <ROOT/RDataFrame.hxx>
#include <ROOT/RFile.hxx>

void read_tree_from_rfile(const char *fileName)
{
// Open an existing ROOT file for reading (will throw an exception if `fileName` cannot be read).
// IMPORTANT! This file must remain open while reading data from the tree.
auto file = ROOT::Experimental::RFile::Open(fileName);

// Get back the TTree from the file
auto tree = file->Get<TTree>("tree");
Comment thread
silverweed marked this conversation as resolved.
R__ASSERT(tree); // we just wrote the tree so we expect to find it in the file
int intVal;
tree->SetBranchAddress("intBranch", &intVal);

for (auto i = 0; i < tree->GetEntries(); ++i) {
tree->GetEntry(i);
std::cout << "value[" << i << "] = " << intVal << "\n";
}
}

void rfile003_ttree()
{
const char *const fileName = "rfile_ttree.root";

// Note that TTree cannot be written to RFile, so we use RDataFrame to write it instead.
ROOT::RDataFrame(10).Define("intBranch", "static_cast<int>(rdfentry_)").Snapshot("tree", fileName);

read_tree_from_rfile(fileName);

gSystem->Unlink(fileName);
}
45 changes: 45 additions & 0 deletions tutorials/io/experimental/rfile/rfile003_ttree.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# \file
# \ingroup ROOT7 tutorial_io
# Demonstrate how to read a TTree with RFile.
#
# Note that, due to how TTree handles lifetime and its relationship with TDirectory, writing TTree through RFile
# is currently unsupported.
#
# \macro_code
# \macro_output
#
# \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback
# is welcome!
#
# \date 2026-10-12
# \author Giacomo Parolini <giacomo.parolini@cern.ch>

import array
import os

import ROOT


def read_ttree_from_rfile(fileName):
# Open an existing ROOT file for reading (will throw an exception if `fileName` cannot be read).
# IMPORTANT! This file must remain open while reading data from the tree.
with ROOT.Experimental.RFile.Open(fileName) as file:
# Get back the TTree from the file
tree = file.Get("tree")
floatVal = array.array("f", [0])
tree.SetBranchAddress("floatBranch", floatVal)

for i in range(tree.GetEntries()):
tree.GetEntry(i)
print(f"value[{i}] = {floatVal[0]}")


fileName = "rfile_ttree_py.root"
try:
# Note that TTree cannot be written to RFile, so we use RDataFrame to write it instead.
ROOT.RDataFrame(10).Define("floatBranch", "static_cast<float>(rdfentry_)").Snapshot("tree", fileName)

read_ttree_from_rfile(fileName)
os.remove(fileName)
except FileNotFoundError:
pass
4 changes: 4 additions & 0 deletions tutorials/io/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ RFile is a simpler alternative to TFile that makes operations and object ownersh
|------|-----------------|
| rfile001_basics.C | Basic reading and writing from/to RFile (C++) |
| rfile001_basics.py | Basic reading and writing from/to RFile (Python) |
| rfile002_rntuple.C | Basic reading and writing of RNTuple from/to RFile (C++) |
| rfile002_rntuple.py | Basic reading and writing of RNTuple from/to RFile (Python) |
| rfile003_ttree.C | Basic reading of TTree from RFile (C++) |
| rfile003_ttree.py | Basic reading of TTree from RFile (Python) |
@}

\defgroup tutorial_ntuple RNTuple tutorials
Expand Down
Loading