ROOT files

ROOT files contain C++ objects that are stored to disk. You can open files when starting ROOT

$ root file.root

or within C++

std::unique_ptr<TFile> myFile( TFile::Open("file.root") );

or Python code

myFile = ROOT.TFile.Open("file.root")

In ROOT you can save objects in ROOT files, making these objects “persistent”. Later on, you can read these objects back: the object is reconstructed in memory.

ROOT files often contain columnar data, used for instance by all LHC (Large Hadron Collider) experiments.

Storing an object in a ROOT file and reading it back

Here we will create a new ROOT file, store a histogram, and read it back.

Creating a ROOT file

Use the function Open() from TFile to create or open a ROOT file.

std::unique_ptr<TFile> myFile( TFile::Open("file.root", "RECREATE") );
myFile = ROOT.TFile.Open("file.root", "RECREATE")

For the second argument, the following options are available:

  • "RECREATE": create a ROOT file, replacing it if it already exists.
  • "CREATE" or "NEW": create a ROOT file.
  • "UPDATE": updates the ROOT file.
  • "READ": opens an existing ROOT file for reading.

Storing an object in a ROOT file

You can save any object, for instance canvases or histograms, into a ROOT file. You can even store your own types.

TFile derives from TDirectory; use TDirectory::WriteObject() to write an object to a ROOT file.

Example

A copy of the object myObject is written to the file myFile. In the file, it can be found back under the name "MyObject".

myFile->WriteObject(&myObject, "MyObject");
myFile.WriteObject(myObject, "MyObject")

Closing a ROOT file

ROOT will automatically save and close any ROOT files still open when the session ends. The ROOT file is also saved and closed when deleting / destructing the TFile object.

void closeAtDestruct(TH1 *hist) {
   std::unique_ptr<TFile> myFile( TFile::Open("file.root", "RECREATE") );
   myFile->WriteObject(hist, "MyHist");
   // At the end of the function, the unique_ptr gets destructed.
   // It deletes the `TFile` object, which in turn saves and closes
   // the ROOT file.
}
def closeAtDestruct(hist):
   myFile = ROOT.TFile.Open("file.root", "RECREATE")
   myFile.WriteObject(hist, "MyHist")
   # At the end of the function, there are no more references to `file`.
   # The `TFile` object gets deleted, which in turn saves and closes
   # the ROOT file.

Opening and inspecting a ROOT file

Use TFile::Open() to open a ROOT file. While this operation might return a valid pointer to a TFile object, this object might not be able to access data, for instance because ROOT was unable to open the file in the filesystem. Use TObject::IsZombie() to check whether the ROOT file was successfully opened.

std::unique_ptr<TFile> file( TFile::Open("file.root") );
if (!file || file->IsZombie()) {
   std::cerr << "Error opening file" << endl;
   exit(-1);
}

Apart from rootls and the object browser introduced below, TFile::ls() lists what is in the ROOT file.

root [] std::unique_ptr<TFile> myFile( TFile::Open("file.root") );
...
root [] myFile->ls()
TFile**		file.root	
 TFile*		file.root	
  OBJ: TH1F	myHist	histo : 0 at: 0x5592d774c2e0
  KEY: TH1F	myHist;2	histo [current cycle]
  KEY: TH1F	myHist;1	histo [backup cycle]

By default, existing objects are not replaced when writing new objects with the same name. Instead, a new namecycle is created, denoted by ;2, ;3, etc. When retrieving the object from the file, ROOT will automatically pick the highest namecycle.

Some objects, such as histograms, automatically register themselves with the current TDirectory (e.g. the last TFile opened): these objects will appear as OBJ entries, without a namecycle. See also → Object ownership.

For the particular case of TTree, cycles only store metadata, see Baskets, clusters and the tree header.

Reading an object from a ROOT file

In C++, use the Get<T>() method to retrieve the objects from a ROOT file.
In Python, objects in the file are accessible as attributes.

Example

The histogram MyHist is retrieved from the ROOT file file.root.

std::unique_ptr<TFile> myFile( TFile::Open("file.root") );
std::unique_ptr<TH1> hist(myFile->Get<TH1>("MyHist"));
myFile = ROOT.TFile.Open("file.root")
hist = myFile.MyHist

