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
12 changes: 12 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

## Version 1.2

### Version 1.2.2

#### User changes

* PyPy 3.8 now supported. [#677][]
* The GIL is released a little more often now. [#662][]
* AxesTuple does not allow construction of non-axes. [#680][]

[#662]: https://github.com/scikit-hep/boost-histogram/pull/662
[#677]: https://github.com/scikit-hep/boost-histogram/pull/677
[#680]: https://github.com/scikit-hep/boost-histogram/pull/680

### Version 1.2.1

#### User changes
Expand Down
16 changes: 12 additions & 4 deletions src/boost_histogram/_internal/axestuple.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from functools import partial
from typing import Any, List, Tuple, TypeVar
from typing import Any, Iterable, List, Tuple, TypeVar

import numpy as np

Expand Down Expand Up @@ -45,6 +45,13 @@ class AxesTuple(tuple): # type: ignore[type-arg]
__slots__ = ()
_MGRIDOPTS = {"sparse": True, "indexing": "ij"}

def __init__(self, __iterable: Iterable[Axis]) -> None:
for item in self:
if not isinstance(item, Axis):
raise TypeError(
f"Only an iterable of Axis supported in AxesTuple, got {item}"
)

@property
def size(self) -> Tuple[int, ...]:
return tuple(s.size for s in self)
Expand Down Expand Up @@ -93,14 +100,15 @@ def __getitem__(self, item: Any) -> Any:
result = super().__getitem__(item)
return self.__class__(result) if isinstance(result, tuple) else result

def __getattr__(self, attr: str) -> Any:
return self.__class__(getattr(s, attr) for s in self)
def __getattr__(self, attr: str) -> Tuple[Any, ...]:
return tuple(getattr(s, attr) for s in self)

def __setattr__(self, attr: str, values: Any) -> None:
try:
return super().__setattr__(attr, values)
except AttributeError:
self.__class__(s.__setattr__(attr, v) for s, v in zip_strict(self, values))
for s, v in zip_strict(self, values):
s.__setattr__(attr, v)

value.__doc__ = Axis.value.__doc__
index.__doc__ = Axis.index.__doc__
Expand Down
27 changes: 26 additions & 1 deletion tests/test_axes_object.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import numpy as np
import pytest

import boost_histogram as bh


def test_axes_all_at_once():
@pytest.fixture
def h():
return bh.Histogram(
bh.axis.Regular(10, 0, 10, metadata=2),
bh.axis.Integer(0, 5, metadata="hi"),
bh.axis.StrCategory(["HI", "HO"]),
)


def test_axes_basics(h):
h = bh.Histogram(
bh.axis.Regular(10, 0, 10, metadata=2),
bh.axis.Integer(0, 5, metadata="hi"),
Expand All @@ -22,6 +32,8 @@ def test_axes_all_at_once():

assert h.axes.metadata == (None, 3, "bye")


def test_axes_centers(h):
centers = h.axes.centers
answers = np.ogrid[0.5:10, 0.5:5, 0.5:2]
full_answers = np.mgrid[0.5:10, 0.5:5, 0.5:2]
Expand All @@ -33,6 +45,8 @@ def test_axes_all_at_once():
np.testing.assert_allclose(centers.flatten()[i], answers[i].flatten())
np.testing.assert_allclose(h.axes[i].centers, answers[i].ravel())


def test_axes_edges(h):
edges = h.axes.edges
answers = np.ogrid[0:11, 0:6, 0:3]
full_answers = np.mgrid[0:11, 0:6, 0:3]
Expand All @@ -44,6 +58,8 @@ def test_axes_all_at_once():
np.testing.assert_allclose(edges.ravel()[i], answers[i].ravel())
np.testing.assert_allclose(h.axes[i].edges, answers[i].ravel())


def test_axes_widths(h):
widths = h.axes.widths
answers = np.ogrid[1:1:10j, 1:1:5j, 1:1:2j]
full_answers = np.mgrid[1:1:10j, 1:1:5j, 1:1:2j]
Expand All @@ -54,3 +70,12 @@ def test_axes_all_at_once():
np.testing.assert_allclose(widths.T[i], answers[i].T)
np.testing.assert_allclose(widths.ravel()[i], answers[i].ravel())
np.testing.assert_allclose(h.axes[i].widths, answers[i].ravel())


def test_axis_misconstuct():
inp = [bh.axis.Regular(12, 0, 1)]
ok = bh.axis.AxesTuple(inp)
assert ok[0] == inp[0]

with pytest.raises(TypeError):
bh.axis.AxesTuple(inp[0])