Skip to content

Commit 7398693

Browse files
committed
feat: support all other axes types
1 parent e7e3f5c commit 7398693

File tree

2 files changed

+51
-12
lines changed

2 files changed

+51
-12
lines changed

docs/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,13 @@ Pressing forward to 1.0.
1010
#### User changes
1111

1212
* You can now set all complex storages, either on a Histogram or a View with an (N+1)D array [#475][]
13+
* Classes provide a `__dict__` attribute that can be set and deleted. [#477][]
1314

1415
#### Bug fixes
1516

1617
* Fixed issue if final bin of Variable histogram was infinite by updating to Boost 1.75 [#470][]
1718
* NumPy arrays can be used for weights in `bh.numpy` [#472][]
19+
* Vectorization for WeightedMean accumulators was broken [#475][]
1820

1921
#### Developer changes
2022

@@ -24,6 +26,7 @@ Pressing forward to 1.0.
2426
[#470]: https://github.com/scikit-hep/boost-histogram/pull/470
2527
[#472]: https://github.com/scikit-hep/boost-histogram/pull/472
2628
[#475]: https://github.com/scikit-hep/boost-histogram/pull/475
29+
[#477]: https://github.com/scikit-hep/boost-histogram/pull/477
2730

2831

2932
## Version 0.11

src/boost_histogram/_internal/axis.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,26 @@
1111

1212
import copy
1313

14-
from typing import Dict, Any, TYPE_CHECKING
14+
from typing import Dict, Any, TYPE_CHECKING, Optional
1515

1616
del absolute_import, division, print_function
1717

1818

19+
def _process_metadata_dict(metadata, __dict__):
20+
# type: (Optional[Any], Optional[Dict[str, Any]]) -> Dict[str, Any]
21+
"""
22+
Provide standardized handling for keywords related to metadata.
23+
"""
24+
if __dict__ is None:
25+
__dict__ = {}
26+
27+
if "metadata" in __dict__ and metadata is not None:
28+
raise KeyError("Cannot provide metadata by keyword and in __dict__")
29+
30+
__dict__["metadata"] = metadata
31+
return __dict__
32+
33+
1934
def _isstr(value):
2035
"""
2136
Check to see if this is a stringlike or a (nested) iterable of stringlikes
@@ -54,6 +69,7 @@ def __copy__(self):
5469
other._ax = copy.copy(self._ax)
5570
return other
5671

72+
# Required for Python 2 + __dict__
5773
def __setstate__(self, state):
5874
self._ax = state["_ax"]
5975

@@ -293,12 +309,7 @@ def __init__(self, bins, start, stop, **kwargs):
293309
underflow=True, overflow=True, growth=False, circular=False
294310
)
295311

296-
if __dict__ is None:
297-
__dict__ = {}
298-
299-
if "metadata" in __dict__ and metadata is not None:
300-
raise KeyError("Cannot provide metadata by keyword and in __dict__")
301-
__dict__["metadata"] = metadata
312+
__dict__ = _process_metadata_dict(metadata, __dict__)
302313

303314
if transform is not None:
304315
if options != {"underflow", "overflow"}:
@@ -372,7 +383,7 @@ class Variable(Axis):
372383
__slots__ = ()
373384

374385
@inject_signature(
375-
"self, edges, *, metadata=None, underflow=True, overflow=True, growth=False"
386+
"self, edges, *, metadata=None, underflow=True, overflow=True, growth=False, __dict__=None"
376387
)
377388
def __init__(self, edges, **kwargs):
378389
"""
@@ -394,13 +405,18 @@ def __init__(self, edges, **kwargs):
394405
growth : bool = False
395406
Allow the axis to grow if a value is encountered out of range.
396407
Be careful, the axis will grow as large as needed.
408+
__dict__: Optional[Dict[str, Any]] = None
409+
The full metadata dictionary
397410
"""
398411
with KWArgs(kwargs) as k:
399412
metadata = k.optional("metadata")
413+
__dict__ = k.optional("__dict__")
400414
options = k.options(
401415
underflow=True, overflow=True, circular=False, growth=False
402416
)
403417

418+
__dict__ = _process_metadata_dict(metadata, __dict__)
419+
404420
if options == {"growth", "underflow", "overflow"}:
405421
self._ax = ca.variable_uoflow_growth(edges)
406422
elif options == {"underflow", "overflow"}:
@@ -447,7 +463,7 @@ class Integer(Axis):
447463
__slots__ = ()
448464

449465
@inject_signature(
450-
"self, start, stop, *, metadata=None, underflow=True, overflow=True, growth=False"
466+
"self, start, stop, *, metadata=None, underflow=True, overflow=True, growth=False, __dict__=None"
451467
)
452468
def __init__(self, start, stop, **kwargs):
453469
"""
@@ -470,13 +486,18 @@ def __init__(self, start, stop, **kwargs):
470486
growth : bool = False
471487
Allow the axis to grow if a value is encountered out of range.
472488
Be careful, the axis will grow as large as needed.
489+
__dict__: Optional[Dict[str, Any]] = None
490+
The full metadata dictionary
473491
"""
474492
with KWArgs(kwargs) as k:
475493
metadata = k.optional("metadata")
494+
__dict__ = k.optional("__dict__")
476495
options = k.options(
477496
underflow=True, overflow=True, circular=False, growth=False
478497
)
479498

499+
__dict__ = _process_metadata_dict(metadata, __dict__)
500+
480501
# underflow and overflow settings are ignored, integers are always
481502
# finite and thus cannot end up in a flow bin when growth is on
482503
if "growth" in options and "circular" not in options:
@@ -528,7 +549,7 @@ def _repr_kwargs(self):
528549
@set_module("boost_histogram.axis")
529550
@register({ca.category_str_growth, ca.category_str})
530551
class StrCategory(BaseCategory):
531-
@inject_signature("self, categories, *, metadata=None, growth=False")
552+
@inject_signature("self, categories, *, metadata=None, growth=False, __dict__=None")
532553
def __init__(self, categories, **kwargs):
533554
"""
534555
Make a category axis with strings; items will
@@ -545,11 +566,16 @@ def __init__(self, categories, **kwargs):
545566
growth : bool = False
546567
Allow the axis to grow if a value is encountered out of range.
547568
Be careful, the axis will grow as large as needed.
569+
__dict__: Optional[Dict[str, Any]] = None
570+
The full metadata dictionary
548571
"""
549572
with KWArgs(kwargs) as k:
550573
metadata = k.optional("metadata")
574+
__dict__ = k.optional("__dict__")
551575
options = k.options(growth=False)
552576

577+
__dict__ = _process_metadata_dict(metadata, __dict__)
578+
553579
# henryiii: We currently expand "abc" to "a", "b", "c" - some
554580
# Python interfaces protect against that
555581

@@ -586,7 +612,7 @@ def _repr_args(self):
586612
@set_module("boost_histogram.axis")
587613
@register({ca.category_int, ca.category_int_growth})
588614
class IntCategory(BaseCategory):
589-
@inject_signature("self, categories, *, metadata=None, growth=False")
615+
@inject_signature("self, categories, *, metadata=None, growth=False, __dict__=None")
590616
def __init__(self, categories, **kwargs):
591617
"""
592618
Make a category axis with ints; items will
@@ -603,11 +629,16 @@ def __init__(self, categories, **kwargs):
603629
growth : bool = False
604630
Allow the axis to grow if a value is encountered out of range.
605631
Be careful, the axis will grow as large as needed.
632+
__dict__: Optional[Dict[str, Any]] = None
633+
The full metadata dictionary
606634
"""
607635
with KWArgs(kwargs) as k:
608636
metadata = k.optional("metadata")
637+
__dict__ = k.optional("__dict__")
609638
options = k.options(growth=False)
610639

640+
__dict__ = _process_metadata_dict(metadata, __dict__)
641+
611642
if options == {"growth"}:
612643
self._ax = ca.category_int_growth(tuple(categories))
613644
elif options == set():
@@ -630,7 +661,7 @@ def _repr_args(self):
630661
class Boolean(Axis):
631662
__slots__ = ()
632663

633-
@inject_signature("self, *, metadata=None")
664+
@inject_signature("self, *, metadata=None, __dict__=None")
634665
def __init__(self, **kwargs):
635666
"""
636667
Make an axis for boolean values.
@@ -639,9 +670,14 @@ def __init__(self, **kwargs):
639670
----------
640671
metadata : object
641672
Any Python object to attach to the axis, like a label.
673+
__dict__: Optional[Dict[str, Any]] = None
674+
The full metadata dictionary
642675
"""
643676
with KWArgs(kwargs) as k:
644677
metadata = k.optional("metadata")
678+
__dict__ = k.optional("__dict__")
679+
680+
__dict__ = _process_metadata_dict(metadata, __dict__)
645681

646682
self._ax = ca.boolean()
647683
self.metadata = metadata

0 commit comments

Comments
 (0)