Examples of working with ROOT dictionaries

28-Feb-2024 William Seligman

This directory (at Nevis, ~seligman/root-class/root-dict) is an extension of my ROOT tutorial. It follows in logical succession from the last Expert Exercise. The files herein contains various examples of how to create ROOT TTrees that contain more complex structures than simple numeric or vector values.

There are two different approaches to creating ROOT I/O dictionaries for your custom classes. They’re both discussed below:

The files are listed below in the rough order that I think will teach you how to create your own TTrees. Go through the files, read the comments, and run the example commands in the files’ comments.

For more information:

The basic definition

STL_TrackList.h = This defines an example class that might be used for a simple definition for detector tracks and the steps within those tracks. It’s intended as a coding example, and has little to do with actual physics.

STLntupleTypes.h = This file contains a few custom type definitions to make some of the code lines shorter.

Generating dictionaries dynamically

STLntuple.icc = This is a C++ code-include file. It contains common C++ executable code for dynamically generating ROOT dictionaries for the class we’re writing and reading to the example ROOT TTree. You’ll see it included in both of the following files:

STLntupleCreate.cxx = A program that creates a TTree with various complex C++ classes as branches.

STLntupleRead.cxx = A program to read that TTree and make various histograms to test that everything works.

STLntupleRead.py = A Python program that does the same thing as the above C++ program.

STLntupleRDF.cxx = This is an example of using RDataFrame to read a TTree. Since that would be too easy once you understand STLntupleRead, I go further and demonstrate how to write multi-threaded code for making histograms.

Generating dictionary libraries

In the programs in the previous section, the dictionaries would be generated automatically if they didn’t already exist. But the dictionary-generating process takes time. While that’s fine for interactive or infrequent use, it’s not suitable if you want to create batch jobs for working with millions of events.

The files listed below are an example of how to generate dictionary libraries which are included in a program’s executable when it is compiled and linked, or (in the case of Python) can be loaded quickly.

STL_LinkDef.h = This is an example of a LinkDef file. A file like this is required if you’re going to create a compiled dictionary for ROOT I/O on anything more complicated than simple values (int, float, double, std::string) or vectors. It defines the C++ structures for which rootcling will generate dictionaries.

STLntupleCreateDict.cxx = The same as STLntupleCreate, except that it uses the pre-compiled dictionary instead of dynamically creating dictionaries.

STLntupleReadDict.cxx = The same as STLntupleRead, except that it uses the pre-compiled dictionary instead of dynamically creating dictionaries.

STLntupleReadDict.py = A Python program that does the same thing as the above C++ program.

The ROOT files created by the programs in this section have different names (they have Dict appended to the name), but they are functionally the same as the ROOT files created with the dynamically-generated dictionaries (up to the random numbers potentially being different in the two Create programs). If you want to fiddle with the TFile::Open statements in the programs, the .root files created by the programs using dynamically-generated dictionaries can be read by the programs using the shared-library dictionaries, and vice versa.