Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: HistStack for #169 #244

Merged
merged 20 commits into from
Jul 7, 2021
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
170 changes: 170 additions & 0 deletions notebooks/HistStack.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "0ada0219-170a-418a-a6a5-b241b9b9fe42",
"metadata": {},
"source": [
"# HistStack"
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "6ed3ec2c-9d11-4c69-b7ce-0365079b22ff",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"[StairsArtists(stairs=<matplotlib.patches.StepPatch object at 0x17c000e80>, errorbar=<ErrorbarContainer object of 3 artists>, legend_artist=<ErrorbarContainer object of 3 artists>),\n",
" StairsArtists(stairs=<matplotlib.patches.StepPatch object at 0x17c045af0>, errorbar=<ErrorbarContainer object of 3 artists>, legend_artist=<ErrorbarContainer object of 3 artists>),\n",
" StairsArtists(stairs=<matplotlib.patches.StepPatch object at 0x17c0687f0>, errorbar=<ErrorbarContainer object of 3 artists>, legend_artist=<ErrorbarContainer object of 3 artists>)]"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"needs_background": "light"
},
"output_type": "display_data"
}
],
"source": [
"from hist import Hist, Stack, axis, NamedHist, BaseHist\n",
"import numpy as np\n",
"\n",
"ax = axis.Regular(50, -5, 5, underflow=False, overflow=False)\n",
"\n",
"h1 = Hist(ax).fill(2 * np.random.normal(size=500) + 2 * np.ones((500,)))\n",
"\n",
"h2 = Hist(ax).fill(2 * np.random.normal(size=500) - 2 * np.ones((500,)))\n",
"\n",
"h3 = Hist(ax).fill(np.random.normal(size=600))\n",
"\n",
"Stack(h1, h2, h3).plot()"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "f8d441be-c7aa-4b5e-93a0-8dd2647b6eca",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Stack[\"Regular(50, -5, 5, underflow=False, overflow=False, name='A', label='a [unit]')\", \"Regular(50, -5, 5, underflow=False, overflow=False, name='A', label='a [unit]')\"]\n",
"Stack[\"NamedHist(\\n Regular(50, -5, 5, underflow=False, overflow=False, name='A', label='a [unit]'),\\n Regular(50, -5, 5, underflow=False, overflow=False, name='B', label='b [unit]'),\\n storage=Double())\"]\n"
]
}
],
"source": [
"named_ax1 = axis.Regular(\n",
" 50, -5, 5, name=\"A\", label=\"a [unit]\", underflow=False, overflow=False\n",
")\n",
"named_ax2 = axis.Regular(\n",
" 50, -5, 5, name=\"B\", label=\"b [unit]\", underflow=False, overflow=False\n",
")\n",
"h4 = NamedHist(named_ax1, named_ax2)\n",
"print(repr(Stack(named_ax1, named_ax1))) # not plotable\n",
"print(repr(Stack(h4))) # plotable"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "379e0186-6cc7-4cec-baa1-340a4821bd85",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Stack[\"Regular(50, -5, 5, underflow=False, overflow=False, name='B', label='b [unit]')\", \"Regular(50, -5, 5, underflow=False, overflow=False, name='B', label='b [unit]')\"]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"h4.stack(1, 1) # h4.stack(0, 1) could not work as names are different"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "a5fef029-3d52-46f9-91ed-6ad204ac87c7",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Stack[\"Regular(50, -5, 5, underflow=False, overflow=False, name='B', label='b [unit]')\", \"Regular(50, -5, 5, underflow=False, overflow=False, name='B', label='b [unit]')\"]"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"h4.stack(\"B\", \"B\")"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "20770a1c-4426-4a23-977e-9cc7f1238d24",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Stack[\"Hist(Regular(50, -5, 5, name='C', label='C'), storage=Double())\", \"Hist(Regular(50, -5, 5, name='C', label='C'), storage=Double())\"]"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"h5 = Hist.new.Reg(50, -5, 5, name=\"C\").StrCat([\"one\", \"two\"], name=\"y\").Double()\n",
"Stack(h5[:, \"one\"], h5[:, \"two\"])"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "hist",
"language": "python",
"name": "hist"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
2 changes: 2 additions & 0 deletions src/hist/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from .basehist import BaseHist
from .hist import Hist
from .namedhist import NamedHist
from .stacks import Stack
from .tag import loc, overflow, rebin, sum, underflow

# Convenient access to the version number
Expand All @@ -21,6 +22,7 @@
"Hist",
"BaseHist",
"NamedHist",
"Stack",
"accumulators",
"axis",
"loc",
Expand Down
22 changes: 22 additions & 0 deletions src/hist/basehist.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,3 +461,25 @@ def plot_pie(
import hist.plot

return hist.plot.plot_pie(self, ax=ax, **kwargs)

def stack(self: T, *args: Union[int, str]) -> "hist.stacks.Stack":
"""
Returns a stack from a normal histogram axes.
"""

if len(args) == 0:
raise ValueError("There should be histograms or axes in stack")

if isinstance(args[0], int):
stack_args = [self.axes[i] for i in args]
return hist.stacks.Stack(*stack_args)
elif isinstance(args[0], str):
axes_names = [ax.name for ax in self.axes]
stack_args = []
for a in args:
idx = axes_names.index(a)
stack_args.append(self.axes[idx])

return hist.stacks.Stack(*stack_args)
else:
raise NotImplementedError("Only int or str args are supported")
64 changes: 64 additions & 0 deletions src/hist/stacks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import sys
from typing import Any, Optional

from .axis import AxesMixin
from .basehist import BaseHist

try:
from mplhep.plot import histplot
except ModuleNotFoundError:
print(
"Hist stack requires mplhep to plot, either install hist[plot] or mplhep",
file=sys.stderr,
)
raise


class Stack:
def __init__(
self,
*args: Any,
) -> None:
"""
Initialize Stack for histograms and axes.
"""
if len(args) == 0:
raise ValueError("There should be histograms or axes in stack")

if all([isinstance(a, BaseHist) for a in args]):
axes_type = args[0].axes
for a in args:
if axes_type != a.axes:
raise ValueError("Histograms' axes don't match")

self._stack = [*args]
self._stack_len = len(args)

elif all([isinstance(a, AxesMixin) for a in args]):
axes_type = args[0]
for a in args:
if axes_type != a:
raise ValueError("Axes don't match")

self._stack = [*args]
self._stack_len = len(args)

else:
raise ValueError("There should be histograms or axes in Stack")

def __repr__(self) -> str:
return "Stack" + str([repr(s) for s in self._stack]) + ""

def plot(self, *args: Any, overlay: "Optional[str]" = None, **kwargs: Any) -> "Any":
"""
Plot method for Stack object.
"""

if all([isinstance(a, BaseHist) for a in self._stack]):
if self._stack[0].ndim == 1:
return histplot(self._stack, stack=True)
else:
raise NotImplementedError("Please project to 1D before calling plot")

else:
raise NotImplementedError("Only plot histogram stack are supported")
15 changes: 15 additions & 0 deletions tests/test_reprs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from hist import Stack, axis


def test_1D_empty_repr(named_hist):

h = named_hist.new.Reg(10, -1, 1, name="x", label="y").Double()
Expand Down Expand Up @@ -83,3 +86,15 @@ def test_ND_empty_repr(named_hist):
assert "label='y'" in repr(h)
assert "label='q'" in repr(h)
assert "label='b'" in repr(h)


def test_stack_repr(named_hist):

a1 = axis.Regular(
50, -5, 5, name="A", label="a [unit]", underflow=False, overflow=False
)
a2 = axis.Regular(
50, -5, 5, name="A", label="a [unit]", underflow=False, overflow=False
)
assert "name='A'" in repr(Stack(a1, a2))
assert "label='a [unit]'" in repr(Stack(a1, a2))
Loading