Contents
Saving and loading Histograms¶
Warning
The URL for this page may change, the general design for this tutorial series is in flux.
Format conversion between ROOT and boost-histogram can be performed by Scikit-HEP tools. Aghast is a histogramming library to provide better communication between histogramming libraries, instead of filling or plotting them. Here, you can see how to convert between ROOT and boost-histogram by Aghast.
Authors
# Conda-forge ROOT, provided by Scikit-HEP
import ROOT
# Standard imports
import numpy as np
import os
import matplotlib.pyplot as plt
# Scikit-HEP packages
import boost_histogram as bh
import aghast
import uproot
Welcome to JupyROOT 6.24/06
Note
Importing ROOT interferes with Jupyter/IPython, causing tab completion to break and “X is not defined” to be printed out ad-nauseam to the terminal. Sorry. Many cases can be handled by uproot, which avoids this dependency and irritaiton.
boost-histogram to ROOT via ROOT¶
Let’s start with a boost-histogram:
h = bh.Histogram(bh.axis.Regular(15, -3, 3))
h.fill(np.random.normal(size=1_000_000))
# Quick plot
plt.bar(h.axes[0].centers, h, h.axes[0].widths);
If you want a ROOT histogram from boost-histogram object, convert the boost-histogram object to an Aghast histogram at first, and then convert the Aghast histogram to ROOT histogram. We currently need to use to/from NumPy to communicate between the libraries (don’t worry, a copy is not made).
ghastly_hist = aghast.from_numpy(h.to_numpy())
ghastly_hist
<Histogram at 0x7f1de81d3ee0>
Now let’s write this with ROOT. Notice that ROOT uses a stateful global interface, so we open a file, we make a new object, then we save the file - the object is created in the open file “magically”. (Does this sound like a problem for things like threading? Yes, it is. It’s going away in ROOT 7 eventually.)
file = ROOT.TFile("demo_root_file.root", "RECREATE")
root_hist = aghast.to_root(ghastly_hist, "root_hist")
file.Write()
342
Now, let’s open the file with uproot:
rf = uproot.open("demo_root_file.root")
th1 = rf["root_hist"]
th1.show()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
/tmp/ipykernel_7079/745223769.py in <module>
1 rf = uproot.open("demo_root_file.root")
2 th1 = rf["root_hist"]
----> 3 th1.show()
AttributeError: 'Model_TH1D_v3' object has no attribute 'show'
You can see that these are similar, though aghast doesn’t handle the overflow bins in the NumPy format yet:
th1.allnumpy()
h.to_numpy()
boost-histogram to ROOT via uproot¶
If you want to save and load simple ROOT histograms, uproot is able to read and write directly in NumPy format:
root_file = uproot.recreate("demo_uproot_file.root")
root_file["words"] = "See what is in the ROOT File!"
root_file["hist"] = h.to_numpy()
There is no .close()
or context manager here. Uproot 3 closes the file after every operation. Context managers will be available in Uproot 4.
Let’s reopen the file:
root_file2 = uproot.open("demo_uproot_file.root")
print(root_file2["words"])
root_file2["hist"].show()
ROOT to boost-histogram¶
Similarly, you can convert a ROOT histogram to boost-histogram histogram. You’ll want to avoid the \(\infty\) on either end of the NumPy array when you access the edges, and instead rely on the built-in flow bins.
ghastly_hist = aghast.from_root(root_hist)
data, edges = aghast.to_numpy(ghastly_hist)
h = bh.Histogram(bh.axis.Variable(edges[1:-1]))
h[:] = data
plt.bar(h.axes[0].centers, h.view(), width=h.axes[0].widths);
%rm demo_uproot_file.root demo_root_file.root