Adaptive binning

Here we will visit all the classes and functions designed to work with adaptive binned histograms.

[1]:
%matplotlib inline
import hep_spt
hep_spt.set_style('multiplot')
import matplotlib.pyplot as plt
import matplotlib as mpl
import numpy as np
from mpl_toolkits.axes_grid1 import make_axes_locatable

Adaptive binning in 1 dimension

Let’s generate an adaptive binned histogram in 1 dimension. We will create three histograms. One will be the raw histogram (with equal-size bins). The second will have adaptive bins, and the second will be the same as the latter but considering some weights for the input sample.

[2]:
# Create a random sample
size = 1000
smp  = np.random.normal(0., 2, size)
wgts = np.random.uniform(0, 1, size)

figs, (root, al, ar) = plt.subplots(1, 3, figsize=(15, 5))

# Draw the normal distribution
bins = 20
rg   = (-10, 10)

root.hist(smp, bins, rg, label = 'raw')
root.set_title('raw')

# Draw both the non-weighted and the weighted adaptive binned histograms
for s, w, a, t in ((smp, None, al, 'adaptive binned'),
                   (smp, wgts, ar, 'weighted adaptive binned')):

    values, edges, ex, ey = hep_spt.adbin_hist1d(s, weights=w, nbins=bins, range=rg)
    centers = (edges[1:] + edges[:-1])/2.

    a.errorbar(centers, values, ey, ex, ls = 'None')
    a.set_ylim(0, 1.5*values.max())
    a.set_title(t)
../_images/notebooks_adbin_3_0.png

Adaptive binning in 2 dimensions

Now let’s take a look at 2-dimensional histograms. First we will define a function to help us to draw 2-dimensional adaptive binned histograms.

[3]:
def _draw_adbin_hist( ax, s, nbins, range, weights = None, **kwargs ):
    '''
    Helper function to plot points and overlaid an adaptive binned histogram.
    '''
    bins = hep_spt.adbin_hist(s, nbins, range, weights)

    recs, cons = hep_spt.adbin_hist2d_rectangles(bins, s, **kwargs)

    ax.plot(x, y, '.k', alpha=0.01)

    for r in recs:
        ax.add_patch(r)

    ax.set_xlim(*range.T[0])
    ax.set_ylim(*range.T[1])

    return recs, cons

Now, we will create a figure showing the evolution of the algorithm to create adaptive bins on a non-weighted sample. Next to it, we will plot the status for a step showing with text the sum of weights in each bin, and another histogram with the weighted case.

[4]:
# For reproducibility
np.random.seed(187391)

# Create a random sample
size = 2500

region = lambda c, s: np.random.normal(c, s, size)

x = np.concatenate([region(-2, 0.5), region(0, 0.5), region(0, 0.5), region(2, 0.5)])
y = np.concatenate([region(0, 0.5), region(-2, 0.5), region(2, 0.5), region(0, 0.5)])
s = np.array([x, y]).T
w = np.random.uniform(0, 1, 4*size)
r = np.array([(-4, -4), (+4, +4)])

# Create the main figure
fig = plt.figure(figsize = (16, 10))

# Create one plot for each step of the divisions
nx = ny = 2
for i in range(nx):
    for j in range(ny):

        a = fig.add_subplot(nx, ny + 1, i*(ny + 1) + j + 1)

        n = 2**(i*ny + j)

        _draw_adbin_hist(a, s, n, r, ec='k')

        a.set_title('{} divisions'.format(n))

# Create a histogram with the data displayed as text in the bins
ax = fig.add_subplot(nx, ny + 1, (nx - 1)*(ny + 1))
ax.set_title('{} divisions'.format(4))

recs, cons = _draw_adbin_hist(ax, s, 4, r, ec='k', color=False)

txt = ['{:.2f}'.format(c) for c in cons]

hep_spt.text_in_rectangles(recs, txt, va='center', ha='center', cax=ax)

# Draw the weighted sample with the color bar
ax = fig.add_subplot(nx, ny + 1, nx*(ny + 1))
ax.set_title('{} divisions (weighted)'.format(4))

_, cons = _draw_adbin_hist(ax, s, 4, r, w, ec='k')

divider = make_axes_locatable(ax)
cax = divider.append_axes('right', size='5%', pad=0.05)

norm = mpl.colors.Normalize(vmin=cons.min(), vmax=cons.max())

mpl.colorbar.ColorbarBase(cax, norm=norm);
../_images/notebooks_adbin_7_0.png
[5]: