Saving and loading Histograms

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);
../_images/aghast_6_0.png

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

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);
../_images/aghast_6_0.png

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