Skip to content

Commit

Permalink
Main API change for v0.11 🎂 (#95)
Browse files Browse the repository at this point in the history
* Main API change for v0.11

* fix append!

* kill second parameter in Hists types

* make Makie plotting recipe more robust

* Update makie_plotting.jl

* update tagbot
  • Loading branch information
Moelf authored Mar 23, 2024
1 parent 5e12b17 commit ced8d83
Show file tree
Hide file tree
Showing 23 changed files with 783 additions and 792 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/TagBot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ on:
types:
- created
workflow_dispatch:
inputs:
lookback:
default: 5
permissions:
contents: write
jobs:
TagBot:
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
Expand Down
12 changes: 8 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ jobs:
fail-fast: false
matrix:
version:
- '1.6'
- '1.7' # Leave this line unchanged. '1' will automatically expand to the latest stable 1.x release of Julia.
- '1.7'
- '1.8'
- '1.9'
- '1'
os:
- ubuntu-latest
Expand Down Expand Up @@ -44,9 +45,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@v1
with:
version: "~1.10.0-rc3"
- uses: julia-actions/cache@v1
- uses: julia-actions/julia-buildpkg@latest
- uses: julia-actions/julia-docdeploy@latest
- uses: julia-actions/julia-buildpkg@v1
- uses: julia-actions/julia-docdeploy@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
4 changes: 2 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "FHist"
uuid = "68837c9b-b678-4cd5-9925-8a54edc8f695"
authors = ["Moelf <proton[at]jling.dev>", "Nick Amin <amin.nj[at]gmail.com>"]
version = "0.10.9"
version = "0.11"

[deps]
BayesHistogram = "000d9b38-65fe-4c81-bdb9-69f01f102479"
Expand Down Expand Up @@ -35,7 +35,7 @@ RecipesBase = "^1"
Requires = "^1.3"
Statistics = "1"
StatsBase = "^0.33, 0.34"
julia = "1.6"
julia = "^1.7"

[extras]
HDF5 = "f67ccb44-e63f-5c2f-98bd-6dc0ccc4ba2f"
Expand Down
29 changes: 14 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
Fast, error-aware, and thread-safe 1D/2D/3D histograms that are also compatible with `StatsBase.Histogram`

## Changelog
- 0.11
- Breaking change to the main constructor API, now the API is sanely divided into "constructor for
empty histogram" and "make histogram given data". See documentation.
- 0.10
- due to huge latency issue, UnicodePlots.jl (for text based terminal display) has been dropped.

Expand All @@ -16,12 +19,12 @@ julia> using FHist

julia> a = randn(1000);

julia> h1 = Hist1D(a, -4:1.0:4)
julia> h1 = Hist1D(a; binedges = -4:1.0:4)
edges: -4.0:1.0:4.0
bin counts: [0, 23, 123, 377, 320, 134, 21, 2]
total count: 1000

julia> h2 = Hist1D(Int; bins=-4.0:1.0:4.0);
julia> h2 = Hist1D(; counttype = Int, binedges = -4.0:1.0:4.0);

julia> push!.(h2, a);

Expand All @@ -36,35 +39,31 @@ true
Additionally, one can specify `overflow=true` when creating a histogram to clamp out-of-bounds values into
the edge bins.
```julia
julia> Hist1D(rand(1000),0:0.2:0.9; overflow=true)
julia> Hist1D(rand(1000); binedges = 0:0.2:0.9, overflow=true)
edges: 0.0:0.2:0.8
bin counts: [218, 183, 198, 401]
total count: 1000
```

## Speed

Single-threaded filling happens at almost 400 MHz
Single-threaded filling happens at 400 MHz
```julia
julia> a = randn(10^6);

julia> @benchmark Hist1D(a, -3:0.01:3)
Range (min max): 2.591 ms 4.746 ms ┊ GC (min max): 0.00% 0.00%
Time (median): 2.802 ms ┊ GC (median): 0.00%
Time (mean ± σ): 2.864 ms ± 195.931 μs ┊ GC (mean ± σ): 0.00% ± 0.00%
julia> @benchmark Hist1D(a; binedges = -3:0.01:3)
BenchmarkTools.Trial: 2578 samples with 1 evaluation.
Range (min max): 1.871 ms 3.360 ms ┊ GC (min max): 0.00% 0.00%
```

## Features

### 1D

```julia
julia> using FHist, Statistics, Random
julia> using FHist, Statistics

julia> Random.seed!(42)
MersenneTwister(42)

julia> h1 = Hist1D(randn(10^4).+2, -5:0.5:5);
julia> h1 = Hist1D(randn(10^4).+2; binedges = -5:0.5:5);

julia> h1 = (h1 + h1*2)
edges: -5.0:0.5:5.0
Expand Down Expand Up @@ -107,7 +106,7 @@ julia> h1 |> normalize |> integral
### 2D

```julia
julia> h2 = Hist2D((randn(10^4),randn(10^4)), (-5:5,-5:5))
julia> h2 = Hist2D((randn(10^4),randn(10^4)); binedges = (-5:5,-5:5))

edges: (-5:5, -5:5)
bin counts: [0 0 0 0; 0 0 0 0; ; 0 0 0 0; 0 0 0 0]
Expand Down Expand Up @@ -137,7 +136,7 @@ total count: 10000
### 3D

```julia
julia> h3 = Hist3D((randn(10^4),randn(10^4),randn(10^4)), (-5:5,-5:5,-5:5))
julia> h3 = Hist3D((randn(10^4),randn(10^4),randn(10^4)); binedges = (-5:5,-5:5,-5:5))
Hist3D{Int64}, edges=(-5:5, -5:5, -5:5), integral=10000

julia> h3 |> project(:x) |> project(:x) |> std
Expand Down
8 changes: 6 additions & 2 deletions docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,14 @@ makedocs(;
),
pages=[
"Introduction" => "index.md",
"APIs" => "api.md",
"User Guide" => Any[
"Creating Histogram" => "start.md",
"Using Histogram" => "usage.md",
],
"APIs Reference" => "api.md",
"Writing to `.root`" => "writingtoroot.md",
"Writing to `HDF5`" => "writingtohdf5.md",
"Tutorials" => T,
"Plotting Tutorials" => T,
],
sitename="FHist.jl",
authors="Jerry Ling"
Expand Down
40 changes: 21 additions & 19 deletions docs/src/notebooks/makie_plotting.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
### A Pluto.jl notebook ###
# v0.19.32
# v0.19.40

using Markdown
using InteractiveUtils
Expand Down Expand Up @@ -29,9 +29,9 @@ Let's generate three dummy histograms sampled from three different distributions

# ╔═╡ 8491f5c3-93b6-4670-8f6e-0d08d7afbf75
begin
h1 = Hist1D(randn(10^3), -2:0.3:2)
h2 = Hist1D(randn(10^4), -2:0.3:2)
h3 = Hist1D(randn(10^3) .+ 0.5, -2:0.3:2)
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

# ╔═╡ da61f742-b530-4aa4-9253-a23f6731f892
Expand All @@ -43,7 +43,7 @@ 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 = stairs(fig[1, 2], h1, label = "stairs(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])
Expand All @@ -59,7 +59,7 @@ We provide a `statbox!()` function to add such box:

# ╔═╡ 99f8bcde-b823-4c5b-8820-22c403c21d6b
begin
f_s = stairs(h1)
f_s = stephist(h1)
statbox!(f_s, h1)
f_s
end
Expand All @@ -71,10 +71,12 @@ md"""

# ╔═╡ f5630dae-870e-45e8-995a-db946687031b
begin
fig2d = Figure()
h2d = Hist2D((randn(10000), randn(10000)))
p2d = plot(h2d)
statbox!(p2d, h2d)
p2d
plot(fig2d[1,2], h2d)
statbox!(fig2d, h2d; position=(1,1))
Colorbar(fig2d[1,3])
fig2d
end

# ╔═╡ d549a735-12a4-443a-98c7-be5cce4e6789
Expand All @@ -85,18 +87,18 @@ You can freely combine these by using the bang `!` version to plot things on top
# ╔═╡ 12b44438-2af4-4ca5-8569-57de2cadc607
begin
pos_h2 = restrict(h2, 0, Inf)
hist(pos_h2;
hist(pos_h2;
label = "fake bkg",
axis=(
yticks=10.0 .^ (-1:1:3),
yminorticks=IntervalsBetween(9),
limits=(nothing, nothing, 0.1, nothing),
yminorticks=IntervalsBetween(5),
yminorticksvisible = true,
yscale=Makie.pseudolog10
yscale=log10
)
)

errorbars!(pos_h2; whiskerwidth=7)
stairs!(h3; color=:red, label = "fake sig")
stephist!(h3; color=:red, label = "fake sig")
axislegend()
current_figure()
end
Expand All @@ -110,7 +112,7 @@ We also have a recipe for that:

# ╔═╡ 70a5ba34-53c5-4e12-93b9-49eace436524
with_theme(ATLASTHEME) do
f, a, p = stackedhist([h2, h2, h1 ])
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"
Expand All @@ -129,10 +131,10 @@ Finally, we have a recipe for ratio plot which is argubaly useful for the bottom
"""

# ╔═╡ b1188446-d16b-4e0c-93be-c5e3d0de379c
with_theme(ATLASTHEME) do
f_ratio, a, p = stairs(h1; label="h1")
begin
f_ratio, a, p = stephist(h1; label="h1")
errorbars!(a, h1)
stairs!(a, h3; label="h3")
stephist!(a, h3; label="h3")
errorbars!(a, h3)

axislegend()
Expand Down Expand Up @@ -192,7 +194,7 @@ end
# ╠═c774440d-c7c1-4b75-b115-64038992174d
# ╠═f5630dae-870e-45e8-995a-db946687031b
# ╠═d549a735-12a4-443a-98c7-be5cce4e6789
# ╟─12b44438-2af4-4ca5-8569-57de2cadc607
# ╠═12b44438-2af4-4ca5-8569-57de2cadc607
# ╟─386b8f0e-ad21-4af3-b2b6-b3412f44315c
# ╠═70a5ba34-53c5-4e12-93b9-49eace436524
# ╠═089fb6a1-3f2a-45f4-b4bf-4013dee3a6da
Expand Down
6 changes: 3 additions & 3 deletions docs/src/notebooks/plots_plotting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ Let's generate three dummy histograms sampled from three different distributions

# ╔═╡ 316167ab-4d59-4978-a3b0-539e23c1eaaa
begin
h1 = Hist1D(randn(10^3), -2:0.3:2)
h2 = Hist1D(randn(10^4), -2:0.3:2)
h3 = Hist1D(randn(10^3) .+ 0.5, -2:0.3:2)
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

# ╔═╡ 2d857d08-f9c2-4a60-86dd-2afbd3b599f6
Expand Down
84 changes: 84 additions & 0 deletions docs/src/start.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Quick Start

This section describes the most important surface level API: creating histogram.
```@contents
Pages = ["start.md"]
```

```@setup fh
using FHist
```

There are two possible ways to make a histogram:
- make an empty histogram to be filled later (via [`atomic_push!`](@ref))
- make a filled histogram given data

We call the first one "constructor like" use case and the second one "fit like" use case (as in "fit
data to a histogram").

Each of the two options imply a set of options that can go with them. The two sets of options
have some overlap, e.g. `binedges`, `overflow`; but there are also options only make sense of one of
them, e.g., `nbins` only works in the "fit like" use case.

## Make an empty histogram

The minimal information needed is `binedges`:
```@example fh
h1 = Hist1D(; binedges = 1:10)
```

You can provide more if you have them available (for example, when you're creating
histogram from another data source):

```@example fh
h2 = Hist1D(; binedges = 1:10, bincounts = collect(1:9))
```

!!! note "Default / infer strategy for empty histogram"

To see the full list of keyword arguments as well as how they are inferred, see [`Hist1D`](@ref). To
summarize in words:

1. `counttype` defaults to `Float64` because `maxintfloat(Float64) ≈ 9e15`
2. `binedges` must be provided by user
3. `bincounts` defaults to all zero, with `eltype == counttype` and appropriate shape
4. `sumw2` defaults to all zero with appropriate shape
5. `nentries` defaults to 0
6. `overflow` defaults to `false`



## Make a filled histogram given data

The minimal information needed is `data`, which is a __positional__ argument:
```@example fh
h3 = Hist1D(randn(2000))
```

You can provide more (in keyword arguments) if you want granular control over the binning behavior (e.g. number of bins,
the exact bins to use):

```@example fh
h4 = Hist1D(randn(2000); nbins=4)
```

!!! warning
`nbins` is not strictly enforced, use `binedges` if you need exact control.

We can do non-uniform binning for example:
```@example fh
h5 = Hist1D(randn(2000); binedges = [0, 0.5, 0.8, 0.9, 1.0])
```

!!! note "Default / infer strategy for filled histogram with data"

To see the full list of keyword arguments as well as how they are inferred, see [`Hist1D`](@ref). To
summarize in words:

1. data `array` must be provided by the user
2. `counttype` defaults to `Float64` because `maxintfloat(Float64) ≈ 9e15`
3. `nbins` defaults to sturges approximation
4. `binedges` defaults to uniform binning given `nbins`
5. `weights` defaults to all unity (i.e. not weighted)
6. `overflow` defaults `false`

28 changes: 28 additions & 0 deletions docs/src/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
## Basic attributes

- [`binedges`](@ref): Get the bin edges of the histogram, for 1D histogram, it returns just a vector. For others, it returns a tuple of vectors. If you need a tuple of vectors, use h.binedges at your own risk.
- [`bincounts`](@ref): Get the bin counts (weights) of the histogram.
- [`sumw2`](@ref): Get the sum of weights squared of the histogram, it has the same shape as `bincounts(h)`.
- [`nentries`](@ref): Get the number of times a histogram is filled (`push!`ed)

## Derived attributes
- [`bincenters`](@ref): Get the bin centers of the histogram, for 1D histogram, it returns just a vector. For others, it returns a tuple of vectors.
- [`binerrors`](@ref): Get the error of each bin of the histogram. By default it calls `sqrt()` on
each entry of `sumw2` as an approximation.
- `mean`, `std`, `median`, `quantile`, weighted by histogram `bincounts()`.
```@docs
integral
```

## Manipulating histogram

This section includes adding data to histogram, and other operations that return a histogram (may
with reduced dimensionality)
```@docs
atomic_push!
cumulative
rebin
restrict
profile
project
```
Loading

6 comments on commit ced8d83

@Moelf
Copy link
Owner Author

@Moelf Moelf commented on ced8d83 Mar 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/103452

Tip: Release Notes

Did you know you can add release notes too? Just add markdown formatted text underneath the comment after the text
"Release notes:" and it will be added to the registry PR, and if TagBot is installed it will also be added to the
release that TagBot creates. i.e.

@JuliaRegistrator register

Release notes:

## Breaking changes

- blah

To add them here just re-invoke and the PR will be updated.

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.11.0 -m "<description of version>" ced8d836077c9264f5c20cd7524d34f31caac8e7
git push origin v0.11.0

@Moelf
Copy link
Owner Author

@Moelf Moelf commented on ced8d83 Mar 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes:

Breaking changes

  • Histogram constructors are redesigned: Hist1D(; <kwargs...>) is used for creating empty histograms, and Hist1D(<args>...; ...) is used for one-shot histogram making
  • Histograms now only have 1 parametric type, making it easy to embed them into user structs
  • Various Makie recipe fix

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request updated: JuliaRegistries/General/103452

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.11.0 -m "<description of version>" ced8d836077c9264f5c20cd7524d34f31caac8e7
git push origin v0.11.0

@Moelf
Copy link
Owner Author

@Moelf Moelf commented on ced8d83 Mar 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes:

Breaking changes

  • Histogram constructors are redesigned: Hist1D(; <kwargs...>) is used for creating empty histograms, and Hist1D(<args>...; ...) is used for one-shot histogram making
  • Histograms now only have 1 parametric type, making it easy to embed them into user structs

Improvements

  • fixed appened!()
  • added new Quick Start documentation
  • improved makie plotting examples
  • Various Makie recipe fix

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request updated: JuliaRegistries/General/103452

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.11.0 -m "<description of version>" ced8d836077c9264f5c20cd7524d34f31caac8e7
git push origin v0.11.0

Please sign in to comment.