This is more of a note for myself. Over time, I’ve learned some useful fact about ROOT that I now wish I have known when I started using ROOT. Hopefully as a ROOT user, you could also find some of these helpful.
Tell ROOT to not show the startup banner
You do:
user@somepc:~$ root -l
To make root shut-up and don’t show the banner. It can get fairly annoying when you are debugging some problem in your interpreted code. This is the default behavior after ROOT 6.20. Good job ROOT team.
Exit after executing a script
Like Python and any other scripting language, you can use ROOT as a C++ script executor. However, unlike most scripting languages, ROOT drops you a command prompt after finishing the script. You add a -q
flag to make root exit automatically.
user@somepc:~$ root do_stuff.cpp -q -l
root [0]
Processing do_stuff.cpp...
user@somepc:~$
Accessing fitted parameters
So you just fitted as Gaussian distribution, and you need to get the parameters programmatically.
# This is PyROOT code. But C++ works exactly the same way
h1 = TH11("h1", "Histogram of something"
, len(data), min(data), max(data))
"""
some code here...
bla bla bla...
"""
h1.fit("gaus")
f1 = h1.GetFunction("gaus")
print(f1)
for i in range(f1.GetNumberFreeParameters()):
p = f1.GetParameter(i)
print("p{} = {}".format(i, p))
Using ROOT in a standalone application.
Sometimes you just need a standalone app instead of script. Maybe for performance reasons. You totally can do so! Just use ROOT normally. If you need the ROOT GUI, initialize a TApplication
and then call Run()
.
# Again this is PyROOT code. But the C++ version works the same way
import ROOT
import sys
app = ROOT.TApplication(sys.argc, sys.argv)
"""
load data, do calculations, etc...
f = ROOT.TFIle("data.root")
t = f.Get("data")
...
"""
h1.Draw()
c1.Draw()
app.Run() # Run ROOT's event loop
But maybe you can’t have a blocking event loop. That’s fine too.
while some_window.isRunning():
some_window.pullEnvent() # Run your window
app.processEvent() # Let ROOT update it's interfaces
As a Python <-> C++ binder
This feature can be accessed as an independent package – cppyy. But heck, why use cppyy when we have the full ROOT. So, assuming you have a awesome C++ library that you want to use in Python, but it doesn’t come with a Python binding.
import ROOT
gROOT = ROOT.gROOT
gROOT.ProcessLine('#include "your_lib.h"')
gSystem.Load('your_lib') # if its not header only
my_cpp_class = ROOT.my_cpp_class
my_class = my_cpp_class()
# It also works with the STL
cpp_vector = ROOT.std.vector(int)()
Matplotlib colors
The default ROOT colors are ugly. That’s fine, we can always switch to a better color pallet. Like the ones in matplotlib
// C++ code
auto c0 = TColor::GetColor("#1f77b4");
auto c1 = TColor::GetColor("#ff7f0e");
auto c2 = TColor::GetColor("#2ca0c2");
auto c3 = TColor::GetColor("#d62728");
auto c4 = TColor::GetColor("#9467bd");
auto c5 = TColor::GetColor("#8c564b");
auto c6 = TColor::GetColor("#e377c2");
auto c7 = TColor::GetColor("#7f7f7f");
auto c8 = TColor::GetColor("#bcbd22");
auto c9 = TColor::GetColor("#17becf");
Save the current canvas for use later
After making a plot. You can serialize the entire plot so you can work on it later! It saves all the internal states of the plot nit just image files!
auto c1 = new TCanvas("c1", "canvas");
// Plot whatever you want
...
c1->Draw();
// Now save the plot!
c1->SaveAs("c1.root"); // You can load the canvas later on
c1->SaveAs("c1.C"); // Save as C++ source code. Run `.x c1.C` then you can use c1 again.
Save canvas as LaTeX
This feature should be well know. But if you didn’t. Yes, you can save your plots as LaTeX files directly and use them in LaTeX. I’ve use the feature very extensively for my project reports.
c1->SaveAs("my_plot.tex");
Then use it in LaTeX as usual.
\begin{figure}
\begin{center}
\include{my_plot}
\label{my_plot:figure}
\caption{"Some random ROOT plot"}
\end{center}
\end{figure}
Just be aware that LaTeX use a different font. So you might need to adjust your legends.
Convert CSV into ROOT archive
Getting data into ROOT can be cannoning at times. Epically when we have to deal with trees and branches. If you have columnar data, newer ROOT comes with RDataFrame that can do it for you!
auto rdf = ROOT::RDF::MakeCsvDataFrame("data.csv");
rdf.Snapshot("data.root", "ntuple");
Disable histogram statistics
If you find the statistics box annoying and providing useless information. You can disable it with one line.
gStyle->SetOptStat(0);
Now instead of this

You get this:

Disable TGraph markers
If you find the markers from TGraph annoying.
gStyle->SetMarkerStyle(0);
Normalizing Histograms
That’s say you’re tasked to build an normalized histogram. Like… Having the data of 1000 cars, their owners age. And you need to build a histogram where the x-axis is the age of the owner and the y axis is on average how many cars they own. It can be annoying to do in plain C++. But no worries. ROOT have that covered.
// Let's say you have the histogram h1 and h2
TH1D h1 = hist_car_owner();
TH1D h2 = hist_owner_age();
auto normalized = h1/h2; // Ta da!
Use RDataFrame instead of PROOF if you can
PROOF is one of the very first distributed computing framework (Even before Hadoop!) designed by CERN to perform huge computations. Although I’m a fan of PROOF’s simplistic and scalable design. PROOF is not user friendly even for computer scientists. So don’t use it. The new RDataFrame is a lot faster (due to not distributed just parallel) and a 60 thread machine is more likely to be bottle necked by data access anyway.
Unless you have a good reason to use PROOF. Just use RDataFrame.
Using ROOT in normal Jupyter
The JupyROOT directory documents how to make the ROOT C++ kernel available under Jupyter.
cp -r $ROOTSYS/etc/notebook/kernels/root ~/.local/share/jupyter/kernels
Then launch Jupyter normally. You’ll see ROOT available there. No more launching with root --notebook
.
Final words:
ROOT is quite capable and you can do some crazy stuff with it. You just have to find it… Let me know if you have some favorite tricks.
Leave a Reply