def test_bh_conversion(): h = bh.Histogram(bh.axis.Regular(3, 2, 1, metadata={"name": "x"})) h.axes[0].name = "y" h2 = hist.Hist(h) assert isinstance(h2.axes[0], hist.axis.Regular) assert h2.axes[0].name == "y" assert h2.axes[0].metadata == {"name": "x"} h3 = bh.Histogram(h2) assert not isinstance(h3.axes[0], hist.axis.Regular) assert h2.axes[0].name == "y" assert h3.axes[0].metadata == {"name": "x"}
def test_str(): h1 = bh.Histogram(bh.axis.Regular(3, 0, 1)) h1.view(True)[...] = [0, 1, 3, 2, 1] assert repr(str(h1)) == repr( """ +---------------------------------------------------------+ [ -inf, 0) 0 | | [ 0, 0.3333) 1 |=================== | [0.3333, 0.6667) 3 |======================================================== | [0.6667, 1) 2 |===================================== | [ 1, inf) 1 |=================== | +---------------------------------------------------------+""" ) h2 = bh.Histogram(bh.axis.Regular(3, 0, 1), bh.axis.Integer(0, 1)) assert repr(str(h2)) == repr(repr(h2))
def test_slicing_projection(): h1 = bh.Histogram( bh.axis.Regular(10, 0, 10), bh.axis.Regular(10, 0, 10), bh.axis.Regular(10, 0, 10), ) X, Y, Z = np.mgrid[-0.5:10.5:12j, -0.5:10.5:12j, -0.5:10.5:12j] h1.fill(X.ravel(), Y.ravel(), Z.ravel()) assert h1[::bh.sum, ::bh.sum, ::bh.sum] == 12**3 assert h1[0:len:bh.sum, 0:len:bh.sum, 0:len:bh.sum] == 10**3 assert h1[0:bh.overflow:bh.sum, 0:len:bh.sum, ::bh.sum] == 10 * 10 * 12 assert h1[::bh.sum, 0:len:bh.sum, ::bh.sum] == 10 * 12 * 12 # make sure nothing was modified assert h1.sum() == 10**3 assert h1.sum(flow=True) == 12**3 h2 = h1[0:3:bh.sum, ...] assert h2[1, 2] == 3 h3 = h2[:, 5:7:bh.sum] assert h3[1] == 6 # Select one bin assert h1[2, ::bh.sum, ::bh.sum] == 12 * 12 # Select one bin assert h1[2, 7, ::bh.sum] == 12
def scale_and_plot(frame, new_lumi: float = 1., c=None, linewidth=1, label=None): xs = frame['weight_mc'].abs().sum() / len(frame.index) lumi = frame['weight'].sum() / xs hist = bh.Histogram(bh.axis.Regular(100, 300, 10000, transform=bh.axis.transform.log), storage=bh.storage.Weight()) hist.fill(frame['MC_WZ_dilep_m_born'], weight=new_lumi * frame['weight'], threads=6) # scale cross-section hist /= hist.axes[0].widths hep.histplot(hist.view().value, bins=hist.axes[0].edges, color=c, linewidth=linewidth, label=label) return xs, lumi
def test_plottible_histogram_simple_var(): h = bh.Histogram(bh.axis.Variable([0, 1, 2, 3, 4])) # Setting directly or filling with weight should cause variances to # be None. Manipulations directly on the view, however, are up to the user # - once you've asked for a view of the memory, you should know what your # are doing. At least if you change it inplace. h.view()[...] = VALUES assert_allclose(VALUES, h.counts()) assert_allclose(VALUES, h.values()) assert_allclose(VALUES, h.variances()) assert h.kind == bh.Kind.COUNT assert h.kind == "COUNT" assert len(h.axes) == 1 assert h.axes[0] == h.axes[0] assert_allclose(h.axes[0][0], (0, 1)) assert_allclose(h.axes[0][1], (1, 2)) assert_allclose(h.axes[0][2], (2, 3)) assert_allclose(h.axes[0][3], (3, 4)) assert not h.axes[0].traits.discrete assert not h.axes[0].traits.circular h.fill([1], weight=0) assert_allclose(VALUES, h.counts()) assert_allclose(VALUES, h.values()) assert h.variances() is None
def test_pickle_bool(): a = bh.Histogram(bh.axis.Boolean(), bh.axis.Boolean(metadata={"one": 1})) assert isinstance(a, bh.Histogram) a.fill([True, True, False, False], [True, False, True, True]) a.fill([True, True, True], True) assert a[True, True] == 4 assert a[True, False] == 1 assert a[False, True] == 2 assert a[False, False] == 0 io = BytesIO() pickle.dump(a, io, protocol=-1) io.seek(0) b = pickle.load(io) assert id(a) != id(b) assert a.ndim == b.ndim assert a.axes[0] == b.axes[0] assert a.axes[1] == b.axes[1] assert a.sum() == b.sum() assert repr(a) == repr(b) assert str(a) == str(b) assert a == b assert_array_equal(a.view(), b.view())
def test_fill_2d(flow): h = bh.Histogram( bh.axis.Integer(-1, 2, underflow=flow, overflow=flow), bh.axis.Regular(4, -2, 2, underflow=flow, overflow=flow), ) h.fill(-1, -2) h.fill(-1, -1) h.fill(0, 0) h.fill(0, 1) h.fill(1, 0) h.fill(3, -1) h.fill(0, -3) with pytest.raises(Exception): h.fill(1) with pytest.raises(Exception): h.fill(1, 2, 3) m = [ [1, 1, 0, 0, 0, 0], [0, 0, 1, 1, 0, 1], [0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], ] for get in (lambda h, x, y: h[bh.tag.at(x), bh.tag.at(y)],): # lambda h, x, y: h[x, y]): for i in range(-flow, h.axes[0].size + flow): for j in range(-flow, h.axes[1].size + flow): assert get(h, i, j) == m[i][j]
def test_2D_fill_int(storage): bins = (10, 15) ranges = ((0, 3), (0, 2)) vals = ((0.15, 0.25, 0.25), (0.35, 0.45, 0.45)) hist = bh.Histogram( bh.axis.Regular(bins[0], *ranges[0]), bh.axis.Regular(bins[1], *ranges[1]), storage=storage(), ) assert hist._storage_type == storage hist.fill(*vals) H = np.histogram2d(*vals, bins=bins, range=ranges)[0] assert_array_equal(np.asarray(hist), H) assert_array_equal(hist.view(flow=True)[1:-1, 1:-1], H) assert_array_equal(hist.view(flow=False), H) assert hist.axes[0].size == bins[0] assert hist.axes[0].extent == bins[0] + 2 assert hist.axes[1].size == bins[1] assert hist.axes[1].extent == bins[1] + 2
def test_add_broadcast(): h = bh.Histogram(bh.axis.Regular(10, 0, 1), bh.axis.Regular(20, 0, 1)) h1 = h.copy() h2 = h.copy() h1[...] = 1 assert h1.view().sum() == 10 * 20 assert h1.view(flow=True).sum() == 10 * 20 h2 = h + [[1]] assert h2.sum() == 10 * 20 assert h2.sum(flow=True) == 10 * 20 h3 = h + np.ones((10, 20)) assert h3.sum() == 10 * 20 assert h3.sum(flow=True) == 10 * 20 h4 = h + np.ones((12, 22)) assert h4.view(flow=True).sum() == 12 * 22 h5 = h + np.ones((10, 1)) assert h5.sum(flow=True) == 10 * 20 h5 = h + np.ones((1, 22)) assert h5.sum(flow=True) == 12 * 22
def test_int_cat_hist_pick_several(): h = bh.Histogram(bh.axis.IntCategory([1, 2, 7], __dict__={"xval": 5}), storage=bh.storage.Int64()) h.fill(1, weight=8) h.fill(2, weight=7) h.fill(7, weight=6) assert h.view() == approx(np.array([8, 7, 6])) assert h.sum() == 21 assert h[[0, 2]].values() == approx(np.array([8, 6])) assert h[[2, 0]].values() == approx(np.array([6, 8])) assert h[[1]].values() == approx(np.array([7])) assert h[[bh.loc(1), bh.loc(7)]].values() == approx(np.array([8, 6])) assert h[[bh.loc(7), bh.loc(1)]].values() == approx(np.array([6, 8])) assert h[[bh.loc(2)]].values() == approx(np.array([7])) assert tuple(h[[0, 2]].axes[0]) == (1, 7) assert tuple(h[[2, 0]].axes[0]) == (7, 1) assert tuple(h[[1]].axes[0]) == (2, ) assert h.axes[0].xval == 5 assert h[[0]].axes[0].xval == 5 assert h[[0, 1, 2]].axes[0].xval == 5
def test_obj_3D_rectangular(use_weights): x = da.random.standard_normal(size=(2000, 3), chunks=(400, 3)) if use_weights: weights = da.random.uniform(0.5, 0.75, size=x.shape[0], chunks=x.chunksize[0]) storage = dhb.storage.Weight() else: weights = None storage = dhb.storage.Double() h = dhb.Histogram( dhb.axis.Regular(8, -3.5, 3.5), dhb.axis.Regular(7, -3.3, 3.3), dhb.axis.Regular(9, -3.2, 3.2), storage=storage, ) h.fill(x, weight=weights) h.compute() control = bh.Histogram(*h.axes, storage=h._storage_type()) if use_weights: control.fill(*(x.compute().T), weight=weights.compute()) else: control.fill(*(x.compute().T)) assert np.allclose(h.counts(), control.counts()) if use_weights: assert np.allclose(h.variances(), control.variances())
def test_from_and_to_hist(): h3 = hist.NamedHist( hist.axis.Regular(25, -3.5, 3, name="x", flow=False), hist.axis.Regular(21, -4, 5, name="y", flow=False), storage=hist.storage.Weight(), ) x2 = np.random.randn(1_000) y2 = 0.5 * np.random.randn(1_000) h3.fill(x=x2, y=y2) from zfit._data.binneddatav1 import BinnedData for _ in range(10): # make sure this works many times h1 = BinnedData.from_hist(h3) np.testing.assert_allclose(h1.variances(), h3.variances()) np.testing.assert_allclose(h1.values(), h3.values()) unbinned = h1.to_unbinned() assert unbinned.value().shape[1] == 2 assert unbinned.value().shape[0] == unbinned.weights.shape[0] h3recreated = h1.to_hist() assert h3recreated == h3 bh3 = bh.Histogram(h1) np.testing.assert_allclose(h1.variances(), bh3.variances()) np.testing.assert_allclose(h1.values(), bh3.values())
def to_boost_histogram(self) -> Any: """Convert into a boost-histogram. NOTE: This is a lossy operation. The metadata is not preserved. Returns: Boost histogram containing the data. """ try: import boost_histogram as bh except ImportError: raise RuntimeError( "Unable to import boost histogram. Please install it to export to a boost histogram." ) # It seems to copy by default, so we don't need to do it ourselves. axes = [] for axis in self.axes: # NOTE: We use Variable instead of Regular even if the bin edges are Regular because it allows us to # construct the axes just from the bin edges. axes.append( bh.axis.Variable(axis.bin_edges, underflow=False, overflow=False)) h = bh.Histogram(*axes, storage=bh.storage.Weight()) # Need to shape the array properly so that it will actually be able to assign to the boost histogram. arr = np.zeros(shape=h.view().shape, dtype=h.view().dtype) arr["value"] = self.values arr["variance"] = self.variances h[...] = arr return h
def test_axes_all_at_once(): h = bh.Histogram( bh.axis.Regular(10, 0, 10, metadata=2), bh.axis.Integer(0, 5, metadata="hi"), bh.axis.StrCategory(["HI", "HO"]), ) assert h.axes.bin(1, 2, 0) == ((1.0, 2.0), 2, "HI") assert h.axes.value(0, 0, 0) == (0.0, 0, "HI") assert h.axes.index(2, 3, "HO") == (2, 3, 1) assert h.axes.size == (10, 5, 2) assert h.axes.extent == (12, 7, 3) assert h.axes.metadata == (2, "hi", None) centers = h.axes.centers answers = np.ogrid[0.5:10, 0.5:5, 0.5:2] for i in range(3): np.testing.assert_allclose(centers[i], answers[i]) np.testing.assert_allclose(h.axes[i].centers, answers[i].ravel()) edges = h.axes.edges answers = np.ogrid[0:11, 0:6, 0:3] for i in range(3): np.testing.assert_allclose(edges[i], answers[i]) np.testing.assert_allclose(h.axes[i].edges, answers[i].ravel()) widths = h.axes.widths answers = np.ogrid[1:1:10j, 1:1:5j, 1:1:2j] for i in range(3): np.testing.assert_allclose(widths[i], answers[i]) np.testing.assert_allclose(h.axes[i].widths, answers[i].ravel())
def test_project(): h = bh.Histogram(bh.axis.Integer(0, 2), bh.axis.Integer(1, 4)) h.fill(0, 1) h.fill(0, 2) h.fill(1, 3) h0 = h.project(0) assert h0.ndim == 1 assert h0.axes[0] == bh.axis.Integer(0, 2) assert [h0[i] for i in range(2)] == [2, 1] h1 = h.project(1) assert h1.ndim == 1 assert h1.axes[0] == bh.axis.Integer(1, 4) assert [h1[i] for i in range(3)] == [1, 1, 1] with pytest.raises(ValueError): h.project(*range(10)) with pytest.raises(ValueError): h.project(2, 1) with pytest.raises(ValueError): h.project(9) with pytest.raises(ValueError): h.project(-1)
def test_growing_histogram(): hist = bh.Histogram(bh.axis.Regular(10, 0, 1, growth=True), storage=bh.storage.Int64()) hist.fill(1.45) assert hist.size == 17
def test_reductions(): h = bh.Histogram(bh.axis.Variable([1, 2, 4, 7, 9, 9.5, 10])) widths_1 = functools.reduce(operator.mul, h.axes.widths) widths_2 = np.prod(h.axes.widths, axis=0) assert_array_equal(widths_1, widths_2)
def test_fill_1d(flow): h = bh.Histogram(bh.axis.Regular(3, -1, 2, underflow=flow, overflow=flow)) with pytest.raises(ValueError): h.fill() with pytest.raises(ValueError): h.fill(1, 2) for x in (-10, -1, -1, 0, 1, 1, 1, 10): h.fill(x) assert h.sum() == 6 assert h.sum(flow=True) == 6 + 2 * flow assert h.axes[0].extent == 3 + 2 * flow with pytest.raises(IndexError): h[0, 1] for get in (lambda h, arg: h[arg],): # lambda h, arg: h[arg]): assert get(h, 0) == 2 assert get(h, 1) == 1 assert get(h, 2) == 3 # assert get(h, 0).variance == 2 # assert get(h, 1).variance == 1 # assert get(h, 2).variance == 3 if flow is True: assert get(h, bh.underflow) == 1 assert get(h, bh.overflow) == 1
def test_growing_cats(): h = bh.Histogram(bh.axis.IntCategory([], growth=True), bh.axis.StrCategory([], growth=True)) h.fill([1, 2, 1, 1], ["hi", "ho", "hi", "ho"]) assert h.size == 4
def test_add_2d(flow): h = bh.Histogram( bh.axis.Integer(-1, 2, underflow=flow, overflow=flow), bh.axis.Regular(4, -2, 2, underflow=flow, overflow=flow), ) assert isinstance(h, bh.Histogram) h.fill(-1, -2) h.fill(-1, -1) h.fill(0, 0) h.fill(0, 1) h.fill(1, 0) h.fill(3, -1) h.fill(0, -3) m = [ [1, 1, 0, 0, 0, 0], [0, 0, 1, 1, 0, 1], [0, 0, 1, 0, 0, 0], [0, 1, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0], ] h += h for i in range(-flow, h.axes[0].size + flow): for j in range(-flow, h.axes[1].size + flow): assert h[bh.tag.at(i), bh.tag.at(j)] == 2 * m[i][j]
def test_hist_hist_div(): h1 = bh.Histogram(bh.axis.Boolean()) h2 = bh.Histogram(bh.axis.Boolean()) h1[:] = (8, 6) h2[:] = (2, 3) h3 = h1 / h2 assert h3[False] == 4 assert h3[True] == 2 h1 /= h2 assert h1[False] == 4 assert h1[True] == 2
def test_view_assign_wmean(): h = bh.Histogram(bh.axis.Integer(0, 4), storage=bh.storage.WeightedMean()) w = h.copy().view() h[...] = [[10, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] assert_allclose(h.view().sum_of_weights, [10, 5, 9, 13]) assert_allclose(h.view().sum_of_weights_squared, [2, 6, 10, 14]) assert_allclose(h.view().value, [3, 7, 11, 15]) assert_allclose(h.view().variance, [4, 8, 12, 16]) # Make sure this really was a copy assert w.sum_of_weights[0] != 10 # Assign directly on view w[...] = [[10, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [13, 14, 15, 16]] assert_allclose(w.sum_of_weights, [10, 5, 9, 13]) assert_allclose(w.sum_of_weights_squared, [2, 6, 10, 14]) assert_allclose(w.value, [3, 7, 11, 15]) assert_allclose(w.variance, [4, 8, 12, 16]) # Note: if sum_of_weights <= 1, variance is undefined w[0] = [9, 1, 2, 3] assert w.sum_of_weights[0] == 9 assert w[0].sum_of_weights_squared == 1 assert w.value[0] == 2 assert w[0].variance == 3
def test_variance_setting(cnt, val, var): h = bh.Histogram(bh.axis.Regular(4, 0, 1), storage=bh.storage.Mean()) h[...] = np.stack([cnt, val, var * cnt], axis=-1) assert h.counts() == approx(cnt) assert h.values() == approx(val) assert h.variances() == approx(var) # , abs=1e-3, rel=1e-3)
def test_numpy_conversion_5(): a = bh.Histogram( bh.axis.Integer(0, 3, underflow=False, overflow=False), bh.axis.Integer(0, 2, underflow=False, overflow=False), storage=bh.storage.Unlimited(), ) a.fill(0, 0) for i in range(80): a = a + a # a now holds a multiprecision type a.fill(1, 0) for i in range(2): a.fill(2, 0) for i in range(3): a.fill(0, 1) for i in range(4): a.fill(1, 1) for i in range(5): a.fill(2, 1) a1 = a.view() assert a1.shape == (3, 2) assert a1[0, 0] == float(2 ** 80) assert a1[1, 0] == 1 assert a1[2, 0] == 2 assert a1[0, 1] == 3 assert a1[1, 1] == 4 assert a1[2, 1] == 5
def test_copy_axes(): h = bh.Histogram(bh.axis.Regular(10, 0, 1)) h2 = h.copy() h.axes[0].metadata = 1 assert h2.axes[0].metadata is None
def test_numpy_conversion_4(): a = bh.Histogram( bh.axis.Integer(0, 2, underflow=False, overflow=False), bh.axis.Integer(0, 4, underflow=False, overflow=False), ) a1 = np.asarray(a) assert a1.dtype == np.double assert a1.shape == (2, 4) b = bh.Histogram() b1 = np.asarray(b) assert b1.shape == () assert np.sum(b1) == 0 # Compare sum methods assert b.sum() == np.asarray(b).sum()
def test_numpy_conversion_2(): a = bh.Histogram( bh.axis.Integer(0, 2, underflow=False, overflow=False), bh.axis.Integer(0, 3, underflow=False, overflow=False), bh.axis.Integer(0, 4, underflow=False, overflow=False), ) r = np.zeros((2, 3, 4), dtype=np.int8) for i in range(a.axes[0].extent): for j in range(a.axes[1].extent): for k in range(a.axes[2].extent): for m in range(i + j + k): a.fill(i, j, k) r[i, j, k] = i + j + k d = np.zeros((2, 3, 4), dtype=np.int8) for i in range(a.axes[0].extent): for j in range(a.axes[1].extent): for k in range(a.axes[2].extent): d[i, j, k] = a[i, j, k] assert_array_equal(d, r) c = np.array(a) # a copy v = np.asarray(a) # a view assert_array_equal(c, r) assert_array_equal(v, r)
def test_pickle_1(): a = bh.Histogram( bh.axis.IntCategory([0, 1, 2]), bh.axis.Integer(0, 3, metadata="ia"), bh.axis.Regular(4, 0.0, 4.0, underflow=False, overflow=False), bh.axis.Variable([0.0, 1.0, 2.0]), ) assert isinstance(a, bh.Histogram) for i in range(a.axes[0].extent): a.fill(i, 0, 0, 0, weight=3) for j in range(a.axes[1].extent): a.fill(i, j, 0, 0, weight=10) for k in range(a.axes[2].extent): a.fill(i, j, k, 0, weight=2) for l in range(a.axes[3].extent): a.fill(i, j, k, l, weight=5) io = BytesIO() pickle.dump(a, io, protocol=-1) io.seek(0) b = pickle.load(io) assert id(a) != id(b) assert a.rank == b.rank assert a.axes[0] == b.axes[0] assert a.axes[1] == b.axes[1] assert a.axes[2] == b.axes[2] assert a.axes[3] == b.axes[3] assert a.sum() == b.sum() assert repr(a) == repr(b) assert str(a) == str(b) assert a == b
def test_pickle_0(): a = bh.Histogram( bh.axis.IntCategory([0, 1, 2]), bh.axis.Integer(0, 20), bh.axis.Regular(2, 0.0, 20.0, underflow=False, overflow=False), bh.axis.Variable([0.0, 1.0, 2.0]), bh.axis.Regular(4, 0, 2 * np.pi, circular=True), ) for i in range(a.axes[0].extent): a.fill(i, 0, 0, 0, 0) for j in range(a.axes[1].extent): a.fill(i, j, 0, 0, 0) for k in range(a.axes[2].extent): a.fill(i, j, k, 0, 0) for l in range(a.axes[3].extent): a.fill(i, j, k, l, 0) for m in range(a.axes[4].extent): a.fill(i, j, k, l, m * 0.5 * np.pi) io = pickle.dumps(a, -1) b = pickle.loads(io) assert id(a) != id(b) assert a.rank == b.rank assert a.axes[0] == b.axes[0] assert a.axes[1] == b.axes[1] assert a.axes[2] == b.axes[2] assert a.axes[3] == b.axes[3] assert a.axes[4] == b.axes[4] assert a.sum() == b.sum() assert repr(a) == repr(b) assert str(a) == str(b) assert a == b
def test_out_of_range(): h = bh.Histogram(bh.axis.Regular(3, 0, 1)) h.fill(-1) h.fill(2) assert h[bh.underflow] == 1 assert h[bh.overflow] == 1 with pytest.raises(IndexError): h[4]