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

Rewrite get_pe_res: numerical FWHM calculation #137

Merged
merged 3 commits into from
Mar 19, 2025
Merged
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
38 changes: 34 additions & 4 deletions src/sipmfit.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
function fit_sipm_spectrum(pe_cal::Vector{<:Real}, min_pe::Real=0.5, max_pe::Real=3.5;
n_mixtures::Int=ceil(Int, (max_pe - min_pe) * 4), nIter::Int=25, nInit::Int=50,
method::Symbol=:kmeans, kind=:diag, Δpe_peak_assignment::Real=0.3, f_uncal::Function=identity, uncertainty::Bool=true)

# first filter peak positions out of amplitude vector
amps_fit = filter(in(min_pe..max_pe), pe_cal)

Expand Down Expand Up @@ -106,9 +105,34 @@
get_pe_pos = pe -> let sel = in.(μ, (-Δpe_peak_assignment..Δpe_peak_assignment) .+ pe)
dot(view(μ, sel), view(w, sel)) / sum(view(w, sel))
end

# get pe resolution (FWHM)
get_pe_res = pe -> let sel = in.(μ, (-Δpe_peak_assignment..Δpe_peak_assignment) .+ pe)
sqrt(dot(view(σ, sel).^2, view(w, sel).^2))
end
model_parameters = [

Check warning on line 111 in src/sipmfit.jl

View check run for this annotation

Codecov / codecov/patch

src/sipmfit.jl#L111

Added line #L111 was not covered by tests
view(μ_ml, sel),
view(σ_ml, sel),
view(w_ml, sel)
]

# Find maximum of PDF in the expected range, step size depends on the maximum variance of the single gaussians
range_steps = maximum(getfield.(view(μ, sel), :err)) / 100
x_max = 0.0
f_max = 0.0

Check warning on line 120 in src/sipmfit.jl

View check run for this annotation

Codecov / codecov/patch

src/sipmfit.jl#L118-L120

Added lines #L118 - L120 were not covered by tests
# Search range depends on the selection of gaussians
for x_i in minimum(view(μ_ml, sel)):range_steps:maximum(view(μ_ml, sel))
if _gmm_pdf(x_i, model_parameters) > f_max
x_max = x_i
f_max = _gmm_pdf(x_i, model_parameters)

Check warning on line 125 in src/sipmfit.jl

View check run for this annotation

Codecov / codecov/patch

src/sipmfit.jl#L122-L125

Added lines #L122 - L125 were not covered by tests
end
end
f_half_max = f_max / 2

Check warning on line 128 in src/sipmfit.jl

View check run for this annotation

Codecov / codecov/patch

src/sipmfit.jl#L127-L128

Added lines #L127 - L128 were not covered by tests

# Find all the points where the half max is reached
roots = find_zeros(x -> f_half_max - _gmm_pdf(x, model_parameters), 0, 5)
return maximum(roots) - minimum(roots)

Check warning on line 132 in src/sipmfit.jl

View check run for this annotation

Codecov / codecov/patch

src/sipmfit.jl#L131-L132

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


n_pos_mixtures = [count(in.(μ, (-Δpe_peak_assignment..Δpe_peak_assignment) .+ pe)) for pe in pes]

pe_pos = get_pe_pos.(pes)
Expand Down Expand Up @@ -170,4 +194,10 @@
xlogy.(bin_counts, binned_density)
)
return f_loglike
end
end

function _gmm_pdf(x::Real, μ::AbstractVector{<:Real}, σ::AbstractVector{<:Real}, w::AbstractVector{<:Real})
return sum(@. w * exp(-0.5 * ((x - μ) / σ)^2) / (σ * sqrt(2π)))

Check warning on line 200 in src/sipmfit.jl

View check run for this annotation

Codecov / codecov/patch

src/sipmfit.jl#L199-L200

Added lines #L199 - L200 were not covered by tests
end

_gmm_pdf(x::Real, V::Vector{<:AbstractVector{<:Real}}) = _gmm_pdf(x, V...)
Loading