Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 21 additions & 6 deletions src/boost_histogram/_internal/hist.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,18 +552,25 @@ def _compute_commonindex(self, index):

return indexes

@inject_signature("self, flow=False, *, dd=False")
@inject_signature("self, flow=False, *, dd=False, view=False")
def to_numpy(self, flow=False, **kwargs):
"""
Convert to a Numpy style tuple of return arrays.
Convert to a Numpy style tuple of return arrays. Edges are converted to
match NumPy standards, with upper edge inclusive, unlike
boost-histogram, where upper edge is exclusive.

Parameters
----------

flow : bool = False
Include the flow bins.
dd : bool = False
Use the histogramdd return syntax, where the edges are in a tuple
Use the histogramdd return syntax, where the edges are in a tuple.
Otherwise, this is the histogram/histogram2d return style.
view : bool = False
The behavior for the return value. By default, this will return
array of the values only regardless of the storage (which is all
NumPy's histogram function can do). view=True will return the
boost-histogram view of the storage.

Return
------
Expand All @@ -575,13 +582,21 @@ def to_numpy(self, flow=False, **kwargs):

with KWArgs(kwargs) as kw:
dd = kw.optional("dd", False)
view = kw.optional("view", False)

# Python 3+ would be simpler
return_tuple = self._hist.to_numpy(flow)
hist = return_tuple[0]

if view:
hist = self.view(flow=flow)
else:
hist = self.values(flow=flow)

if dd:
return return_tuple[0], return_tuple[1:]
return hist, return_tuple[1:]
else:
return return_tuple
return (hist,) + return_tuple[1:]

@inject_signature("self, *, deep=True")
def copy(self, **kwargs):
Expand Down
5 changes: 4 additions & 1 deletion src/boost_histogram/numpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ def histogramdd(
density = hist.view() / hist.sum() / areas
return (density, hist.to_numpy()[1:])

return hist if bh_cls is not None else hist.to_numpy(dd=True)
# Note: this is view=True since users have to ask explicitly for special
# storages, so view=False would throw away part of what they are asking
# for. Users can use a histogram return type if they need view=False.
return hist if bh_cls is not None else hist.to_numpy(view=True, dd=True)


@_inject_signature(
Expand Down
25 changes: 25 additions & 0 deletions tests/test_internal_histogram.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,31 @@ def test_numpy_dd():
assert_array_equal(x1, x2)
assert_array_equal(y1, y2)

def test_numpy_weights():
h = bh.Histogram(
bh.axis.Regular(10, 0, 1), bh.axis.Regular(5, 0, 1), storage=bh.storage.Weight()
)

for i in range(10):
for j in range(5):
x, y = h.axes[0].centers[i], h.axes[1].centers[j]
v = i + j * 10 + 1
h.fill([x] * v, [y] * v)

h2, x2, y2 = h.to_numpy(view=False)
h1, (x1, y1) = h.to_numpy(dd=True, view=False)

assert_array_equal(h1, h2)
assert_array_equal(x1, x2)
assert_array_equal(y1, y2)

h1, (x1, y1) = h.to_numpy(dd=True, view=False)
h2, x2, y2 = h.to_numpy(view=True)

assert_array_equal(h1, h2.value)
assert_array_equal(x1, x2)
assert_array_equal(y1, y2)


def test_numpy_flow():
h = bh.Histogram(
Expand Down