using FHist, CairoMakie

Let's generate three dummy histograms sampled from three different distributions:

1. unit Gaussian with 1000 points

2. unit Gaussian with 10000 points

3. unit Gaussians with 1000 points and a mean of 0.5

begin
h1 = Hist1D(randn(10^3); binedges = -2:0.3:2)
h2 = Hist1D(randn(10^4); binedges = -2:0.3:2)
h3 = Hist1D(randn(10^3) .+ 0.5; binedges = -2:0.3:2)
end
• edges: [-2.0, -1.7, -1.4, -1.1, -0.8, -0.5, -0.2, 0.1, 0.4, 0.7, 1.0, 1.3, 1.6, 1.9]
• bin counts: [11.0, 18.0, 23.0, 41.0, 66.0, 71.0, 116.0, 118.0, 99.0, 121.0, 91.0, 73.0, 63.0]
• maximum count: 121.0
• total count: 911.0

To plot a single histogram, you can do any of the following:

begin
fig = Figure()
p1, ax1= plot(fig[1, 1],h1; label = "plot(h1)")
p2, ax2 = stephist(fig[1, 2], h1, label = "stairs(h1)")
p3, ax3 = hist(fig[2, 1], h1, label = "hist(h1)")
p4, ax4 = errorbars(fig[2, 2], h1, color=:black, whiskerwidth=6, label = "errorbars(h1)")
axislegend.([p1, p2, p3, p4])
fig
end
begin
h1_log = Hist1D(rand(10^5); binedges = [0.001, 0.01, 0.1, 1])
ax_log = plot(h1_log; axis=(;xscale=log10, yscale=log10), label = "log-log scale")
xlims!(0.0001, nothing)
ylims!(1, nothing)
axislegend()
ax_log
end

When you're studying a single histogram, it's hepful to have statbox (CERN ROOT enjoyer?)

We provide a statbox!() function to add such box:

begin
f_s = stephist(h1)
statbox!(f_s, h1)
f_s
end

statbox also works for 2D histogram as one'd expect:

begin
fig2d = Figure()
h2d = Hist2D((randn(10000), randn(10000)))
_, _heatmap = plot(fig2d[1,2], h2d)
statbox!(fig2d, h2d; position=(1,1))
Colorbar(fig2d[1,3], _heatmap)
fig2d
end
begin
even_edges = 0:0.1:1
uneven_edges = [0, 0.2, 0.5, 1]
data = (randn(10000), randn(10000))
h2d_even =   Hist2D(data; binedges = (even_edges, even_edges))
h2d_uneven = Hist2D(data; binedges = (uneven_edges, even_edges))

f2_uneven = Figure()
plot(f2_uneven[2,1], h2d_even; axis=(title="even x-binning", ))
plot(f2_uneven[1,1], h2d_uneven; axis=(title="uneven x-binning", ))
f2_uneven
end

You can freely combine these by using the bang ! version to plot things on top of each other, for example this is some plot you might see:

begin
pos_h2 = restrict(h2, 0, Inf)
hist(pos_h2;
label = "fake bkg",
axis=(
limits=(nothing, nothing, 0.1, nothing),
yminorticks=IntervalsBetween(5),
yminorticksvisible = true,
yscale=log10
)
)

errorbars!(pos_h2; whiskerwidth=7)
stephist!(h3; color=:red, label = "fake sig")
axislegend()
current_figure()
end

But it's also pretty common to have multiple background components (processes), in such case, we often want a stacked histogram with error bar representing the sum of each component added up correctly.

We also have a recipe for that:

with_theme(ATLASTHEME) do
f, a, p = stackedhist([h2, h2, h1]; )
labels = ["proc1", "blah", "third one"]
elements = [PolyElement(polycolor = p.attributes.color[][i]) for i in 1:length(labels)]
title = "Legend title"
Legend(f[1,2], elements, labels, title)
f
end

Notice the with_theme(ATLASTHEME), you can apply a bunch of appearance tweaks for the entire plot.

Finally, we have a recipe for ratio plot which is argubaly useful for the bottom pannel in many plots:

begin
f_ratio, a, p = stephist(h1; label="h1")
errorbars!(a, h1)
stephist!(a, h3; label="h3")
errorbars!(a, h3)

axislegend()
ratioax = Axis(f_ratio[2, 1], aspect = 5.5, xlabel = "my x-axis", ylabel="h1 / h3")
hidexdecorations!(a)
ratiohist!(ratioax, h1/h3; color=:black, errors=true)
rowsize!(f_ratio.layout, 1, Aspect(1, 0.5))
f_ratio
end

## Clamping/clipping bincounts and errorbars

-clamp_bincounts = false (default)clamp_bincounts = true
clamp_errors = falseDon't do this
clamp_errors = true (default)
Note

clamp_bincounts only works with stairs() and barplot() directly (does not work with stephist(), hist() for the moment. See Makie upstream github issue: https://github.com/MakieOrg/Makie.jl/issues/3904

let h = Hist1D(;binedges=0:2, bincounts=[-0.1, 0.1], sumw2=[0.1, 0.1])
fig = Figure()

scatter(fig[1,1], h;); errorbars!(h; clamp_errors=false);
scatter(fig[2,1], h;); errorbars!(h; clamp_errors=true);
scatter(fig[2,2], h; clamp_bincounts=true); errorbars!(h; clamp_bincounts=true, clamp_errors=true);

fig
end
let h = Hist1D(;binedges=0:2, bincounts=[-0.1, 0.1], sumw2=[0.1, 0.1])
fig = Figure()

stairs(fig[1,1], h;); errorbars!(h; clamp_errors=false);
stairs(fig[2,1], h;); errorbars!(h; clamp_errors=true);
stairs(fig[2,2], h; clamp_bincounts=true); errorbars!(h; clamp_bincounts=true, clamp_errors=true);

fig
end

# Shading/Hatching errorbar band

let
f, a, p = stackedhist([h1, h1 ]; error_color=(:black, 0.5))
labels = ["proc1", "blah"]
elements = [PolyElement(polycolor = p.attributes.color[][i]) for i in 1:length(labels)]
title = "Legend title"
Legend(f[1,2], elements, labels, title)
f
end
let
f, a, p = stackedhist([h1, h1]; error_color=Pattern('/'))
f
end