Skip to content

Commit ce81f77

Browse files
authored
Merge pull request #137 from benedikt-nagler/dev
Rewrite `get_pe_res`: numerical FWHM calculation
2 parents 609fb3b + cb331e9 commit ce81f77

File tree

1 file changed

+34
-4
lines changed

1 file changed

+34
-4
lines changed

src/sipmfit.jl

+34-4
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ Fit a Gaussian Mixture Model to the given pe calibration data and return the fit
2626
function fit_sipm_spectrum(pe_cal::Vector{<:Real}, min_pe::Real=0.5, max_pe::Real=3.5;
2727
n_mixtures::Int=ceil(Int, (max_pe - min_pe) * 4), nIter::Int=25, nInit::Int=50,
2828
method::Symbol=:kmeans, kind=:diag, Δpe_peak_assignment::Real=0.3, f_uncal::Function=identity, uncertainty::Bool=true)
29-
3029
# first filter peak positions out of amplitude vector
3130
amps_fit = filter(in(min_pe..max_pe), pe_cal)
3231

@@ -106,9 +105,34 @@ function fit_sipm_spectrum(pe_cal::Vector{<:Real}, min_pe::Real=0.5, max_pe::Rea
106105
get_pe_pos = pe -> let sel = in.(μ, (-Δpe_peak_assignment..Δpe_peak_assignment) .+ pe)
107106
dot(view(μ, sel), view(w, sel)) / sum(view(w, sel))
108107
end
108+
109+
# get pe resolution (FWHM)
109110
get_pe_res = pe -> let sel = in.(μ, (-Δpe_peak_assignment..Δpe_peak_assignment) .+ pe)
110-
sqrt(dot(view(σ, sel).^2, view(w, sel).^2))
111-
end
111+
model_parameters = [
112+
view(μ_ml, sel),
113+
view(σ_ml, sel),
114+
view(w_ml, sel)
115+
]
116+
117+
# Find maximum of PDF in the expected range, step size depends on the maximum variance of the single gaussians
118+
range_steps = maximum(getfield.(view(μ, sel), :err)) / 100
119+
x_max = 0.0
120+
f_max = 0.0
121+
# Search range depends on the selection of gaussians
122+
for x_i in minimum(view(μ_ml, sel)):range_steps:maximum(view(μ_ml, sel))
123+
if _gmm_pdf(x_i, model_parameters) > f_max
124+
x_max = x_i
125+
f_max = _gmm_pdf(x_i, model_parameters)
126+
end
127+
end
128+
f_half_max = f_max / 2
129+
130+
# Find all the points where the half max is reached
131+
roots = find_zeros(x -> f_half_max - _gmm_pdf(x, model_parameters), 0, 5)
132+
return maximum(roots) - minimum(roots)
133+
end
134+
135+
112136
n_pos_mixtures = [count(in.(μ, (-Δpe_peak_assignment..Δpe_peak_assignment) .+ pe)) for pe in pes]
113137

114138
pe_pos = get_pe_pos.(pes)
@@ -170,4 +194,10 @@ function _gmm_binned_loglike_func(
170194
xlogy.(bin_counts, binned_density)
171195
)
172196
return f_loglike
173-
end
197+
end
198+
199+
function _gmm_pdf(x::Real, μ::AbstractVector{<:Real}, σ::AbstractVector{<:Real}, w::AbstractVector{<:Real})
200+
return sum(@. w * exp(-0.5 * ((x - μ) / σ)^2) /* sqrt(2π)))
201+
end
202+
203+
_gmm_pdf(x::Real, V::Vector{<:AbstractVector{<:Real}}) = _gmm_pdf(x, V...)

0 commit comments

Comments
 (0)