Skip to content

Commit 3af719f

Browse files
committed
fix: categorical axes need special flow handling (#564)
1 parent b6d5f55 commit 3af719f

File tree

4 files changed

+42
-5
lines changed

4 files changed

+42
-5
lines changed

docs/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
## UPCOMING
44

55
* Fix scaling a weighted storage [#559][]
6+
* Fix partial summation over a Categorical axis [#564][]
67
* Support running type checking from Python < 3.8 [#542][]
78

89
[#542]: https://github.com/scikit-hep/boost-histogram/pull/542
910
[#559]: https://github.com/scikit-hep/boost-histogram/pull/559
11+
[#564]: https://github.com/scikit-hep/boost-histogram/pull/564
1012

1113

1214
## Version 0.13

src/boost_histogram/_internal/axis.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,23 @@ def _process_loc(self, start, stop):
136136
Compute start and stop into actual start and stop values in Boost.Histogram.
137137
None -> -1 or 0 for start, -> len or len+1 for stop. If start or stop are
138138
callable, then call them with the axes.
139+
140+
For a non-ordered axes, flow is all or nothing, so this will ensure overflow
141+
is turned off if underflow is not None.
139142
"""
140143

141144
def _process_internal(item, default):
142145
return default if item is None else item(self) if callable(item) else item
143146

144-
begin = _process_internal(start, -1 if self._ax.traits_underflow else 0)
145-
end = _process_internal(
146-
stop, len(self) + (1 if self._ax.traits_overflow else 0)
147-
)
147+
underflow = -1 if self._ax.traits_underflow else 0
148+
overflow = 1 if self._ax.traits_overflow else 0
149+
150+
# Non-ordered axes only use flow if integrating from None to None
151+
if not self._ax.traits_ordered and not (start is None and stop is None):
152+
overflow = 0
153+
154+
begin = _process_internal(start, underflow)
155+
end = _process_internal(stop, len(self) + overflow)
148156

149157
return begin, end
150158

src/register_algorithm.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ void register_algorithms(py::module& algorithm) {
3131
self.begin.index,
3232
self.end.index,
3333
merge,
34-
self.crop);
34+
self.crop ? "slice_mode.crop" : "slice_mode.shrink");
3535
} else {
3636
return py::
3737
str("reduce_command(shrink{0}({1}, lower={2}, upper={3}{4}))")

tests/test_histogram_indexing.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,3 +378,30 @@ def test_axes_tuple_Nd():
378378

379379
assert b1.ndim == 3
380380
assert a1.ndim == 2
381+
382+
383+
# issue 556
384+
def test_single_flow_bin():
385+
# Flow is removed for category axes unless full sum is used
386+
h = bh.Histogram(bh.axis.IntCategory([0, 1, 2]))
387+
h.view(True)[:] = 1
388+
389+
assert h[::sum] == 4
390+
assert h[0::sum] == 3
391+
assert h[1::sum] == 2
392+
assert h[2::sum] == 1
393+
with pytest.raises(ValueError):
394+
h[3::sum]
395+
396+
assert h[1:2][sum] == 4
397+
398+
h = bh.Histogram(bh.axis.Integer(0, 3))
399+
h.view(True)[:] = 1
400+
401+
assert h[::sum] == 5
402+
assert h[0::sum] == 4
403+
assert h[1::sum] == 3
404+
assert h[2::sum] == 2
405+
assert h[3::sum] == 1
406+
407+
assert h[1:2][sum] == 5

0 commit comments

Comments
 (0)