-
Notifications
You must be signed in to change notification settings - Fork 10
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
Generic simple_calibration #108
base: main
Are you sure you want to change the base?
Changes from 3 commits
a0b628f
fa21052
1639f38
888996b
421e2c3
692c1de
b8dda3f
8e924d9
13a85f9
4851690
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -490,6 +490,41 @@ end | |
end | ||
end | ||
|
||
@recipe function f(report::NamedTuple{(:h_calsimple, :h_uncal, :c, :peak_guess, :peakhists, :peakstats)}; cal=true) | ||
ylabel := "Counts" | ||
legend := :topright | ||
yscale := :log10 | ||
fill := false | ||
if cal | ||
h = LinearAlgebra.normalize(report.h_calsimple, mode = :density) | ||
xlabel := "Energy (keV)" | ||
xlims := (0, 3000) | ||
xticks := (0:500:3000, ["$i" for i in 0:500:3000]) | ||
ylims := (0.2, maximum(h.weights)*1.1) | ||
peak_guess = ustrip(report.c * report.peak_guess) | ||
else | ||
h = LinearAlgebra.normalize(report.h_uncal, mode = :density) | ||
xlabel := "Energy (ADC)" | ||
xlims := (0, 1.2*report.peak_guess) | ||
xticks := (0:3000:1.2*report.peak_guess, ["$i" for i in 0:3000:1.2*report.peak_guess]) | ||
ylims := (0.2, maximum(h.weights)*1.1) | ||
peak_guess = report.peak_guess | ||
end | ||
@series begin | ||
seriestype := :stepbins | ||
label := "Energy" | ||
h | ||
end | ||
y_vline = 0.2:1:maximum(h.weights)*1.1 | ||
@series begin | ||
seriestype := :line | ||
label := "Peak guess"#: $(round(peak_guess, digits = 1))" | ||
color := :red2 | ||
linewidth := 1.5 | ||
fill(peak_guess, length(y_vline)), y_vline | ||
end | ||
end | ||
|
||
@recipe function f(report::NamedTuple{(:peakpos, :peakpos_cal, :h_uncal, :h_calsimple)}; cal=true) | ||
legend := :topright | ||
size := (1000, 600) | ||
|
@@ -820,7 +855,8 @@ end | |
if plot_ribbon | ||
ribbon := uncertainty.(report.f_fit.(0:1:1.2*value(maximum(report.x)))) | ||
end | ||
0:1:1.2*value(maximum(report.x)), value.(report.f_fit.(0:1:1.2*value(maximum(report.x)))) | ||
xstep = value(maximum(report.x))/100 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this also work for the |
||
0:xstep:1.2*value(maximum(report.x)), value.(report.f_fit.(0:xstep:1.2*value(maximum(report.x)))) | ||
end | ||
@series begin | ||
seriestype := :scatter | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,20 +18,22 @@ Returns | |
function simple_calibration end | ||
export simple_calibration | ||
|
||
function simple_calibration(e_uncal::Vector{<:Real}, th228_lines::Vector{<:Unitful.Energy{<:Real}}, window_sizes::Vector{<:Tuple{Unitful.Energy{<:Real}, Unitful.Energy{<:Real}}},; kwargs...) | ||
function simple_calibration(e_uncal::Vector{<:Real}, gamma_lines::Vector{<:Unitful.Energy{<:Real}}, window_sizes::Vector{<:Tuple{Unitful.Energy{<:Real}, Unitful.Energy{<:Real}}},; kwargs...) | ||
# remove calib type from kwargs | ||
@assert haskey(kwargs, :calib_type) "Calibration type not specified" | ||
calib_type = kwargs[:calib_type] | ||
# remove :calib_type from kwargs | ||
kwargs = pairs(NamedTuple(filter(k -> !(:calib_type in k), kwargs))) | ||
if calib_type == :th228 | ||
@debug "Use simple calibration for Th228 lines" | ||
return simple_calibration_th228(e_uncal, th228_lines, window_sizes,; kwargs...) | ||
return simple_calibration_th228(e_uncal, gamma_lines, window_sizes,; kwargs...) | ||
elseif calib_type == :gamma | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why not call this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This works also for any calibration data. I think we should have only 1 generic |
||
return simple_calibration_gamma(e_uncal, gamma_lines, window_sizes,; kwargs...) | ||
else | ||
error("Calibration type not supported") | ||
end | ||
end | ||
simple_calibration(e_uncal::Vector{<:Real}, th228_lines::Vector{<:Unitful.Energy{<:Real}}, left_window_sizes::Vector{<:Unitful.Energy{<:Real}}, right_window_sizes::Vector{<:Unitful.Energy{<:Real}}; kwargs...) = simple_calibration(e_uncal, th228_lines, [(l,r) for (l,r) in zip(left_window_sizes, right_window_sizes)],; kwargs...) | ||
simple_calibration(e_uncal::Vector{<:Real}, gamma_lines::Vector{<:Unitful.Energy{<:Real}}, left_window_sizes::Vector{<:Unitful.Energy{<:Real}}, right_window_sizes::Vector{<:Unitful.Energy{<:Real}}; kwargs...) = simple_calibration(e_uncal, gamma_lines, [(l,r) for (l,r) in zip(left_window_sizes, right_window_sizes)],; kwargs...) | ||
|
||
|
||
function simple_calibration_th228(e_uncal::Vector{<:Real}, th228_lines::Vector{<:Unitful.Energy{<:Real}}, window_sizes::Vector{<:Tuple{Unitful.Energy{<:Real}, Unitful.Energy{<:Real}}},; n_bins::Int=15000, quantile_perc::Float64=NaN, binning_peak_window::Unitful.Energy{<:Real}=10.0u"keV") | ||
|
@@ -81,7 +83,60 @@ function simple_calibration_th228(e_uncal::Vector{<:Real}, th228_lines::Vector{< | |
return result, report | ||
end | ||
|
||
|
||
""" | ||
simple_calibration_gamma(e_uncal::Array, gamma_lines::Array, window_size::Float64=25.0, n_bins::Int=15000, quantile_perc::Float64=NaN, binning_peak_window::Float64=10.0, peak_quantile::ClosedInterval{<:Real} = 0.5..1.0) | ||
Perform a simple calibration for the uncalibrated energy array `e_uncal` | ||
* Find peaks within peak_quantile::ClosedInterval{<:Real} = 0.5..1.0 of the data | ||
* Estimate the calibration constant `c` by dividing the maximum gamma line energy by the peak guess | ||
* Return peakstats and peakhists of gamma lines for further calibration | ||
""" | ||
fhagemann marked this conversation as resolved.
Show resolved
Hide resolved
|
||
function simple_calibration_gamma(e_uncal::Vector{<:Real}, gamma_lines::Vector{<:Unitful.Energy{<:Real}}, window_sizes::Vector{<:Tuple{Unitful.Energy{<:Real}, Unitful.Energy{<:Real}}},; n_bins::Int=15000, quantile_perc::Float64=NaN, binning_peak_window::Unitful.Energy{<:Real}=10.0u"keV", peak_quantile::ClosedInterval{<:Real} = 0.5..1.0) | ||
e_min = quantile(e_uncal, leftendpoint(peak_quantile)) | ||
e_max = quantile(e_uncal, rightendpoint(peak_quantile)) | ||
# initial binning | ||
bin_width = get_friedman_diaconis_bin_width(filter(in(e_min..e_max), e_uncal)) | ||
# create initial peak search histogram | ||
h_uncal = fit(Histogram, e_uncal, 0:bin_width:maximum(e_uncal)) | ||
peak_guess, peak_idx = if isnan(quantile_perc) | ||
h_peaksearch = fit(Histogram, e_uncal, e_min:bin_width:e_max) | ||
# search all possible peak candidates | ||
h_decon, peakpos = RadiationSpectra.peakfinder(h_peaksearch, σ=2.0, backgroundRemove=true, threshold=10) | ||
# find the most prominent peak in the deconvoluted histogram | ||
peakpos_idxs = StatsBase.binindex.(Ref(h_decon), peakpos) | ||
cts_peakpos = h_decon.weights[peakpos_idxs] | ||
peakpos[argmax(cts_peakpos)], argmax(cts_peakpos) | ||
else | ||
quantile(e_uncal, quantile_perc), length(gamma_lines) | ||
end | ||
@info "Identified most prominent peak (peak $(peak_idx), $(gamma_lines[peak_idx])). Peak guess: $peak_guess" | ||
# get calibration constant for simple calibration | ||
c = gamma_lines[peak_idx] / peak_guess | ||
e_simple = e_uncal .* c | ||
e_unit = u"keV" | ||
fhagemann marked this conversation as resolved.
Show resolved
Hide resolved
|
||
# get peakhists and peakstats | ||
peakhists, peakstats, h_calsimple, bin_widths = get_peakhists_th228(e_simple, gamma_lines, window_sizes; binning_peak_window=binning_peak_window, e_unit=e_unit) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes it does. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It makes sense to rename it, but maybe this could go along then with a PR onto the dataflow where we do a search and replace for these functions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree. I can take care of this beginning of next year. In that context, I'd suggest to change the julia energy-calibration metadata as well:
OR
I prefer option 1, because this allows you to switch easily back and fourth between different calibration sources. |
||
|
||
result = ( | ||
h_calsimple = h_calsimple, | ||
h_uncal = h_uncal, | ||
c = c, | ||
unit = e_unit, | ||
bin_width = median(bin_widths), | ||
peak_guess = peak_guess, | ||
peakbinwidths = bin_widths, | ||
peakhists = peakhists, | ||
peakstats = peakstats | ||
) | ||
report = ( | ||
h_calsimple = result.h_calsimple, | ||
h_uncal = result.h_uncal, | ||
c = result.c, | ||
peak_guess = result.peak_guess, | ||
peakhists = result.peakhists, | ||
peakstats = result.peakstats | ||
) | ||
return result, report | ||
end | ||
""" | ||
get_peakhists_th228(e::Array, th228_lines::Array, window_sizes::Array, e_unit::String="keV", proxy_binning_peak::Float64=2103.5, proxy_binning_peak_window::Float64=10.0) | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't understand why this is a new recipe. Was this not here already before?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is almost a duplicate of the existing recipe. However, the old one has some stuff hardcoded, e.g. "FEP" in the plot label. I didn't want to mess with the existing one, since we're int he middle of the processing.