Storing columnar data in a ROOT file and reading it back

In addition to individual objects, ROOT files can also store tabular datasets, formed by rows and columns. Such datasets are optimized for fast reading of selected columns during an analysis (throughput in the order of GB/s) and for low memory usage by keeping only a few rows in memory.

Note

Tabular datasets in ROOT are actually not just flat tables, but their columns can contain complex nested collections.

In High-Energy Physics, more than one exabyte of data is stored in ROOT’s tabular format.

The easiest way to process ROOT columnar datasets is RDataFrame. A more thorough introduction to RDataFrame can be found → here.

Writing a columnar dataset with ROOT

RDataFrame provides a method called Snapshot to write a columnar dataset to a ROOT file.

The example below creates a new dataset with 100 rows, with one column x that contains random numbers, and stores that dataset in a file called output.root.

ROOT::RDataFrame rdf(100);
auto rdf_x = rdf.Define("x", [](){ return gRandom->Rndm(); });
rdf_x.Snapshot("my_dataset", "output.root");
rdf = ROOT.RDataFrame(100)
rdf_x = rdf.Define("x", "gRandom->Rndm()")
rdf_x.Snapshot("my_dataset", "output.root")

Reading a columnar dataset with ROOT

Let’s see now how to read and process the dataset we just wrote, creating a 1D histogram of column x.

ROOT::RDataFrame rdf("my_dataset", "output.root");
auto h = rdf.Histo1D("x");
h->Draw();
rdf = ROOT.RDataFrame("my_dataset", "output.root")
h = rdf.Histo1D("x")
h.Draw()

Besides ROOT files, RDataFrame can also read from other data sources, for example CSV files:

auto rdf = ROOT::RDF::FromCSV("myfile.csv");
auto h = rdf.Histo1D("x");
h->Draw();

Merging ROOT files with hadd

Use the hadd utility in $ROOTSYS/bin/hadd to merge ROOT files:

$ hadd output.root input1.root input2.root ...

ROOT command line tools

With the ROOT command line tools you can quickly inspect and modify the contents of ROOT files. The most commonly used ones are:

  • rootls: Lists the content of a ROOT file.
  • rootcp: Copies objects stored in a ROOT file to another ROOT file.
  • rootrm: Deletes objects contained in a ROOT file.
  • rootmv: Moves objects stored in a ROOT file to another ROOT file.
  • rootmkdir: Creates a “directory” inside a ROOT file.
  • rootbrowse: Opens a TBrowser directly with the contents of a ROOT file.
  • rooteventselector: Extracts a range of events of a tree contained in a ROOT file and put them as a new tree in another ROOT file.
  • rootprint: Plots objects in an image ROOT file.
  • rootslimtree: Copies trees with a subset of branches from source ROOT files.

Use the -h option to get more information on the available options for the specific ROOT command line tool.

Example

On the system prompt, you can use the ROOT command line tool rootls to list the contents of a ROOT file.

$ rootls hsimple.root
hprof  hpx  hpxpy  ntuple

ROOT object browser

With a TBrowser you can browse all ROOT objects within a ROOT file. You can open it with the rootbrowse command or as part of a ROOT session, instantiating a TBrowser object:

   $ root file.root
   root[0] TBrowser b

The ROOT object browser is displayed.

Figure: ROOT object browser.

Double-click the ROOT file to inspect its content.

Figure: ROOT object browser displaying the content of a ROOT file.

Double-clicking graphical objects displays them in a canvas tab. Double-clicking files that end with .C displays them in an editor tab.

Accessing a remote ROOT file

You can read and write a remote ROOT file by specifying its URL to TFile::Open().

Depending on the features of your ROOT installation, the following protocols will be available:

URI Scheme Protocol
http:// unencrypted HTTP
https:// encrypted HTTP
root:// Xrootd
s3:// S3

Xrootd is a high-performance, authenticated data transfer protocol. S3 is the standard API for object store data transfer.

Example

Simple session:

std::unique_ptr<TFile> myFile( TFile::Open("https://root.cern/files/na49.root") );