Skip to content

Commit d557913

Browse files
jonas-eschlepre-commit-ci[bot]andrzejnovak
authored
fix: array copy and logic for obtaining variances and values (#488)
* fix: array copy and logic * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * fix: new logic with values and flow * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * tests: expand test to incorporate hists _without_ variance * tests: fix parametrized histplot flow variances test * ci: fix mypy --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: andrzejnovak <[email protected]>
1 parent f3ad6af commit d557913

File tree

4 files changed

+66
-56
lines changed

4 files changed

+66
-56
lines changed

Diff for: src/mplhep/plot.py

+39-32
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
ErrorBarArtists = namedtuple("ErrorBarArtists", "errorbar")
3232
ColormeshArtists = namedtuple("ColormeshArtists", "pcolormesh cbar text")
3333

34-
3534
Hist1DArtists = Union[StairsArtists, ErrorBarArtists]
3635
Hist2DArtists = ColormeshArtists
3736

@@ -188,36 +187,40 @@ def histplot(
188187
plottables = []
189188
flow_bins = final_bins
190189
for i, h in enumerate(hists):
191-
value, variance = h.values().copy(), h.variances()
192-
if variance is not None:
193-
variance = variance.copy()
194-
underflow, overflow = 0, 0
195-
underflowv, overflowv = 0, 0
196-
# One sided flow bins - hist
197-
if hasattr(h, "axes") and hasattr(h.axes[0], "traits"):
198-
if hasattr(h.axes[0].traits, "overflow") and h.axes[0].traits.overflow:
199-
overflow = h.values(flow=True)[-1].copy()
200-
overflowv = h.variances(flow=True)[-1].copy()
201-
if hasattr(h.axes[0].traits, "underflow") and h.axes[0].traits.underflow:
202-
underflow = h.values(flow=True)[0].copy()
203-
underflowv = h.variances(flow=True)[0].copy()
190+
value, variance = np.copy(h.values()), h.variances()
191+
if has_variances := variance is not None:
192+
variance = np.copy(variance)
193+
underflow, overflow = 0.0, 0.0
194+
underflowv, overflowv = 0.0, 0.0
195+
# One sided flow bins - hist (uproot hist does not have the over- or underflow traits)
196+
if (
197+
hasattr(h, "axes")
198+
and (traits := getattr(h.axes[0], "traits", None)) is not None
199+
and hasattr(traits, "underflow")
200+
and hasattr(traits, "overflow")
201+
):
202+
if traits.overflow:
203+
overflow = np.copy(h.values(flow=True))[-1]
204+
if has_variances:
205+
overflowv = np.copy(h.variances(flow=True))[-1]
206+
if traits.underflow:
207+
underflow = np.copy(h.values(flow=True))[0]
208+
if has_variances:
209+
underflowv = np.copy(h.variances(flow=True))[0]
204210
# Both flow bins exist - uproot
205-
if hasattr(h, "values") and "flow" in inspect.getfullargspec(h.values).args:
211+
elif hasattr(h, "values") and "flow" in inspect.getfullargspec(h.values).args:
206212
if len(h.values()) + 2 == len(
207213
h.values(flow=True)
208214
): # easy case, both over/under
209215
underflow, overflow = (
210-
h.values(flow=True)[0].copy(),
211-
h.values(flow=True)[-1].copy(),
212-
)
213-
underflowv, overflowv = (
214-
h.variances(flow=True)[0].copy(),
215-
h.variances(flow=True)[-1].copy(),
216+
np.copy(h.values(flow=True))[0],
217+
np.copy(h.values(flow=True))[-1],
216218
)
217-
# Bins cannot be parsed
218-
else:
219-
underflow, overflow = 0, 0
220-
underflowv, overflowv = 0, 0
219+
if has_variances:
220+
underflowv, overflowv = (
221+
np.copy(h.variances(flow=True))[0],
222+
np.copy(h.variances(flow=True))[-1],
223+
)
221224

222225
# Set plottables
223226
if flow == "none":
@@ -228,23 +231,27 @@ def histplot(
228231
_flow_bin_size = np.max(
229232
[0.05 * (final_bins[-1] - final_bins[0]), np.mean(np.diff(final_bins))]
230233
)
231-
flow_bins = final_bins.copy()
234+
flow_bins = np.copy(final_bins)
232235
if underflow > 0:
233236
flow_bins = np.r_[flow_bins[0] - _flow_bin_size, flow_bins]
234237
value = np.r_[underflow, value]
235-
variance = np.r_[underflowv, variance]
238+
if has_variances:
239+
variance = np.r_[underflowv, variance]
236240
if overflow > 0:
237241
flow_bins = np.r_[flow_bins, flow_bins[-1] + _flow_bin_size]
238242
value = np.r_[value, overflow]
239-
variance = np.r_[variance, overflowv]
243+
if has_variances:
244+
variance = np.r_[variance, overflowv]
240245
plottables.append(Plottable(value, edges=flow_bins, variances=variance))
241246
elif flow == "sum":
242247
if underflow > 0:
243248
value[0] += underflow
244-
variance[0] += underflowv
249+
if has_variances:
250+
variance[0] += underflowv
245251
if overflow > 0:
246252
value[-1] += overflow
247-
variance[-1] += overflowv
253+
if has_variances:
254+
variance[-1] += overflowv
248255
plottables.append(Plottable(value, edges=final_bins, variances=variance))
249256
else:
250257
plottables.append(Plottable(value, edges=final_bins, variances=variance))
@@ -675,7 +682,7 @@ def hist2dplot(
675682

676683
# TODO: use Histogram everywhere
677684

678-
H = h.values().copy()
685+
H = np.copy(h.values())
679686
xbins, xtick_labels = get_plottable_protocol_bins(h.axes[0])
680687
ybins, ytick_labels = get_plottable_protocol_bins(h.axes[1])
681688
# Show under/overflow bins
@@ -715,7 +722,7 @@ def hist2dplot(
715722
H = padded
716723
xbins, ybins = pxbins, pybins
717724
elif flow == "sum":
718-
H = h.values().copy()
725+
H = np.copy(h.values())
719726
# Sum borders
720727
H[0], H[-1] = (
721728
H[0] + h.values(flow=True)[0, 1:-1],
38.2 KB
Loading

Diff for: tests/test_basic.py

+27-24
Original file line numberDiff line numberDiff line change
@@ -142,26 +142,29 @@ def test_histplot_flow():
142142
return fig
143143

144144

145+
@pytest.mark.parametrize("variances", [True, False], ids=["variances", "no_variances"])
145146
@pytest.mark.mpl_image_compare(style="default")
146-
def test_histplot_hist_flow():
147+
def test_histplot_hist_flow(variances):
147148
np.random.seed(0)
148149
entries = np.random.normal(10, 3, 400)
149-
h = hist.new.Reg(20, 5, 15, name="x", flow=True).Weight()
150-
h2 = hist.new.Reg(20, 5, 15, name="x", underflow=True, overflow=False).Weight()
151-
h3 = hist.new.Reg(20, 5, 15, name="x", underflow=False, overflow=True).Weight()
152-
h4 = hist.new.Reg(20, 5, 15, name="x", flow=False).Weight()
150+
hist_constr = [
151+
hist.new.Reg(20, 5, 15, name="x", flow=True),
152+
hist.new.Reg(20, 5, 15, name="x", underflow=True, overflow=False),
153+
hist.new.Reg(20, 5, 15, name="x", underflow=False, overflow=True),
154+
hist.new.Reg(20, 5, 15, name="x", flow=False),
155+
]
156+
if variances:
157+
hists = [h.Weight() for h in hist_constr]
158+
else:
159+
hists = [h.Double() for h in hist_constr]
160+
for h in hists:
161+
h.fill(entries, weight=np.ones_like(entries))
153162

154-
h.fill(entries)
155-
h2.fill(entries)
156-
h3.fill(entries)
157-
h4.fill(entries)
158163
fig, axs = plt.subplots(2, 2, sharey=True, figsize=(10, 10))
159164
axs = axs.flatten()
160165

161-
hep.histplot(h, ax=axs[0], flow="show")
162-
hep.histplot(h2, ax=axs[1], flow="show")
163-
hep.histplot(h3, ax=axs[2], flow="show")
164-
hep.histplot(h4, ax=axs[3], flow="show")
166+
for i, h in enumerate(hists):
167+
hep.histplot(h, ax=axs[i], flow="show", yerr=variances)
165168

166169
axs[0].set_title("Two-side overflow", fontsize=18)
167170
axs[1].set_title("Left-side overflow", fontsize=18)
@@ -187,17 +190,17 @@ def test_histplot_uproot_flow():
187190
h4.fill(entries[(entries > 5) & (entries < 15)])
188191
import uproot
189192

190-
f = uproot.recreate("flow_th1.root")
191-
f["h"] = h
192-
f["h2"] = h2
193-
f["h3"] = h3
194-
f["h4"] = h4
195-
196-
f = uproot.open("flow_th1.root")
197-
h = f["h"]
198-
h2 = f["h2"]
199-
h3 = f["h3"]
200-
h4 = f["h4"]
193+
with uproot.recreate("flow_th1.root") as f:
194+
f["h"] = h
195+
f["h2"] = h2
196+
f["h3"] = h3
197+
f["h4"] = h4
198+
199+
with uproot.open("flow_th1.root") as f:
200+
h = f["h"]
201+
h2 = f["h2"]
202+
h3 = f["h3"]
203+
h4 = f["h4"]
201204

202205
fig, axs = plt.subplots(2, 2, sharey=True, figsize=(10, 10))
203206
axs = axs.flatten()

0 commit comments

Comments
 (0)