Skip to content

Commit 98e2bfe

Browse files
authored
feat: to_numpy matching uproot, extra mode (#498)
* feat: to_numpy matching uproot, with mode * refactor: bool view instead of mode
1 parent a1974b9 commit 98e2bfe

File tree

3 files changed

+50
-7
lines changed

3 files changed

+50
-7
lines changed

src/boost_histogram/_internal/hist.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -552,18 +552,25 @@ def _compute_commonindex(self, index):
552552

553553
return indexes
554554

555-
@inject_signature("self, flow=False, *, dd=False")
555+
@inject_signature("self, flow=False, *, dd=False, view=False")
556556
def to_numpy(self, flow=False, **kwargs):
557557
"""
558-
Convert to a Numpy style tuple of return arrays.
558+
Convert to a Numpy style tuple of return arrays. Edges are converted to
559+
match NumPy standards, with upper edge inclusive, unlike
560+
boost-histogram, where upper edge is exclusive.
559561
560562
Parameters
561563
----------
562-
563564
flow : bool = False
564565
Include the flow bins.
565566
dd : bool = False
566-
Use the histogramdd return syntax, where the edges are in a tuple
567+
Use the histogramdd return syntax, where the edges are in a tuple.
568+
Otherwise, this is the histogram/histogram2d return style.
569+
view : bool = False
570+
The behavior for the return value. By default, this will return
571+
array of the values only regardless of the storage (which is all
572+
NumPy's histogram function can do). view=True will return the
573+
boost-histogram view of the storage.
567574
568575
Return
569576
------
@@ -575,13 +582,21 @@ def to_numpy(self, flow=False, **kwargs):
575582

576583
with KWArgs(kwargs) as kw:
577584
dd = kw.optional("dd", False)
585+
view = kw.optional("view", False)
578586

587+
# Python 3+ would be simpler
579588
return_tuple = self._hist.to_numpy(flow)
589+
hist = return_tuple[0]
590+
591+
if view:
592+
hist = self.view(flow=flow)
593+
else:
594+
hist = self.values(flow=flow)
580595

581596
if dd:
582-
return return_tuple[0], return_tuple[1:]
597+
return hist, return_tuple[1:]
583598
else:
584-
return return_tuple
599+
return (hist,) + return_tuple[1:]
585600

586601
@inject_signature("self, *, deep=True")
587602
def copy(self, **kwargs):

src/boost_histogram/numpy.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,10 @@ def histogramdd(
7979
density = hist.view() / hist.sum() / areas
8080
return (density, hist.to_numpy()[1:])
8181

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

8487

8588
@_inject_signature(

tests/test_internal_histogram.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,31 @@ def test_numpy_dd():
135135
assert_array_equal(x1, x2)
136136
assert_array_equal(y1, y2)
137137

138+
def test_numpy_weights():
139+
h = bh.Histogram(
140+
bh.axis.Regular(10, 0, 1), bh.axis.Regular(5, 0, 1), storage=bh.storage.Weight()
141+
)
142+
143+
for i in range(10):
144+
for j in range(5):
145+
x, y = h.axes[0].centers[i], h.axes[1].centers[j]
146+
v = i + j * 10 + 1
147+
h.fill([x] * v, [y] * v)
148+
149+
h2, x2, y2 = h.to_numpy(view=False)
150+
h1, (x1, y1) = h.to_numpy(dd=True, view=False)
151+
152+
assert_array_equal(h1, h2)
153+
assert_array_equal(x1, x2)
154+
assert_array_equal(y1, y2)
155+
156+
h1, (x1, y1) = h.to_numpy(dd=True, view=False)
157+
h2, x2, y2 = h.to_numpy(view=True)
158+
159+
assert_array_equal(h1, h2.value)
160+
assert_array_equal(x1, x2)
161+
assert_array_equal(y1, y2)
162+
138163

139164
def test_numpy_flow():
140165
h = bh.Histogram(

0 commit comments

Comments
 (0)