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

[WIP] Add advanced plotting recipies #127

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
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
131 changes: 131 additions & 0 deletions ext/FHistPlotsExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,136 @@
z := (surf = bincounts(h), )
()
end


"""
WithData(factor, support)
WithData(bins, N::Int = 1)
WithData(h::Hist1D)

A struct that helps plotting a model curve on top of the binned data with correct normalization.
If the model is normalized to 1, the scaling factor accounts for the bin width and number of entries in the histogram.
For a model curve normalized to the total number of events, default option `N=1` is provided.

# Examples:
```julia
julia> data = randn(1000);
julia> h = Hist1D(data; binedges=range(-5,5, 100));
julia> model_fun(x) = length(data) * exp(-x^2 / 2) / sqrt(2π);
julia> #
julia> let
plot(h, seriestype=:stepbins)
plot!(model_fun, WithData(h.binedges[1]), lw=2)
end # displays the plot
```
"""
struct WithData
factor::Float64
support::Tuple{Float64, Float64}
end
WithData(bins, N::Int = 1) = WithData(N * diff(bins)[1], (bins[1], bins[end]))
WithData(h::Hist1D) = WithData(h.binedges[1], Int(sum(h.bincounts)))

Check warning on line 53 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L52-L53

Added lines #L52 - L53 were not covered by tests
#
@recipe function f(model_fun::Function, scale::WithData; n_points = 100)
normalized_function(x) = model_fun(x) * scale.factor
xv = range(scale.support..., n_points)
return (normalized_function, xv)

Check warning on line 58 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L55-L58

Added lines #L55 - L58 were not covered by tests
end


"""
curvedfitwithpulls(h, best_model;, data_scale_curve = true)

Plots the histogram with Poisson uncertainties, the model by a curve, and a pull distribution.

# Example
```julia
julia> h = Hist1D(data; binedges=1.1:0.1:2.5))
julia> curvedfitwithpulls(h0, best_model, xlab = "X-axis", ylab = "Y-axis")
````

The recipe does something along the lines of the following code:
```julia
WD = data_scale_curve ? WithData(h) : WithData(h.binedges[1], 1)

# pulls
mismatches = h0.bincounts - best_model.(bincenters(h0)) .* WD.factor
hpull = Hist1D(; binedges, bincounts = mismatches ./ binerrors(h0))
dx = (step(binedges)) / 2

# plotting
plot(layout = grid(2, 1, heights = (0.8, 0.2)), link = :x)
plot!(sp = 1, best_model, WD, lw = 2, lc = :cornflowerblue)
scatter!(sp = 1, bincenters(h0), h0.bincounts, yerror = binerrors(h0), xerror = dx)
scatter!(sp = 2, bincenters(hpull), hpull.bincounts, yerror = 1, xerror = dx)
```
"""
@userplot CurvedFitWithPulls

@recipe function f(h::CurvedFitWithPulls; data_scale_curve = true)
if length(h.args) != 2 || !(typeof(h.args[1]) <: Hist1D) ||

Check warning on line 92 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L91-L92

Added lines #L91 - L92 were not covered by tests
!(typeof(h.args[2]) <: Function)
error("Marginal CurvedFitWithPulls should be given a histogram and a function. Got: $(typeof(h.args))")

Check warning on line 94 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L94

Added line #L94 was not covered by tests
end
h, model = h.args
binedges = h.binedges[1]
WD = data_scale_curve ? WithData(h) : WithData(binedges, 1)

Check warning on line 98 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L96-L98

Added lines #L96 - L98 were not covered by tests

mismatches = h.bincounts - best_model.(bincenters(h)) .* WD.factor
hpull = Hist1D(; binedges, bincounts = mismatches ./ binerrors(h))
dx = (binedges[2] - binedges[1]) / 2

Check warning on line 102 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L100-L102

Added lines #L100 - L102 were not covered by tests

# set up the subplots
legend := false
link := :x
framestyle := :box
grid := false
layout := grid(2, 1, heights = (0.8, 0.2))

Check warning on line 109 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L105-L109

Added lines #L105 - L109 were not covered by tests

xlimits := (WD.support)

Check warning on line 111 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L111

Added line #L111 was not covered by tests

# model curve
@series begin
subplot := 1
linewidth := 1.5
best_model, WD

Check warning on line 117 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L114-L117

Added lines #L114 - L117 were not covered by tests
end
markersize := 1.5

Check warning on line 119 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L119

Added line #L119 was not covered by tests

# data
@series begin
xticks := false
xguide := ""
ylimits := (0, :auto)
bottom_margin := -4.5mm
markercolor --> :black
seriestype := :scatter
subplot := 1
yerror := binerrors(h0)
xerror := dx
bincenters(h), h.bincounts

Check warning on line 132 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L122-L132

Added lines #L122 - L132 were not covered by tests
end

# pull
@series begin
linecolor := :gray
subplot := 2
seriestype := :hline
[0.0]

Check warning on line 140 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L136-L140

Added lines #L136 - L140 were not covered by tests
end
@series begin
bottom_margin := 0mm
markercolor --> :black
yguide := "Pull"
guidefontvalign := :center
seriestype := :scatter
ylims := (-7, 7)
subplot := 2
yerror := 1.0
xerror := dx
bincenters(hpull), hpull.bincounts

Check warning on line 152 in ext/FHistPlotsExt.jl

View check run for this annotation

Codecov / codecov/patch

ext/FHistPlotsExt.jl#L142-L152

Added lines #L142 - L152 were not covered by tests
end
end

end

Loading