diff --git a/io/io/test/rfile.cxx b/io/io/test/rfile.cxx index 2d40607e6e703..7116d3c102965 100644 --- a/io/io/test/rfile.cxx +++ b/io/io/test/rfile.cxx @@ -36,7 +36,7 @@ class FileRaii { if (!fPreserveFile) std::remove(fPath.c_str()); } - std::string GetPath() const { return fPath; } + const std::string &GetPath() const { return fPath; } // Useful if you want to keep a test file after the test has finished running // for debugging purposes. Should only be used locally and never pushed. diff --git a/tutorials/io/experimental/rfile001_basics.C b/tutorials/io/experimental/rfile001_basics.C new file mode 100644 index 0000000000000..9b6a56578a923 --- /dev/null +++ b/tutorials/io/experimental/rfile001_basics.C @@ -0,0 +1,55 @@ +/// \file tutorials/io/experimental/rfile001_basics.py +/// \ingroup Base ROOT7 tutorial_io +/// \author Giacomo Parolini +/// \date 2025-11-06 +/// \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! + +void write_hist_to_rfile(const char *fileName) +{ + // Create a histogram to write to the file + TH1D hist("hist", "hist", 10, 0, 100); + hist.FillRandom("gaus", 1000); + + // Create a new ROOT file for writing + auto file = ROOT::Experimental::RFile::Recreate(fileName); + + // Put objects into the file (in this case we write the same object multiple times + // under different paths). Note that the ownership of `hist` is untouched by `file->Put`. + file->Put(hist.GetName(), hist); + file->Put(std::string("a/") + hist.GetName(), hist); + file->Put(std::string("a/b/") + hist.GetName(), hist); + + // When `file` goes out of scope it will write itself to disk. + // To manually write the file to disk without closing it, one can use `file->Flush()`. +} + +void read_hist_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); + // Iterate all keys of all objects in the file (this excludes directories by default - see the documentation of + // ListKeys() for all the options). + for (auto key : file->ListKeys()) { + // Retrieve the objects from the file. `file->Get` will return a `std::unique_ptr` to the object, or `nullptr` + // if the object isn't there. + // Once an object is retrieved, it is fully owned by the application, so it survives even if `file` is closed. + auto hist = file->Get(key.GetPath()); + if (!hist) + continue; + std::cout << key.GetClassName() << " at " << key.GetPath() << ';' << key.GetCycle() << ":\n"; + std::cout << " entries: " << hist->GetEntries() << "\n"; + } +} + +void rfile001_basics() +{ + const char *const fileName = "rfile_basics.root"; + + write_hist_to_rfile(fileName); + read_hist_from_rfile(fileName); + + gSystem->Unlink(fileName); +} diff --git a/tutorials/io/experimental/rfile001_basics.py b/tutorials/io/experimental/rfile001_basics.py new file mode 100644 index 0000000000000..75e9ac77a6be2 --- /dev/null +++ b/tutorials/io/experimental/rfile001_basics.py @@ -0,0 +1,53 @@ +# \file tutorials/io/experimental/rfile001_basics.py +# \ingroup Base ROOT7 tutorial_io +# \author Giacomo Parolini +# \date 2025-11-06 +# \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! + +import ROOT + +import os + +def write_hist_to_rfile(fileName): + # Create a histogram to write to the file + hist = ROOT.TH1D("hist", "hist", 10, 0, 100) + hist.FillRandom("gaus", 1000) + + # Create a new ROOT file for writing + with ROOT.Experimental.RFile.Recreate(fileName) as file: + # Put objects into the file (in this case we write the same object multiple times + # under different paths). Note that the ownership of `hist` is untouched by `file.Put`. + file.Put(hist.GetName(), hist) + file.Put(f"a/{hist.GetName()}", hist) + file.Put(f"a/b/{hist.GetName()}", hist) + + # 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). + with ROOT.Experimental.RFile.Open(fileName) as file: + # Iterate all keys of all objects in the file (this excludes directories by default - see the documentation of + # ListKeys() for all the options). + for key in file.ListKeys(): + # Retrieve the objects from the file. `file.Get` will return an object of the proper type or None if + # the object isn't there. + # Once an object is retrieved, it is fully owned by the application, so it survives even if `file` is closed. + hist = file.Get(key.GetPath()) + if hist is not None: + continue + print(f"{key.GetClassName()} at {key.GetPath()};{key.GetCycle()}:") + print(f" entries: {hist.GetEntries()}") + + +fileName = "rfile_basics_py.root" +try: + write_hist_to_rfile(fileName) + read_hist_from_rfile(fileName) + os.remove(fileName) +except FileNotFoundError: + pass